Contents


Web services hints and tips

JAX-RPC versus JAX-WS, Part 2

A look at the differences in data mapping

Comments

Content series:

This content is part # of # in the series: Web services hints and tips

Stay tuned for additional content in this series.

This content is part of the series:Web services hints and tips

Stay tuned for additional content in this series.

While some aspects of JAX-WS 2.0 are merely evolutionary to JAX-RPC 1.1, other parts are revolutionary. For example, JAX-WS does not provide mapping between XML schema and Java, a major feature of JAX-RPC 1.1. Instead, JAX-WS uses another JCP-defined technology, JAXB (the Java Architecture for XML Binding) 2.0, to do its data mapping for it. JAX-WS simply represents the invocation model for Web services. It no longer concerns itself with the Java Beans that represent application data; it only focuses on delivering them to the target Web service. Here, we'll compare JAX-RPC 1.1 and the JAXB 2.0 mappings.

Mapping XML schema to Java

Mapping XML names to Java names in JAX-RPC and JAX-WS/JAXB are essentially the same, while mapping simple types has some slight differences. Table 1 shows these differences, which may appear significant; however, except for date/time types, they're the least-used XML simple types.

Table 1. Mapping differences between JAX-RPC 1.1 and JAXB 2.0 for XML simple types
TypeJAX-RPC 1.1JAXB 2.0
xsd:anySimpleTypejava.lang.Stringjava.lang.Object
xsd:durationjava.lang.Stringjavax.xml.datatype.Duration (new type)
xsd:dateTimejava.util.Calendarjavax.xml.datatype.XMLGregorianCalendar (new type)
xsd:timejava.util.Calendarjavax.xml.datatype.XMLGregorianCalendar
xsd:datejava.util.Calendarjavax.xml.datatype.XMLGregorianCalendar
xsd:gYearMonthjava.lang.Stringjavax.xml.datatype.XMLGregorianCalendar
xsd:gYearjava.lang.Stringjavax.xml.datatype.XMLGregorianCalendar
xsd:gMonthDayjava.lang.Stringjavax.xml.datatype.XMLGregorianCalendar
xsd:gMonthjava.lang.Stringjavax.xml.datatype.XMLGregorianCalendar
xsd:gDayjava.lang.Stringjavax.xml.datatype.XMLGregorianCalendar
xsd:anyURIjava.net.URIjava.lang.String
xsd:NMTOKENSjava.lang.String[]java.util.List<java.lang.String>
xsd:IDREFjava.lang.Stringjava.lang.Object
xsd:IDREFSjava.lang.String[]java.util.List<java.lang.Object>
xsd:ENTITYnot supportedjava.lang.String
xsd:ENTITIESnot supportedjava.util.List<java.lang.String>

The pure Java aspects of the simple type mappings are nearly the same between JAX-RPC and JAXB, but the JAXB mappings also use the new Java annotation feature. See Listings 1 through 3 for some examples of simple type mappings.

Listing 1. XML complexType elements and attributes
  <xsd:sequence>
    <xsd:element name="intField" type="xsd:int"/>
    <xsd:element name="intMinField" type="xsd:int" minOccurs="0"/>
    <xsd:element name="intNilField" type="xsd:int" nillable="true"/>
    <xsd:element name="stringField" type="xsd:string"/>
    <xsd:element name="stringMinField" type="xsd:string" minOccurs="0"/>
    <xsd:element name="stringNilField" type="xsd:string" nillable="true"/>
  </xsd:sequence>
  <xsd:attribute name="intAttr" type="xsd:int"/>
  <xsd:attribute name="intAttrReq" type="xsd:int" use="required"/>
Listing 2. Mapping to Java Bean properties via JAX-RPC 1.1
	private int intField;
    private Integer intMinField;
    private Integer intNilField;
    private String stringField;
    private String stringMinField;
    private String stringNilField;
    private Integer intAtt;
    private int intAttReq;
Listing 3. Mapping to Java Bean properties via JAXB 2.0
  protected int intField;
  protected Integer intMinField;

    @XmlElement(required = true, type = Integer.class, nillable = true)
    protected Integer intNilField;

    @XmlElement(required = true)
    protected String stringField;

    protected String stringMinField;

    @XmlElement(required = true, nillable = true)
    protected String stringNilField;

    @XmlAttribute
    protected Integer intAtt;

    @XmlAttribute(required = true)
    protected int intAttReq;

In a JAX-RPC 1.1-generated Java Bean, you cannot tell the difference between:

  • An element field and an attribute field
  • A field mapped from minOccurs="0" type="xsd:int" and a field mapped from nillable="true" type="xsd:int"
  • A field mapped from type="xsd:string" and type="xsd:string" minOccurs="0"

But now you can, thanks to JAXB's use of new Java annotations. The @XmlElement and @XmlAttribute annotations have several parameters. The ones pertinent to this article include:

  • Required: Must the element exist? For example, is minOccurs something other than one?
  • Nillable: Does the field contain the nillable="true" attribute?

Mapping arrays

Mapping arrays from XML to Java differs between JAX-RPC and JAXB because JAXB uses the new generic Java feature, as Listings 4 through 6 show.

Listing 4. XML array
  <xsd:element name="intArrayField" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
Listing 5. Mapping to Java Bean properties via JAX-RPC 1.1
  private int[] intArrayField;
    public int[] getIntArrayField() {...}
    public void setIntArrayField(int[] intArrayField) {...}
    public int getIntArrayField(int i) {...}
    public void setIntArrayField(int i, int value) {...}
