# MTOM and Swaref

## MTOM and XOP

MTOM (Message Transmission and Optimization Mechanism) together with XOP (XML Binary Optimized Packaging) defines how an XML binary data such as `xs:base64Binary` or `xs:hexBinary` can be optimally transmitted over the wire. XML type, such as `xs:base64Binary` is sent in lined inside the SOAP envelope. This gets quite in-efficient when the data size is more, for example a SOAP endpoint that exchanges images/songs etc. MTOM specifies how XOP packaging can be used to send the binary data optimally.

## MTOM in JAX-WS 2.0

MTOM feature is disabled in JAX-WS by default. It can be enabled on the client and server. Once enabled all the XML binary data, XML elements of type `xs:base64Binary` and `xs:hexBinary` is optimally transmitted. Currently MTOM works only with proxy port.

Note: MTOM optimization is applied right at the time when JAX-WS writes the message on to the wire. This is done to avoid any bufferring. Having a handler means that JAX-WS transforms the Message in to DOM or SOAPMessage. It results in inlined base64 encoded data and it remains so when the data is written over the wire as attachment. This is done in order to avoid unnecessary conversion to and from when handlers are being used. In short: when handlers are used, MTOM optimization does not happen.

### `xmime:expectedContentType` to Java type mapping

An schema element of type `xs:bas64Binary` or `xs:hexBinary` can be annotated by using attribute reference using `xmime:expectedContentType` JAXB 2.0 specification defines `xmime:expectedContentType` to Java type mapping in . Here is this table:

`xmime:expectedContentType` to Java type mapping

MIME Type | Java Type
--- | ---
`image/gif` | `java.awt.Image`
`image/jpeg` | `java.awt.Image`
`text/plain` | `java.lang.String`
`text/xml` or `application/xml` | `javax.xml.transform.Source`
`*/*` | `javax.activation.DataHandler`

    <element name="image" type="base64Binary"/>

is mapped to `byte[]`

    <element name="image" type="base64Binary"
            xmime:expectedContentTypes="image/jpeg"
            xmlns:xmime="http://www.w3.org/2005/05/xmlmime"/>

is mapped to `java.awt.Image`

### `xmime:contentType` schema annotation

`xmime:contentType` schema annotation indicates the content-type of an XML element content whose type is `xs:base64Binary` or `xs:hexBinary`. The value of the attribute is a valid `content-type` string (e.g., "`text/xml; charset=utf-16`"). This attribute specifies the `content-type` of the element content on which it occurs. This annotation can be primarily used to indicate the `Content-Type` of binary data.

For example the schema type

    <element name="TestMtomXmimeContentType" type="types:PictureType"/>
    <complexType name="PictureType">
        <simpleContent>
            <restriction base="xmime:base64Binary">
                <attribute ref="xmime:contentType" use="required"/>
            </restriction>
        </simpleContent>
    </complexType>

Here `xmime:base64Binary` is defined by Describing Media Content of Binary Data in XML.

Gets mapped to PicutreType bean by `wsimport`:

     PictureType req = new PictureType();
    req.setValue(name.getBytes());
    req.setContentType("application/xml");

On the wire this is how it looks:

     <?xml version="1.0" encoding="UTF-8"?>
    <soapenv:Envelope xmlns:soapenv=" http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:xsd=" http://www.w3.org/2001/XMLSchema"
            xmlns:ns1=" http://example.org/mtom/data"
            xmlns:ns2="http://www.w3.org/2005/05/xmlmime">
        <soapenv:Body>
            <ns1:TestMtomXmimeContentTypeResponse
                    ns2:contentType="application/xml">
                <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
                        href="c id:193ed174-d313-4325-8eed-16cc25595e4e@example.org"/>
            </ns1:TestMtomXmimeContentTypeResponse>
        </soapenv:Body>
    </soapenv:Envelope>

### How to enable MTOM in JAX-WS 2.0

Enabling MTOM on Server:

- Enable using `@javax.xml.ws.soap.MTOM` annotation on the endpoint (SEI) implementation class

      @javax.xml.ws.soap.MTOM
      @WebService(endpointInterface = "mtom.server.Hello")
      public class HelloImpl implements Hello {
          // ...
      }

- MTOM can be also be enabled on an endpoint by specifying enable-mtom attribute to true on an endpoint element in sun-jaxws.xml deployment descriptor.

      <?xml version="1.0" encoding="UTF-8"?>
      <endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'
              version='2.0'>
          <endpoint name="Mtom"
                  implementation="mtom.server.HelloImpl"
                  url-pattern="/hello"
                  enable-mtom="true"/>
      </endpoints>

- Enable using `@BindingType` on the endpoint (SEI) implementation class

  - `@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING)` will enable MTOM on the deployed endpoint for SOAP 1.1 binding

  - `@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING)` will enable MTOM on the deployed endpoint for SOAP 1.2 binding

Enabling MTOM on Client:

