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

Comparing attachment files: Sw/A and MTOM

Java™ API for XML-based RPC (JAX-RPC) supports the SOAP with Attachments (Sw/A) specification, while Java API for XML Web Services (JAX-WS) supports Sw/A along with the new Message Transmission Optimization Mechanism (MTOM) specification. This fifth tip in this series compares these two attachment models by examining samples of Web Services Description Languages (WSDLs) and mapped Java interfaces.

Share:

Russell Butek, Certified IT Specialist, IBM

Russell Butek is an IBM SOA/Web services consultant. He has been one of the developers of IBM's 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, Advisory Software Engineer, IBM

Nick Gallardo is an IBM software engineer working on the WebSphere platform. He has worked on various aspects of the Websphere Web services run time, with a concentration on the programming models. In addition, Nick is a member of the Apache Software Foundation and helped shape the support for JAX-WS within the Axis2 community.



15 November 2007

Also available in Japanese

Introduction

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See Building and deploying JAX-WS web services

The attachment model for JAX-RPC is Sw/A. Since JAX-RPC was written, a new attachment model has come onto the scene: MTOM. JAX-WS provides Sw/A support just as JAX-RPC does, but adds support for MTOM. JAX-WS supports MTOM via the Java Architecture for XML Binding (JAXB) specification, which includes APIs for marshalling and unmarshalling both Sw/A and MTOM attachments. In this tip, you examine both models through examples. Note: This tip compares only the WSDLs and the Java programming models; comparing the wire-level messages is left as an exercise to the reader.


JAX-RPC and Sw/A example

Listing 1 shows the WSDL from an attachment tip written a few years ago (see Resources). Listing 2 shows the Java interface, which the JAX-RPC mapping produces from this WSDL.

Listing 1. JAX-RPC Sw/A WSDL
<definitions
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:tns="http://attachment.tip/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
        targetNamespace="http://attachment.tip/">
  <types/>
  <message name="sendImage">
    <part name="image" type="xsd:base64Binary"/>
  </message>
  <message name="sendImageResponse"/>
  <message name="sendOctet">
    <part name="octet" type="xsd:base64Binary"/>
  </message>
  <message name="sendOctetResponse"/>
  <portType name="AttachmentTip">
    <operation name="sendImage">
      <input message="tns:sendImage"/>
      <output message="tns:sendImageResponse"/>
    </operation>
    <operation name="sendOctet">
      <input message="tns:sendOctet"/>
      <output message="tns:sendOctetResponse"/>
    </operation>
  </portType>
  <binding name="AttachmentBinding" type="tns:AttachmentTip">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="sendImage">
      <soap:operation soapAction=""/>
      <input>
        <mime:multipartRelated>
          <mime:part>
            <soap:body parts="" namespace="http://attachment.tip/" use="literal"/>
          </mime:part>
          <mime:part>
            <mime:content part="image" type="image/jpeg"/>
          </mime:part>
        </mime:multipartRelated>
      </input>
      <output>
        <soap:body namespace="http://attachment.tip/" use="literal"/>
      </output>
    </operation>
    <operation name="sendOctet">
      <soap:operation soapAction=""/>
      <input>
        <mime:multipartRelated>
          <mime:part>
            <soap:body parts="" namespace="http://attachment.tip/" use="literal"/>
          </mime:part>
          <mime:part>
            <mime:content part="octet" type="application/octet-stream"/>
          </mime:part>
        </mime:multipartRelated>
      </input>
      <output>
        <soap:body namespace="http://attachment.tip/" use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="AttachmentService">
    <port binding="tns:AttachmentBinding" name="AttachmentTip">
      <soap:address location="http://localhost:9080/SwAService/services/AttachmentTip"/>
    </port>
  </service>
  </definitions>
Listing 2. JAX-RPC Sw/A Java interface
package tip.attachment;

import java.awt.Image;
import java.rmi.Remote;
import java.rmi.RemoteException;

import javax.activation.DataHandler;

public interface AttachmentTip extends Remote {
    public void sendImage(Image image) throws RemoteException;
    public void sendOctet(DataHandler octet) throws RemoteException;
}

