devxlogo

Faster Data Transport Means Faster Web Services with MTOM/XOP

Faster Data Transport Means Faster Web Services with MTOM/XOP

he technologies of Message Transmission Optimization Mechanism (MTOM) and XML-Binary Optimized Packaging (XOP) are concerned with the fundamental issue of binary data transmission, which is of great importance to web service performance. Since becoming W3C standards in 2005, XOP and MTOM have been quickly and widely adopted in next-generation SOAP engines. In hindsight, one has to wonder why they were not proposed earlier in the development of web services or as part of the original SOAP specification.

This article introduces MTOM and XOP, discusses the problems they address, and then uses an example to demonstrate how to work with them in JAX-WS 2.0.

Challenges That MTOM/XOP Addresses
The issue MTOM/XOP tackles is the coordinated transport of opaque binary data in conjunction with an XML document. The two traditional approaches for handling this issue are:

  1. Embedding such data in XML as text-encoded octets with type xs:base64Binary or xs:hexBinary
  2. Referring to the binary data with a URI of type xs:anyURI in the XML document, with the opaque data bundled alongside using a package format (e.g., SwA and WS-Attachment)

Unfortunately, these approaches suffer from performance and interoperability problems. The first one bloats the message size (with UTF-8 text encoding, base64 encoded data expands by a factor of 1.33x, and hexadecimal encoded data expands by a factor of 2x). It also carries the overhead of processing costs, especially when decoding back into binary. In the second approach, the data is external to the XML document and isn’t part of the message Infoset. As a result, layered technologies for processing and describing XML and SOAP need to provide one set of solutions for the XML component of their data and another set of solutions for the external components (e.g., DIME and multipart MIME). This not only complicates all the entities working with such messages, but also brings interoperability issues because no standard model governs how SOAP intermediaries process the referenced data; existing technologies such as XML signature and encryption weren’t really designed with such referenced data in mind.

For a detailed and well-written analysis of those challenges, refer to “XML, SOAP and Binary Data“, a white paper from BEA and Microsoft written by Adam Bosworth and Don Box, et al.

How XOP Works
XOP extracts binary data in an XML document and serializes them into packages located inside an extensible packaging format such as MIME Multipart/Related. The new XML document marks the locations of those binary data packages with special elements that contain URI identifying the corresponding location.

Unlike traditional approaches for handling binary data in XML documents, XOP does not require encoding binary data in base64. The data can take its original format as octet streams. An application parsing an XOP package may work directly with the octet stream, or if appropriate, compute the base64 binary character representation from this stream.

Listing 1 and Listing 2 are SOAP messages that contain the same content in transmission over HTTP, but Listing 2 shows the message as serialized using the XOP format into a MIME Multipart/Related package. Look at the …/book/coverImage and …/book/sample/content elements in Listing 1. Both contain base64-encoded streams. In Listing 2, those base64-encoded streams are replaced with xop:Include elements, each of which contains an attribute href pointing to a MIME part through a URI following the cid:URI schema. The MIME parts contain the actual binary data in octet streams.

The W3C recommendation, XML-binary Optimized Packaging, specifies the various constructs in an XOP package, such as the syntax and semantics of the xop:Include element and its href attribute. It also specifies how to create and interpret an XOP package using the original XML document as the reference. By the specification, XOP works only with XML elements of xs:base64Binary type.

How MTOM Addresses These Challenges
MTOM provides a concrete implementation for using XOP to optimize the transmission and/or wire format of SOAP messages. It describes how to serialize a SOAP envelope using the XOP format and MIME Multipart/Related packaging (note that MIME Multipart/Related is not required in XOP). Following the rules specified, MTOM serializes a SOAP message into a MIME Multipart/Related XOP package with one body part (the root) that contains an XML representation of the modified SOAP envelope and additional parts that contain the binary representation of each element of the xs:base64Binary type. With MTOM, deserialization of this transferred SOAP message follows the standard XOP approach.

MTOM further specifies a concrete implementation of this mechanism for SOAP HTTP binding. For example, it requires placing the MIME headers of the resulting MIME Multipart/Related XOP package in HTTP headers and the rest of the package into the HTTP body.

You can identify MTOM in a SOAP message transmission over HTTP by the following four attributes:

  1. The application/xop+xml media is present.
  2. The media type of the HTTP message is multipart/related.
  3. The media type of the root part of the MIME Multipart/Related package is application/xop+xml.
  4. The start-info parameter indicates a content type of application/soap+xml.