Listing 6. Mapping to Java Bean properties via JAXB 2.0
  @XmlElement(type = Integer.class)
    protected List<Integer> intArrayField;
    public List<Integer> getIntArrayField() {...}

Notice the differences in the accessor methods. The JAX-RPC mapping follows the strict definition of Java Bean array accessors. The JAXB mapping does not map to an array, so it slightly differs. getIntArrayField returns a reference, not just a snapshot, to the live list. Therefore, any modification you make to the returned list will be present inside the property. This is why no set method exists for 'array' properties.

Mapping complex types

Mapping a complexType is nearly the same between JAX-RPC and JAXB, except the fields are private in JAX-RPC and protected in JAXB, and the JAXB mapping adds annotations describing the field order. See Listings 7 through 9 for an example and comparisons between the two mappings.

Listing 7. XML schema complexType
  <xsd:element name="Phone" type="tns:Phone"/>
  <xsd:complexType name="Phone">
    <xsd:sequence>
      <xsd:element name="areaCode" type="xsd:string"/>
      <xsd:element name="exchange" type="xsd:string"/>
      <xsd:element name="number" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
Listing 8. JAX-RPC 1.1 mapping of complexType
  public class Phone {
    private String areaCode;
    private String exchange;
    private String number;

    ...
}
Listing 9. JAXB 2.0 mapping of complexType
  @XmlType(name = "Phone", propOrder = {
    "areaCode",
    "exchange",
    "number"
})
public class Phone {

    @XmlElement(required = true)
    protected String areaCode;
    @XmlElement(required = true)
    protected String exchange;
    @XmlElement(required = true)
    protected String number;

    ...
}

Note that the schema in Listing 7 used xsd:sequence. If it had used xsd:all instead, the propOrder annotation would have been empty: @XmlType(name = "Phone", propOrder = {}).

The new ObjectFactory class

JAXB generates a file that JAX-RPC does not: ObjectFactory. Each directory containing Java Beans will have one ObjectFactory. For each type defined in the schema's corresponding namespace, the ObjectFactory class will have a create method for that type. For each element, the ObjectFactory class will have a create element method, which returns a javax.xml.bind.JAXBElement<Type>. For example, for the Phone schema in Listing 7, Listing 10 shows the generated ObjectFactory class with a method that returns an instance of Phone and a method that returns an instance of JAXBElement<Phone>. You can still directly instantiate the Java Beans in the directory, but it would be best to use the factory.

Listing 10. JAXB 2.0 ObjectFactory for Phone
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.namespace.QName;

public class ObjectFactory {

    private final static QName _Phone_QNAME = new QName
    ("urn:types.MyServiceSample.ibm.com", "Phone");

    public ObjectFactory() {...}

    public Phone createPhone() {...}

    @XmlElementDecl(namespace = "urn:types.MyServiceSample.ibm.com", name = "Phone")
    public JAXBElement<Phone> createPhone(Phone value) {...}
}

Java to XML schema mappings

With a judicious sprinkling of these new JAXB-defined annotations, Java can map in a well-directed manner to XML, essentially in the reverse of the XML-to-Java mappings that we have presented. But what about unannotated Java?

Mapping Java names to XML names in JAX-RPC and JAXB are essentially the same. That is, Java primitive types map to the same XML schema whether the mapping follows JAX-RPC or JAXB. JAX-RPC defines a small set of standard Java classes that map to XML. For all but one of those, JAXB maps precisely the same, but JAXB adds a few more to its list of mapped classes, as Table 2 shows.

Table 2. Mapping differences between JAX-RPC 1.1 and JAXB 2.0 for standard Java classes
TypeJAX-RPC 1.1JAXB 2.0
java.lang.Stringxsd:stringxsd:string
java.math.BigIntegerxsd:integerxsd:integer
java.math.BigDecimalxsd:decimalxsd:decimal
java.util.Calendarxsd:dateTimexsd:dateTime
java.util.Datexsd:dateTimexsd:dateTime
javax.xml.namespace.QNamexsd:QNamexsd:QName
java.net.URIxsd:anyURIxsd:string
javax.xml.datatype.XMLGregorianCalendarn/axsd:anySimpleType
javax.xml.datatype.Durationn/axsd:duration
java.lang.Objectn/a1xsd:anyType
java.awt.Imagen/a2xsd:base64Binary
javax.activation.DataHandlern/a2xsd:base64Binary
javax.xml.transform.Sourcen/a2xsd:base64Binary
java.util.UUIDn/axsd:string

Table 2 Notes:
1. Some vendors mapped java.lang.Object to xsd:anyType.
2. In JAX-RPC, this is mapped to a mime binding type - the XML type is undefined.

Conclusion

We've compared the mappings of JAX-RPC 1.1 and JAXB 2.0. They are similar with some notable exceptions:

  • XML to Java:
    • A few of the simple types are mapped differently
    • JAXB adds the ObjectFactory class
    • JAXB makes use of the new Java language annotation feature and generic feature
  • Java to XML:
    • The primitive type mappings are identical
    • The standard Java mappings are nearly identical

We can say much more about the JAXB 2.0 specification, particularly its use of Java annotations, but that topic is out of this article's scope. For more information about JAXB 2.0, see Related topics.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=180779
ArticleTitle=Web services hints and tips: JAX-RPC versus JAX-WS, Part 2
publish-date=11302006