- To enable MTOM on client-side, pass javax.xml.ws.soap.MTOMFeature as WebServiceFeature parameter while crating the Proxy or Dispatch. Here is the code snippet from the client `samples/mtom/src/mtom/client/MtomApp.java` of the mtom sample:

  - Hello port = new HelloService().getHelloPort(new MTOMFeature()); gives a proxy with MTOM enabled

  - javax.xml.ws.Service.createDispatch(....,new javax.xml.ws.soap.MTOMFeature()) gives a Dispatch instance with MTOM enabled

- JAX-WS 2.0 specification has defined API to enable and to check if the MTOM is enabled.

  - javax.xml.ws.soap.SOAPBinding.setMTOMEnabled(boolean enable) - enable or disable MTOM.

  - javax.xml.ws.soap.SOAPBinding.isMTOMEnabled() - returns true if MTOM is enabled otherwise false.

      Hello port = new HelloService.getHelloPort();
      //get the binding and enable mtom
      SOAPBinding binding = (SOAPBinding) ((BindingProvider) port).getBinding();
      boolean mtomEnabled = binding.isMTOMEnabled();

      binding.setMTOMEnabled(true);

### Attach vs In-line

As defined by JAXB 2.0 specification `xs:base64Binary` and `xs:hexBinary` mapping to java is `byte[]`. JAX-WS implementation has set a threshold of 1KB of `byte[]` size. This threshold can be modified using implementation specific property `com.sun.xml.ws.developer.JAXWSProperties.MTOM_THRESHOLD_VALUE` in the `RequestContext` on the client side and in the `MessageContext` on the server side. If the `byte[]` that is being sent is less than this threshold (default is 1KB) then the binary data is base64 encoded by JAXB and in lined inside the SOAP Body otherwise the binary data is sent as attachment mime part in Multipart/Related package and XML infoset for the binary data is XOP encoded by JAXB

    <xop:Include href=...>

is used to reference the attachment. The XOP encoding and packaging is done as per described by the XOP packaging rules. The href is the the `Content-ID` of the attachment and is encoded as per CID URI scheme defined in RFC 2111. `xmime:contentType` attribute may appear on the element that includes binary data to indicate preferred media type as annotated on the corresponding schema.

#### How to specify MTOM data Threshold

Default threshold value for MTOM feature is 0 bytes. You can set a threshold value for MTOM by using `@MTOM` annotation on server-side or using MTOMFeature on client-side. Let's say you set MTOM threshold as 3000, this serves as hint to JAX-WS when to send binary dat as attachments. In this case, JAX-WS will send any byte array in the message thats equal to or larger than 3KB as attachment and the corresponding XML infoset will be XOP encoded (will contain reference to this attachment)

- On Server-side, `@MTOM(threshold=3000)`

- On Client-side, pass `MTOMFeature(3000)` as `WebServiceFeature` as mentioned in , while creating the proxy/dispatch.

### MTOM Samples

MTOM Sample - mtom

This is SOAP 1.1 MTOM SampleThis is how the JAX-WS generated XOP packaged SOAP message looks on the wire:

    Content-Type: Multipart/Related; start-info="text/xml"; type="application/xop+xml";
        boundary="----=_Part_0_1744155.1118953559416"
    Content-Length: 3453
    SOAPAction: ""

        ------=_Part_1_4558657.1118953559446
    Content-Type: application/xop+xml; type="text/xml"; charset=utf-8

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Body>
            <Detail xmlns="http://example.org/mtom/data">
                <Photo>RHVrZQ==</Photo>
                <image>
                    <xop:Include
                            xmlns:xop="http://www.w3.org/2004/08/xop/include"
                            href="cid:5aeaa450-17f0-4484-b845-a8480c363444@example.org"/>
                </image>
            </Detail>
        </soapenv:Body>
    </soapenv:Envelope>

    ------=_Part_1_4558657.1118953559446
    Content-Type: image/jpeg
    Content-ID: <5aeaa450-17f0-4484-b845-a8480c363444@example.org>

     ╪
        α ►JFIF ☺☻ ☺ ☺ █ ♠♠
    ♀¶
    ♀♂♂♀↓↕‼☼¶↔→▼▲↔→∟∟
        $.' ",#∟∟(7),01444▼'9=82<.342 █ C☺ ♀♂♀↑↑2!∟!22222222222222222222222222222222222222222222

    222222 └ ) ¬♥☺" ☻◄☺♥◄☺ ─ ▼ ☺♣☺☺☺☺☺☺
        ☺☻♥♦ ♂ ─ ╡► ☻☺♥♥☻♦♥♣♣♦♦
        ☺}☺☻♥ ♦◄♣↕!1A♠‼Qa"q¶2?#B▒┴§R╤≡$3bré

    ▬↨↑↓→%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzâäàåçêëèÆôöòûùÿÖÜóúñÑªº¿⌐¬▓│┤╡╢╖╕╣║┬├─┼╞╟╚╔╩╥╙╘╒╓╫╪┘┌ßΓπΣσµτΦΘΩ±≥≤⌠⌡÷≈°∙·
        ─

