JAX-WS Attachment – Enable MTOM

It all begins with the fact that SOAP is XML. And when you send anything other than text, for instance, an image – it has to be converted into a datatype that an XML processor can understand.

Without MTOM, your image will be converted to base64Binary and placed smack in the middle of your SOAP envelope. This conversion process makes the data fat.

<tns:data>A very looooooooooooooooooooooong base64Binary string</tns:data>

Here’s a simple illustration:

lXWep

With MTOM, the image will be transmitted outside the envelope as a MIME attachment – in short, it’s sent according to its original datatype: a jpg, png, or gif. Of course it’s still transmitted as binary data, but this time, there’s no XML-related conversion, avoiding the unnecessary overhead. XOP comes into the picture as it’s the one that gives the location of the externalized image.

<soap:Body><soap:Envelope>

<tns:data><xop:include href="SomeUniqueID-ThatLeadsToTheImage"/></tns:data>

</soap:Body></soap:Envelope>

Content-id: "SomeUniqueID"

Content-Type: image/png

image binary data here

What is MTOM?
MTOM (Message Transmission Optimization Mechanism) provides an efficient mechanism for transmitting binary data to and from web services over internet. MTOM uses XML binary Optimized Packaging or XOP to serialize and de-serialize binary part of an XML infoset.
MTOM is a standard that is developed by the World Wide Web Consortium (W3C) and it is a SOAP Version 1.2 feature (based on the Infoset). Even though SwA (SOAP with Attachments) and MTOM are theoretically similar, and both encode binary data as a MIME attachment in a MIME document, SwA could be replaced by the more powerful MTOM and XOP mechanisms because it solves some of the interoperability issues of SwA. MTOM uses XOP in the context of SOAP and MIME over HTTP to achieve performance improvement.

How Does XOP works?
As we know, the serialization of XML infoset is text based and uses BASE64 binary-to-text encoding scheme, where the binary data represented in an ASCII string format. This increases the size of the XML payload.
An MTOM-enabled web services engine detects the presence of Base64Binary data. XOP packaging process extracts the binary data out of the XML Infoset and the binary data serialized differently. XOP process extracts the binary part of the XML info-set and leaves the XML Infoset with the binary parts replaced by external references. This is called XOP infoset and the external reference is added as “xop:Include” element in XML. This makes MTOM actually a “by reference” method.
The raw bytes are appended to the SOAP Message and are separated by a MIME boundary.
The XOP package is created by serializing the XOP infoset and the binary data as a MIME attachment. Once the data is received at the other end, the XOP Package is de-serialized into the XOP Infoset plus the extracted content and the extracted content is placed back in the XML infoset where the corresponding external reference is present.
See and example SOAP response below which uses MTOM. We will see the complete working example as we move on.

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:retrieveImageResponse xmlns:ns2="http://globinch.com"> <return> <xop:Include href="cid:40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com" xmlns:xop="http://www.w3.org/2004/08/xop/include"/> </return> </ns2:retrieveImageResponse> </S:Body> </S:Envelope>

You can see the reference to the MIME attachment as

<xop:Include href="cid:40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>

If you examine the SOAP header you will something like the below

	
Transfer-encoding  : chunked
Content-type            : multipart/related;start="&lt;rootpart*75292b03-7617-4261-a44f-ac8d9df23382@example.jaxws.sun.com&gt;";type="application/xop+xml";boundary="uuid:75292b03-7617-4261-a44f-ac8d9df23382";start-info="text/xml"
#status# : HTTP/1.1 200 OK

The attachment details are as below

Name: 40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com	
Content type: image/png	
Size:431731	
Part: 40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com	
Type: XOP	
ContentId: 40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com

The contentId is same as the reference.

Enabling MTOM in JAX-WS :
In JAX-WS, it’s easy to enable MTOM for a web service endpoint by using either the @MTOM or @BindingType annotations. At the client side, MTOM can be enabled either by passing a new instance of MTOMFeature class when getting a reference to the web service endpoint (port), or by calling the SOAPBinding.setMTOMEnabled(true) method on the binding provider object. Here are the usages and examples in details.

  • Enabling MTOM for the web service endpoint
  • @MTOM annotation :

    The following example illustrates a web service endpoint is annotated with the @MTOM annotation:

    import javax.jws.WebMethod;
    import javax.jws.WebService;
    import javax.xml.ws.soap.MTOM;
    
    
    @WebService
    @MTOM
    public class MyWebService {
      
      @WebMethod
      public void upload(byte[] data) {
        // implementation details...	
      }
    }
    

    The @MTOM annotation has two optional parameters, enabled and threshold. The enabled parameter has a boolean value and indicates if MTOM is enabled for the JAX-WS endpoint. If an attachment is smaller than the size specified in threshold parameter, the runtime will inline the binary data as base64 binary instead of creating an attachment.

    @WebService
    @MTOM(threshold = 10240)
    public class MyWebService {
    }
    

    An alternative way is using the @BindingType annotation with an appropriate value for the SOAP version used. For example:

    Enabling MTOM with SOAP version 1.1:

    import javax.xml.ws.BindingType;
    import javax.xml.ws.soap.SOAPBinding;
    
    @WebService
    @BindingType(value = SOAPBinding.SOAP11HTTP_MTOM_BINDING)
    public class MyWebService {
    }
    

    Enabling MTOM with SOAP version 1.2:

    import javax.xml.ws.BindingType;
    import javax.xml.ws.soap.SOAPBinding;
    
    @WebService
    @BindingType(value = SOAPBinding.SOAP12HTTP_MTOM_BINDING)
    public class MyWebService {
    }
    

    From the above examples, we can see that using the @MTOM annotation is preferred as its succinct and flexibility (enabled/disabled and threshold).

    Enabling MTOM for the client :

    The following example shows how to enable MTOM at the client by passing a new instance of the MTOMFeature class when getting a proxy reference the web service endpoint:

    import javax.xml.ws.soap.MTOMFeature;
    
    MyWebServiceService service = new MyWebServiceService();
    MyWebService port = service.getMyWebServicePort(new MTOMFeature());
    

    Suppose that the MyWebServiceService and MyWebService classes are generated by the wsimport tool. And similar to the @MTOM annotation, we can also specify the enabled and threshold parameters in the MTOMFeature class’ constructor like this:

    boolean enabled = true;
    int threshold = 10240;
    MyWebService port = service.getMyWebServicePort(new MTOMFeature(enabled, threshold));
    

    And here’s an alternative way, calling the SOAPBinding.setMTOMEnabled(true) method:

    MyWebServiceService service = new MyWebServiceService();
    MyWebService port = service.getMyWebServicePort();
    
    BindingProvider provider = (BindingProvider) port;
    SOAPBinding soapBinding = (SOAPBinding) provider.getBinding();
    soapBinding.setMTOMEnabled(true);
    

    For more info :

    http://stackoverflow.com/questions/215741/how-does-mtom-work

    http://java.globinch.com/enterprise-java/web-services/jax-ws/jax-ws-attachment-enable-mtom-jax-ws-web-services/

    http://www.tuicool.com/articles/I3yEbu

    Advertisements

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s