The Java interface mapping from the WSDL is fairly straightforward: The sendImage operation's image/jpeg part is mapped to a java.awt.Image parameter; the sendOctet operation's application/octet-stream is mapped to a javax.activation.DataHandler parameter. However, there's a cost to this mapping: The Multipurpose Internet Mail Extensions (MIME) type information isn't in the interface portion of the WSDL (the portType, message, and types sections). You must dip into the binding to find the MIME information. This is unfortunate because different bindings for the same WSDL interface could result in different types and, therefore, map to different Java interfaces. It would be better if there were a one-to-one mapping from WSDL interface to Java interface. If you have more than one binding, each simply maps to an implementation, all of which implements the same Java interface. With Sw/A, you can't do that; the mapping from WSDL to Java interfaces is not one to one.

A secondary issue with Sw/A is that it doesn't lend itself well to the industry convention of document/literal wrapped WSDL (you'll notice that the WSDL in Listing 1 is an rpc/literal WSDL). Adding Sw/A content to a document/literal wrapped message requires specifying additional message parts beyond the single operation wrapper.

Does MTOM fix these issues? Let's move on to the next section to find out.


JAX-WS and MTOM example

In Listing 3, we've modified the Sw/A WSDL from Listing 1 to produce an equivalent MTOM WSDL.

Listing 3. JAX-WS MTOM WSDL
<definitions
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:tns="http://attachment.tip/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://attachment.tip/">
  <types/>
  <message name="sendImage">
    <part name="image" type="xsd:base64Binary"/>
  </message>
  <message name="sendImageResponse"/>
  <message name="sendOctet">
    <part name="octet" type="xsd:base64Binary"/>
  </message>
  <message name="sendOctetResponse"/>
  <portType name="AttachmentTip">
    <operation name="sendImage">
      <input message="tns:sendImage"/>
      <output message="tns:sendImageResponse"/>
    </operation>
    <operation name="sendOctet">
      <input message="tns:sendOctet"/>
      <output message="tns:sendOctetResponse"/>
    </operation>
  </portType>
  <binding name="AttachmentBinding" type="tns:AttachmentTip">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="sendImage">
      <soap:operation soapAction=""/>
      <input>
        <soap:body namespace="http://attachment.tip/" use="literal"/>
      </input>
      <output>
        <soap:body namespace="http://attachment.tip/" use="literal"/>
      </output>
    </operation>
    <operation name="sendOctet">
      <soap:operation soapAction=""/>
      <input>
        <soap:body namespace="http://attachment.tip/" use="literal"/>
      </input>
      <output>
        <soap:body namespace="http://attachment.tip/" use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="AttachmentService">
    <port binding="tns:AttachmentBinding" name="AttachmentTip">
      <soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/>
    </port>
  </service>
</definitions>

The only real difference between the MTOM WSDL in Listing 3 and the Sw/A WSDL in Listing 1 is the binding. The MTOM binding contains no MIME information. In fact, there's no way to tell, from the WSDL, that you're dealing with attachments; the WSDL's binding looks like a normal binding.

Listing 4 shows the Java interface, which a JAX-WS mapping produces from this WSDL.

Listing 4. JAX-WS MTOM Java interface
package tip.attachment;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface AttachmentTip {


    @WebMethod
    public void sendImage(
        @WebParam(name = "image", partName = "image")
        byte[] image);

    @WebMethod
    public void sendOctet(
        @WebParam(name = "octet", partName = "octet")
        byte[] octet);

}

Because the WSDL is a normal-looking WSDL with no hint of attachments, you end up with a Java interface that reflects that as well. Given parts of type base64Binary (or hexBinary), JAX-WS maps those to parameters of type byte[]. With MTOM, the MIME-ness of the types has all been extracted from the WSDL with the burden placed on the client or server run time to format the content appropriately.


Comparison of Sw/A and MTOM

The JAX-RPC Sw/A section noted two drawbacks to Sw/A:

  • The MIME type info is in the WSDL binding, not the WSDL interface.
  • It's difficult to create a document/literal wrapped attachment WSDL.