Above Photo is inlined binary data because its less than 1KB and image which is more than 1KB is sent as attachment. Here is the associated schema:

    <element name="Detail" type="types:DetailType"/>
    <complexType name="DetailType">
        <sequence>
            <!-- mapped to byte[] -->
            <element name="Photo" type="base64Binary"/>
            <!-- mapped tojava.awt.Image -->
            <element name="image" type="base64Binary"
                    xmime:expectedContentTypes="image/jpeg"/>
        </sequence>
    </complexType>

MTOM Sample - mtom-soap12

This is SOAP 1.2 MTOM Sample. Here is how the JAX-WS generated soap message looks on the wire:

    <element name="image" type="base64Binary" xmime:expectedContentTypes="image/jpeg"/>

    Content-Type:
        Multipart/Related; start-info="application/soap+xml"; type="application/xop+xml";
        boundary="----=_Part_0_1744155.1118960238280"
    Content-Length: 1946
    SOAPAction: ""

    ------=_Part_1_4558657.1118960238320
    Content-Type: application/xop+xml; type="application/soap+xml"; charset=utf-8

    <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
        <soapenv:Body>
            <Detail xmlns="http://example.org/mtom/data">
                <Photo>RHVrZQ==</Photo>
                <image>
                    <xop:Include
                            xmlns:xop="http://www.w3.org/2004/08/xop/include"
                            href="cid:42a7ee0a-20ee-426b-a135-094d72bc138f@example.org"/>
                </image>
            </Detail>
        </soapenv:Body>
    </soapenv:Envelope>

    ------=_Part_1_4558657.1118960238320
    Content-Type: application/octet-stream
    Content-ID: <42a7ee0a-20ee-426b-a135-094d72bc138f@example.org>

     ╪ α ►JFIF ☺☻ ☺ ☺ █ ♠♠
    ♀¶

        ♀♂♂♀↓↕‼☼¶↔→▼▲↔→∟∟
        $.' ",#∟∟(7),01444▼'9=82<.342 █ C☺ ♀♂♀↑↑2!∟!22222222222222222222222222222222222222222222

    222222 └ ' )♥☺" ☻◄☺♥◄☺ ─ ▼ ☺♣☺☺☺☺☺☺
        ☺☻♥♦ ♂ ─ ╡► ☻☺♥♥☻♦♥♣♣♦♦
        ☺}☺☻♥ ♦◄♣↕!1A♠‼Qa"q¶2?#B▒┴§R╤≡$3bré

    ▬↨↑↓→%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzâäàåçêëèÆôöòûùÿÖÜóúñÑªº¿⌐¬▓│┤╡╢╖╕╣║┬├─┼╞╟╚╔╩╥╙╘╒╓╫╪┘┌ßΓπΣσµτΦΘΩ±≥≤⌠⌡÷≈°∙·
        ─
     ▼☺ ♥☺☺☺☺☺☺☺☺☺ ☺☻♥♦

## swaRef

WS-I Attachment Profile 1.0 defines mechanism to reference MIME attachment parts using swaRef. In this mechanism the content of XML element of type `wsi:swaRef` is sent as MIME attachment and the element inside SOAP Body holds the reference to this attachment in the CID URI scheme as defined by RFC 2111.

### swaRef in JAX-WS 2.0

JAXB 2.0 defines mapping of `wsi:swaRef` schema type to javax.activation.DataHandler. An application will construct the DataHandler with the data and the appropriate MIME type and JAX-WS will coordinate with JAXB and SAAJ to send it as attachment MIME part.

### How to use swaRef

An XML element of type `wsi:swaRef` is mapped to a DataHandler and is sent as attachment over the wire. For example,

    <element name="claimForm" type="wsi:swaRef"
            xmlns:wsi="http://ws-i.org/profiles/basic/1.1/xsd"/>

will be sent over the wire as :

    Content-Type: Multipart/Related; start-info="text/xml"; type="application/xop+xml";
        boundary="----=_Part_4_32542424.1118953563492"
    Content-Length: 1193
    SOAPAction: ""

    ------=_Part_5_32550604.1118953563502
    Content-Type: application/xop+xml; type="text/xml"; charset=utf-8

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Body>
            <claimForm xmlns="http://example.org/mtom/data">
                cid:b0a597fd-5ef7-4f0c-9d85-6666239f1d25@example.jaxws.sun.com
            </claimForm>
        </soapenv:Body>
    </soapenv:Envelope>

    ------=_Part_5_32550604.1118953563502
    Content-Type: application/xml
    Content-ID: <b0a597fd-5ef7-4f0c-9d85-6666239f1d25@example.jaxws.sun.com>

    <?xml version="1.0" encoding="UTF-8"?>
    <application xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocaption="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/application_1_4.xsd" version="1.4">
        <display-name>Simple example of application</display-name>
        <description>Simple example</description>
        <module>
            <ejb>ejb1.jar</ejb>
        </module>
        <module>
            <ejb>ejb2.jar</ejb>
        </module>
        <module>
            <web>
                <web-uri>web.war</web-uri>
                <context-root>web</context-root>
            </web>
        </module>
    </application>

### swaRef Sample

Refer to swaRef sample `testSwaRef()` method in `samples/mime/src/mime/client/MimeApp.java`