Tuesday 20 October 2015

Using MTOM to optimize binary data transfer with JAX-WS web services

Reference : - http://www.codejava.net/java-ee/web-services/using-mtom-to-optimize-binary-data-transfer-with-jax-ws-web-services

By default, binary data is converted to base64Binary or hexBinary XML data type within a SOAP envelope, meaning that the raw bytes are encoded as a String using base64 technique. For example, the following XML snippet is content of such a SOAP message:

<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:upload xmlns:ns2="http://server.mtom.ws.codejava.net/">
            <arg0>binary.png</arg0>
            <arg1>iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoL...5CYII=</arg1>
        </ns2:upload>
    </S:Body>
</S:Envelope>


Look at the text inside the element <arg1> - it is the encoded form of the binary data in base64 format. Basically, the base64 encoding technique bloats the original data by a factor of 1.33x (with UTF-8 encoding) or 2.66x (with UTF-16), so it becomes very inefficient when dealing with a large amount of data. To overcome this drawback, MTOM is defined as a specification for optimizing the transmission of this kind of data type in SOAP messages, and XOP (XML-binary Optimized Packaging) is the concrete implementation. The following example is content of a HTTP POST request which is generated by MTOM/XOP:

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 @BindingTypeannotations. 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 theSOAPBinding.setMTOMEnabled(true) method on the binding provider object. Here are the usages and examples in details.

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




That enables MTOM support for the MyWebService endpoint. The @MTOM annotation has two optional parameters:
  • enabled: specifies whether MTOM feature is enabled (true) or disabled (false).
  • threshold: specifies the size (in bytes) above which the binary data will be sent as attachment. This would be useful to enable MTOM only for data which is larger than a specified amount.



@WebService
@MTOM(enabled = false)
public class FrogWebService {
}


This example shows MTOM is enabled only for binary data which is larger than 12222 bytes:
1
2
3
4

@WebService
@MTOM(threshold = 12222)
public class FrogWebService {
}
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:
    1
    2
    3
    4
    5
    6
    7
    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:
    1
    2
    3
    4
    5
    6
    7
    import javax.xml.ws.BindingType;
    import javax.xml.ws.soap.SOAPBinding;
     
    @WebService
    @BindingType(value = SOAPBinding.SOAP12HTTP_MTOM_BINDING)
    public class MyWebService {
    }

Enabling MTOM for the client
The following example shows how to enable MTOM at the client by passing a new instance of the MTOMFeatureclass when getting a proxy reference the web service endpoint:
1
2
3
4
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 MTOMFeatureclass’ constructor like this:
1
2
3
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:
1
2
3
4
5
6
MyWebServiceService service = new MyWebServiceService();
MyWebService port = service.getMyWebServicePort();
 
BindingProvider provider = (BindingProvider) port;
SOAPBinding soapBinding = (SOAPBinding) provider.getBinding();
soapBinding.setMTOMEnabled(true);



No comments:

Post a Comment