Let's discuss the document/literal wrapped style first.

document/literal wrapped style and attachments

We left the MTOM WSDL in Listing 3 as rpc/literal WSDL for comparison purposes; but it's an easy matter to turn this WSDL into document/literal wrapped WSDL. Listing 5 in the next section shows the document/literal wrapped equivalent of the WSDL in Listing 3 (see Resources for more information about the differences between various WSDL styles).

MIME type info in the binding

Because the MTOM WSDL's binding doesn't have any MIME information, you don't have to dip into the binding to determine the part types. You have everything you need in the WSDL interface to generate the Java interface. However, as you can see by comparing the Java interfaces in Listing 2 and Listing 4, we've lost some information.

The interface portion of both WSDLs shows that the data type in the operations is base64Binary, which maps to byte[]. In the JAX-RPC Sw/A WSDL, however, you know from the binding that the part types are a MIME image and a MIME octet stream. In the JAX-WS MTOM WSDL, this information is lost. This may seem like a bad thing, but the positive spin is that this completely cleans up the interface. No matter what the binding, the interface is always the same. In fact, the implementors of the client and the server codebases shouldn't be bothered with the notion of whether the parameter is an attachment. That's merely a detail of the SOAP message, and the writers of the WSDL-to-Java mappings have tried their best to abstract the programmer away from the details of the SOAP message.

However, if you really want to know what the MIME type is—if you want to get back to the information you lost—JAX-WS provides support for an attribute that you can inject into an XML element: expectedContentTypes. This special attribute is highlighted in Listing 5. Listing 6 shows the corresponding Java interface. Ignoring the annotations, this Java interface is essentially the same as the interface in Listing 2.

Listing 5. JAX-WS MIME attribute

Click to see code listing

Listing 5. JAX-WS MIME attribute

<definitions
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:tns="http://attachment.tip/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://attachment.tip/">
  <types>
    <xsd:schema
            xmlns:tns="http://attachment.tip/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://attachment.tip/">
      <xsd:element name="sendImage" type="tns:sendImage"/>
      <xsd:complexType name="sendImage">
        <xsd:sequence>
          <xsd:element
                  xmlns:ns1="http://www.w3.org/2005/05/xmlmime"ns1:expectedContentTypes="image/*"
                  name="image"
                  type="xsd:base64Binary"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="sendImageResponse" type="tns:sendImageResponse"/>
      <xsd:complexType name="sendImageResponse">
        <xsd:sequence/>
      </xsd:complexType>
      <xsd:element name="sendOctet" type="tns:sendOctet"/>
      <xsd:complexType name="sendOctet">
        <xsd:sequence>
          <xsd:element 
                 xmlns:ns1="http://www.w3.org/2005/05/xmlmime"ns1:expectedContentTypes="application/octet-stream"
                 name="octet"
                 type="xsd:base64Binary"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="sendOctetResponse" type="tns:sendOctetResponse"/>
      <xsd:complexType name="sendOctetResponse">
        <xsd:sequence/>
      </xsd:complexType>
    </xsd:schema>
  </types>
  <message name="sendImage">
    <part name="parameters" element="tns:sendImage"/>
  </message>
  <message name="sendImageResponse">
    <part name="parameters" element="tns:sendImageResponse"/>
  </message>
  <message name="sendOctet">
    <part name="parameters" element="tns:sendOctet"/>
  </message>
  <message name="sendOctetResponse">
    <part name="parameters" element="tns:sendOctetResponse"/>
  </message>
  <portType name="AttachmentTip">
    <operation name="sendImage">
      <input message="tns:sendImage"/>
      <output message="tns:sendImageResponse"/>
    </operation>
    <operation name="sendOctet">
      <input message="tns:sendOctet"/>
      <output message="tns:sendOctetResponse"/>
    </operation>
  </portType>
  <binding name="AttachmentBinding" type="tns:AttachmentTip">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="sendImage">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
    <operation name="sendOctet">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="AttachmentService">
    <port binding="tns:AttachmentBinding" name="AttachmentTip">
      <soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/>
    </port>
  </service>