Note that the W3C MTOM specification considers only SOAP 1.2. On April 2006, IBM, Microsoft, SAP, and Oracle submitted SOAP 1.1 Binding for MTOM 1.0 to the W3C to cover SOAP 1.1. This document, while reflecting the difference between SOAP 1.1 and SOAP 1.2, keeps the essential features of MTOM untouched. Following this member submission, the above-mentioned start-info parameter of the root part of the MIME Multipart/Related package becomes text/xml instead of application/soap+xml in SOAP 1.1. (Listing 2 shows a SOAP 1.1 example.)

With this background information covered, the next section will illustrate how to work with MTOM/XOP in JAX-WS 2.0, which is part of Java SE 6.0, (and its reference implementation) using a sample web service.

A Simple JAX-WS 2.0 Web Service
The sample web service developed in this section simulates a book catalog management system. (Listing 3 shows the web service WSDL.) It defines two operations in the service endpoint interface CatalogPort: upload and retrieve, which allow client applications to register (and update) book information and retrieve the sample chapter stored in the system, respectively. Listing 4 presents the schema file, Book.xsd, which is referred to in the WSDL. Pay particular attention to two previously mentioned elements, /book/coverImage and /book/sample/content.

To implement the sample web service with JAX-WS 2.0, you first need to use the apt tool to generate the port type interface CatalogPortType.java (see Listing 5), the domain objects in the com.company.mtom.catalog.book package, and the service class Catalog.java, which the clients will use to obtain the CatalogPort.

In the endpoint implementation class CatalogImpl.java, the upload() method stores the following:

  1. Basic information about the book and the sample chapter name in a properties file with the name of ${isbn}.properties under the book_info folder.
  2. The cover image in a file ${isbn}.jpg under the book_cover folder.
  3. The description (desc) string in a file ${isbn}.txt under the book_desc folder.
  4. The sample chapter content in a file ${isbn}.pdf under the folder book_sample.

The retrieve() method, on the other hand, obtains the sample chapter name from the properties file and the content from the book_sample directory, all based on an input parameter isbn, and returns a Chapter object to the client.

To get the web service up and running, all you have to do now is come up with the web service deployment descriptor (sun-jaxws.xml) and the web application deployment descriptor (web.xml), and then deploy the application war into a container (Tomcat, in this example). You can download the accompanying source code and look at these artifacts and the various Ant tasks for packaging, deployment, etc. For reference, here is the example’s sun-jaxws.xml descriptor:

     

That’s about it for the service. Listing 6 shows the main body of the sample web service client, in which the input book information is captured in a properties file named isbn, and the book cover image, sample chapter content, and description text are all kept in separate files (under ./etc). The private method getBook() creates a Book object to be used for invoking upload(), and compareSample() compares retrieved (through retrieve()) sample chapter names and content with information available in the local repository at this client side (./etc).

The example application comes with all the input files utilized by the client for three sample books. To look at the SOAP messages in transmission, you can install tcpmon as a proxy. Listing 1 shows a SOAP request message as captured by tcpmon while invoking the upload() method with information about one of the sample books. Listing 7 shows the response from the web service when the client calls the retrieve() method. In this listing, the sample chapter content is base64 encoded and embedded in the SOAP body.

Enabling the Example Application with MTOM
JAX-WS 2.0 supports MTOM for both SOAP 1.1 and SOAP 1.2 HTTP bindings. This section describes how to enable the example application with MTOM using the SOAP 1.1 binding. Working with SOAP 1.2 would require slight adjustments to the application and obvious changes to the instructions to follow.

With JAX-WS 2.0, you can enable MTOM on the client side, the service side, or both. To enable MTOM on the client side for the example application, all you need to do is uncomment the first two bold lines in Listing 6, the client application:

SOAPBinding binding = (SOAPBinding)((BindingProvider)port).getBinding();binding.setMTOMEnabled (true);

When you call the upload() method in this case (with the client MTOM enabled and the service not), the request SOAP message will look like Listing 2, indicating the client is sending optimized messages. Even though the service is not MTOM-enabled, the call succeeds. This shows that the service is able to respond to both optimized and ordinary messages.

When you invoke the retrieve() operation, the response SOAP message looks like Listing 7, indicating the service is sending ordinary messages even though the client is MTOM-enabled.

