Web services hints and tips: JAX-RPC versus JAX-WS, Part 2

A look at the differences in data mapping

JAX-WS 2.0, the successor to JAX-RPC 1.1, has evolved its data mapping methods by using JAXB (the Java Architecture for XML Binding), a JCP-defined technology. This second tip in a series compares the data mappings of these two Web services specifications. Read Part 1 of JAX-RPC vs. JAX-WS for a broader look at their differences.

Share:

Russell Butek (butek@us.ibm.com), IT Specialist, IBM

Russell Butek is an IBM SOA and web services consultant. He has been one of the developers of the IBM WebSphere web services engine. He has also been a member the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache's AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC.


developerWorks Contributing author
        level

Nicholas Gallardo (nlgallar@us.ibm.com), Staff Software Engineer, IBM

Nicholas Gallardo works as a software engineer on the IBM WebSphere web services engine, where he is focused on serviceability and interoperability. Nicholas came to IBM in 2001 after contributing development efforts to two different technology start-ups in Austin, Texas.



30 November 2006

Also available in Chinese Russian

Introduction

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

JAX-RPC and JAXB

Why didn't JAX-RPC use JAXB in the first place? The answer is timing. The first version of JAX-RPC was completed before JAXB, so rather than wait, the writers of JAX-RPC developed their own mapping feature.

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 Resources.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


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