</definitions>

Notice that this new attribute is wholly contained within the WSDL interface. It's not in the binding, so all of the type information is where you want it.

Listing 6. JAX-WS Java interface mapped from the MIME attribute
package tip.attachment;

import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
public interface AttachmentTip {

    @WebMethod
    @RequestWrapper(localName = "sendImage", 
            targetNamespace = "http://attachment.tip/", 
            className = "tip.attachment.SendImage")
    @ResponseWrapper(localName = "sendImageResponse", 
            targetNamespace = "http://attachment.tip/", 
            className = "tip.attachment.SendImageResponse")
    public void sendImage(
        @WebParam(name = "image", targetNamespace = "")
        Image image);

    @WebMethod
    @RequestWrapper(localName = "sendOctet", 
            targetNamespace = "http://attachment.tip/", 
            className = "tip.attachment.SendOctet")
    @ResponseWrapper(localName = "sendOctetResponse", 
            targetNamespace = "http://attachment.tip/", 
            className = "tip.attachment.SendOctetResponse")
    public void sendOctet(
        @WebParam(name = "octet", targetNamespace = "")
        DataHandler octet);
}

As mentioned earlier, JAX-WS relies on JAXB to handle the data binding for most of its Web services content. The mapping for the expectedContentTypes element is defined in Appendix H of the JAXB 2.0 specification (see Resources). The JAXB 2.0 mappings are similar to the JAX-RPC mappings. Compare these mappings in Table 1.

Table 1. MIME type to Java type mappings
MIME typeJAX-RPC mappingJAX-WS/JAXB mapping
image/gifjava.awt.Imagejava.awt.Image
image/jpgjava.awt.Imagejava.awt.Image
text/plainjava.lang.Stringjavax.xml.transform.Source
text/xmljavax.xml.transform.Sourcejavax.xml.transform.Source
application/xmljavax.xml.transform.Sourcejavax.xml.transform.Source
multipart/*javax.mail.internet.MimeMultipartjavax.activation.DataHandler
all other typesjavax.activation.DataHandlerjavax.activation.DataHandler

enabling/disabling attachment support

One of the of additional benefits of MTOM is the fact that you can turn it on or off. In the case of Sw/A, if one side or the other doesn't support sending Sw/A attachments, then the contract defined by the WSDL cannot be honored. On the other hand, if you have an MTOM WSDL such as that in listing 3 or 5, a client could choose to send data as an MTOM attachment or inline in the SOAP message. No matter what the client chooses, it can still interact with the Web service. MTOM is just an optimization of sending content, not a mandate like Sw/A.


Sw/A and JAX-WS

JAX-WS still supports the Sw/A model. By default, JAX-WS maps a Sw/A attachment to a byte[] on the Java interface, like the sample in Listing 4. To get the mapping you are used to in JAX-RPC, you can use the enableMIMEContent WSDL binding definition (see section 8.7.5 of the JAX-WS specification for more details). Listing 7 shows the JAX-WS version of the Java interface equivalent to the JAX-RPC version of the interface in listing 2.

Listing 7. JAX-WS Java interface with Sw/A attachments mapped from the mime:content
package tip.attachment;

import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface AttachmentTip {


    @WebMethod
    public void sendImage(
        @WebParam(name = "image", partName = "image")
        Image image);

    @WebMethod
    public void sendOctet(
        @WebParam(name = "octet", partName = "octet")
        DataHandler octet);

}

Summary

JAX-RPC supports the Sw/A model. JAX-WS supports Sw/A as well, but it has also stepped up to the new MTOM model. MTOM is an improvement upon Sw/A in a number of ways:

  • Everything necessary to create a Java interface is now available in the WSDL interface.
  • MTOM is usable in a document/literal wrapped WSDL.
  • MTOM allows optimization to attachments, but it doesn't force attachments like Sw/A does.

Resources

Learn

Get products and technologies

  • Innovate your next development project with IBM trial software, available for download or on DVD.

Discuss

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=269336
ArticleTitle=Web services hints and tips: JAX-RPC versus JAX-WS, Part 5
publish-date=11152007