Two provisions to note are:

  1. The SOAPBinding interface also provides a method for checking if MTOM is enabled on the binding, javax.xml.ws.soap.SOAPBinding.isMTOMEnabled().
  2. JAX-WS 2.0 allows clients to interact with a web service through either a port proxy (as in this example) or the Dispatch API. MTOM can be enabled only for port proxy-based clients.

On the service side, you can enable MTOM in one of three ways:

  1. You can add one line to the proprietary web service deployment descriptor, sun-jaxws.xml, as follows:
         
  2. Use the same descriptor as in the following example:
         

    Notice the binding attribute of endpoint. To enable MTOM for SOAP 1.1 or SOAP 1.2 HTTP bindings, you may specify one of the following identifiers for the binding attribute, respectively:

    • http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true
    • http://www.w3.org/2003/05/soap/bindings/HTTP/?mtom=true
  3. Use the @javax.xml.ws.BindingType annotation on the service endpoint implementation class, specifying a value of javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING (or javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING for SOAP 1.2). This approach is a variant of the second and is JAX-WS 2.0 standard compliant. The following example illustrates it:
    @WebService(endpointInterface = "com.company.mtom.catalog.service.CatalogPortType")@BindingType(value=SOAPBinding.SOAP11HTTP_MTOM_BINDING)public class CatalogImpl implements CatalogPortType {     ......}

    The predefined constant javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING (.SOAP12HTTP_MTOM_BINDING) corresponds to the MTOM-enabled SOAP 1.1 (SOAP 1.2) HTTP binding identifier listed above.

When the service-side MTOM is enabled, if you disable MTOM at the client side you will find from tcpmon that the web service will send an optimized SOAP response when the client calls the retrieve() method (see Listing 8). Comparing this with Listing 7, the content of the …/chapter/content element in the SOAP body is replaced with an xop:Include element, which refers to the actual sample chapter content as a binary stream in a MIME part.

With MTOM enabled only on the service side, when the client invokes the upload() method it sends an ordinary SOAP request message, and the service is able to respond properly per the JAX-WS 2.0 specification.

If you have both the service side and the client side MTOM enabled, all communications are optimized when applicable.

Enabling MTOM for Large-Sized Binary Data Only
The reference implementation of JAX-WS 2.0 has a proprietary feature that allows the service and/or client to optimize only binary data that are larger than a configured threshold. With the example application, you can set the threshold on the client side by uncommenting the third bold line in Listing 6. The number is measured in bytes, and the following sample will instruct the client runtime to optimize only binary data with a size larger than 5 KB (Yes, the property is named MTOM_THRESHOLOD_VALUE, obviously a typo not caught before the final release):

((BindingProvider) port).getRequestContext().put(JAXWSProperties.MTOM_THRESHOLOD_VALUE, 6120);

Binary data less than 5 KB will remain in line in the SOAP message and stay base64 encoded. The default threshold value of the JAX-WS 2.0 reference implementation is 1 KB.

On the service side, you can set the threshold programmatically by adding the following lines in the endpoint implementation class CatalogImpl.java:

@Resourceprivate WebServiceContext wsContext;...wsContext.getMessageContext().put(com.sun.xml.ws.developer.JAXWSProperties.MTOM_THRESHOLOD_VALUE, 30720);...

The following code snippet shows how you can set the threshold for the retrieve() method using this approach:

public class CatalogImpl implements CatalogPortType {     @Resource     WebServiceContext wsContext;     public Chapter retrieve(String isbn) {          wsContext.getMessageContext().put(com.sun.xml.ws.developer.JAXWSProperties.MTOM_THRESHOLOD_VALUE, 30720);          ......     }     public boolean upload(Book bookInfo) {          ......     }     ......}

You may also specify the service side threshold value in the web service deployment descriptor, sun-jaxws.xml, as follows:

     

While the threshold value set in the deployment descriptor applies to all web methods exposed in the corresponding endpoint, using the programmatic approach allows different web methods to have different threshold values.

MTOM Features in JAX-WS 2.1.1 Release
The next version of JAX-WS (2.1.1) standardizes the feature of setting thresholds to enable MTOM only for large-sized data. It also will feature two new annotations (@javax.xml.ws.Feature and @javax.xml.ws.FeatureParameter) for easily configuring MTOM support.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist