Chapter 10. Transmitting Messages Using MIME Attachment

Table of Contents

10.1. Overview
10.2. MTOM/XOP
10.2.1. Basic Operations
10.2.2. Binary Data Attachment Size Configuration
10.2.3. Example of MTOM/XOP
10.2.4. Executing MTOM/XOP Example
10.3. swaRef
10.3.1. Using swaRef
10.3.2. Example of swaRef
10.3.3. Executing swaRef Example
10.4. Processing Attachments Using Streaming Method

This chapter describes how to transmit a message with a MIME attachment.

10.1. Overview

In implementing a web service, a parameter or return value from a client or server is included in the SOAP message body as a payload, and the message is transmitted over the network. If the parameter or return value is a large binary data containing photo or music, the performance may be compromised.

JAX-WS web services optimize and send such large binary data, defined as the xs:base64Binary or xs:hexBinary element, through MTOM(Message Transmission and Optimization Mechanism) and XOP(XML Binary Optimized Packaging). In addition, it provides a schema called swaRef to transmit all contents of XML elements, which are defined by the schema, as MIME attachments.

In JEUS 8, JAX-WS can send and receive an attachment through the streaming method by using the MessageContext property. This is useful for receiving a large attachment.

10.2. MTOM/XOP

MTOM(Message Transmission and Optimization Mechanism) and XOP(XML Binary Optimized Packaging) define how an XML binary data, such as xs:base64Binary or xs:hexBinary, is optimized for the network and transmitted.

Since an XML type like xs:base64Binary is included in a SOAP envelope when transmitted, the larger the data is the lower the efficiency will be. To resolve this issue, MTOM XOP packages the data into a MIME attachment if the binary data size is larger than the specified value. When the xs:base64Binary or xs:hexBinary element is XOP-packaged into a MIME attachment, the Context-Type of the attachment can be specified as the xmime:expectedContentType attribute value, and the type mapping supported by JAXB is applied to the Context-Type.

An xs:base64Binary or xs:hexBinary schema element is included in a MIME attachment as a MIME type when the size of the element value exceeds the maximum limit. This happens when the element is used with the xmime:expectedContentType attribute setting, which applies the type mapping supported by JAXB to the element. When the xmime:expectedType attribute is not used, it is mapped to a general byte[ ] type. However, if the element value is larger than the maximum value, it is included in the Content-Type of the MIME attachment as a value type like "application/octet-stream".

The following is the JAXB type mapping of the xmime:expectedContentType to a Java type.

[Table 10.1] JAXB 2.0 specification of xmime:expectedContentType to Java type mapping

MIME-TypeJava Type
image/gifjava.awt.Image
image/jpegjava.awt.Image
text/plainjava.lang.String
text/xml or application/xmljavax.xml.transform.Source
*/*javax.activation.DataHandler

An element such as <element name="image" type="base64Binary"/> is simply mapped to the byte[ ] type, but other elements such as <element name="image" type="base64Binary" xmime:expectedContentTypes="image/jpeg" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"/> are mapped to the java.awt.Image type.

10.2.1. Basic Operations

An element, which is defined as the xs:base64Binary or xs:hexBinary type in wsdl:type of the WSDL document, is defined as the xmime:expectedContentType attribute. When the service interface and portable artifacts are created using a particular type mapping of JAXB through the wsimport tool, the client and server can execute the MTOM/XOP environment.

MTOM Operation on a Server

The following example shows how to add the @javax.xml.ws.soap.MTOM annotation to a service endpoint implementation class in order to run MTOM on the server side.

@javax.xml.ws.soap.MTOM
@WebService (endpointInterface = "com.tmax.mtom.Server")
public class ServerImpl implements Server {
    ...
}

As an alternative method, MTOM can be run by adding the @BindingType annotation to the service endpoint implementation class as shown in the following example.

@BindingType(value=javax.xml.ws.SOAPBinding.SOAP11HTTP_MTOM_BINDING)
@BindingType(value=javax.xml.ws.SOAPBinding.SOAP12HTTP_MTOM_BINDING)

MTOM Operation on a Client

The following example shows how to obtain a proxy or dispatch object through the javax.xml.ws.soap.MTOMFeature parameter to run MTOM from the client side.

Server port = new ServerService().getServerPort(new MTOMFeature());
javax.xml.ws.Service.createDispatch(..., new javax.xml.ws.soap.MTOMFeature())

The following example shows how to use the obtained proxy or dispatch object to check whether or not MTOM is configured.

Server port = new ServerService.getServerPort();
SOAPBinding binding = (SOAPBinding)((BindingProvider)port).getBinding();
boolean mtomEnabled = binding.isMTOMEnabled();
binding.setMTOMEnabled(true);

10.2.2. Binary Data Attachment Size Configuration

In a JAX-WS web service, if the size of a java object of the xs:base64Binary or xs:hexBInary type is larger than one kilobyte, it is XOP-encoded as a MIME attachment when it is transmitted from the client or server. The attachment is either packaged into a message or just included in the SOAP message.

When it is XOP-encoded and packaged into a message, the original element is configured with a value of the form <xop:Include href=...>, and the href attribute value of the element is set to the Content-ID of the attachment. The Content-Type of the attachment is set to the xmime:expectedContentTypes attribute value of the type defined as the schema's xs:base64Binary or xs:hexBinary.

The size of the binary data that will be treated as an attachment is set in the following way.

  • @MTOM Annotation is used to configure the server.

    @javax.xml.ws.soap.MTOM(threshold=3000)
    @WebService (endpointInterface = "com.tmax.mtom.Server")
    public class ServerImpl implements Server {
        ...
    }
  • MTOMFeature class is used to configure the client.

    Server port = new ServerService().getServerPort(new MTOMFeature(3000));
    javax.xml.ws.Service.createDispatch(..., new javax.xml.ws.soap.MTOMFeature())

The following is the actual schema of wsdl:type in WSDL.

<element name="Detail" type="types:DetailType"/>
<complexType name="DetailType">
    <sequence>
        <element name="Photo" type="base64Binary"/>
        <element name="image" type="base64Binary"
            xmime:expectedContentTypes="image/jpeg"/>
    </sequence>
</complexType>

The following is the message that is transmitted over the network.

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">
                </xop:Include>
            </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!∟!222222222222222222222222222222222
22222222222 222222 └ ) ¬♥☺" ☻◄☺♥◄☺ ─ ▼ ☺♣☺☺☺☺☺☺ ☺☻♥♦ ♂ 
─ ╡► ☻☺♥♥☻♦♥♣♣♦♦ ☺}☺☻♥ ♦◄♣↕!1A♠‼Qa"q¶2?#B▒┴§R╤≡$3bré ▬
↨↑↓→%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzâäàåçêëèÆôöòûùÿÖÜ
óúñѪº¿⌐¬▓│┤╡╢╖╕╣║┬├─┼╞╟╚╔╩╥╙╘╒╓╫╪┘┌ßΓπΣσµτΦΘΩ±
≥≤⌠⌡÷≈°∙· ─ 

10.2.3. Example of MTOM/XOP

The following is an example of WSDL file to which MTOM/XOP has been applied.

[Example 10.1] << hello.wsdl >>

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:types="http://tmaxsoft.com/mtom/data"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://tmaxsoft.com/mtom"
    targetNamespace="http://tmaxsoft.com/mtom" name="mtom">
    <wsdl:types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://tmaxsoft.com/mtom/data"
            xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
            elementFormDefault="qualified">
            <complexType name="DetailType">
                <sequence>
                     <element name="image" type="base64Binary"
                        xmime:expectedContentTypes="image/jpeg" />
                </sequence>
            </complexType>
            <element name="Detail" type="types:DetailType" />
            <element name="DetailResponse" type="types:DetailType" />
        </schema>
    </wsdl:types>
    <wsdl:message name="HelloIn">
        <wsdl:part name="data" element="types:Detail" />
    </wsdl:message>
    <wsdl:message name="HelloOut">
        <wsdl:part name="data" element="types:DetailResponse" />
    </wsdl:message>
    <wsdl:portType name="Hello">
        <wsdl:operation name="Detail">
            <wsdl:input message="tns:HelloIn" />
            <wsdl:output message="tns:HelloOut" />
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="HelloBinding" type="tns:Hello">
        <soap:binding style="document"
            transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="Detail">
            <soap:operation />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="HelloService">
        <wsdl:port name="HelloPort" binding="tns:HelloBinding">
            <soap:address location="REPLACE_WITH_ACTUAL_URL" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>


As shown in the previous example, the base64Binary type of the image element is defined in the schema of the DetailType element, and it can be managed by MTOM. Since the image type attribute is declared as xmime:expectedContentTypes="image/ jpeg", the Content-Type will be set to "image/jpeg" when it is handled as an attachment by MTOM.

10.2.4. Executing MTOM/XOP Example

This section shows how to execute a handler framework by using the implemented classes and other configuration files in this section.

Create a service configured to use MTOM, and deploy it to JEUS.

$ ant deploy

Since the client is processed by using the wsimport tool, it can only be built after the service has been deployed.

As shown in the following example, create a client in which MTOM is configured and invoke the service. Enter the command in the console, and the console will display the message exchanges between the client and service.

$ ant run

...

Host: localhost:8088
Content-length: 4848
Content-type: multipart/related;type="application/xop+xml";boundary="uuid:23ba19
3c-bd1a-4323-abdd-339bf5c05cd1";start-info="text/xml"
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2,
*/*; q=.2
Connection: keep-alive
Soapaction:
User-agent: JAX-WS RI 2.2 - JEUS 8
--uuid:23ba193c-bd1a-4323-abdd-339bf5c05cd1
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
Content-Transfer-Encoding: binary

<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envel
ope/"><S:Body><Detail xmlns="http://tmaxsoft.com/mtom/data"><image><Include xmln
s="http://www.w3.org/2004/08/xop/include" href="cid:dc0fa852-3d46-4bac-9ad4-889d
59c6198a@example.jaxws.sun.com"/></image></Detail></S:Body></S:Envelope>
--uuid:23ba193c-bd1a-4323-abdd-339bf5c05cd1
Content-Type: image/jpeg
Content-Id: <dc0fa852-3d46-4bac-9ad4-889d59c6198a@example.jaxws.sun.com>
Content-Transfer-Encoding: binary

??JFIF

...

10.3. swaRef

When a JAX-WS web service is created by defining an element in wsdl:type of WSDL as wsi:swaRef, a schema type, the transmitted message includes the element value as a MIME attachment.

The element value in the SOAP message body is a reference to the attachment. The element of wsi:swaRef schema is mapped to a Java class of the javax.activation.DataHandler type.

10.3.1. Using swaRef

The wsi:swaRef type of XML element is mapped to the DataHandler java class, but it is actually transmitted as an attachment over the network.

For example, the XML schema is defined in WSDL as in the following.

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

If a user creates a web service with the WSDL document by using the wsimport tool and transmits a message over the network, the message will look like the following.

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>

10.3.2. Example of swaRef

The following is an example of a WSDL file to which swaRef has been applied.

[Example 10.2] << hello.wsdl >>

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:types="http://tmaxsoft.com/swaref/data"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://tmaxsoft.com/swaref"
    targetNamespace="http://tmaxsoft.com/swaref" name="swaref">
    <wsdl:types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://tmaxsoft.com/swaref/data"
            xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
            elementFormDefault="qualified"
            xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd">
            <import namespace="http://ws-i.org/profiles/basic/1.1/xsd"
                schemaLocation="wsi-swa.xsd" />
            <element name="claimForm" type="ref:swaRef" />
            <element name="claimFormResponse" type="ref:swaRef" />
        </schema>
    </wsdl:types>
    <wsdl:message name="claimFormIn">
        <wsdl:part name="data" element="types:claimForm" />
    </wsdl:message>
    <wsdl:message name="claimFormOut">
        <wsdl:part name="data" element="types:claimFormResponse" />
    </wsdl:message>
    <wsdl:portType name="Hello">
        <wsdl:operation name="claimForm">
            <wsdl:input message="tns:claimFormIn" />
            <wsdl:output message="tns:claimFormOut" />
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="HelloBinding" type="tns:Hello">
        <soap:binding style="document"
            transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="claimForm">
            <soap:operation />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="HelloService">
        <wsdl:port name="HelloPort" binding="tns:HelloBinding">
            <soap:address location="REPLACE_WITH_ACTUAL_URL" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>


As shown in the previous example, the claimForm and claimFormResponse elements are defined as ref:swaRef, a swaRef data type, by using the external schema, wsi-swa.xsd. Hence, they will be transmitted as an attachment over the network.

10.3.3. Executing swaRef Example

This section describes how to execute a handler framework by using the implemented classes and other configuration files in this section.

Create a service configured to use swaRef, and deploy it to JEUS.

$ ant build deploy

Since the client is processed using the wsimport tool, it can only be built after the service has been deployed.

As shown in the following example, create a client in which swaRef is configured and invoke the service. Enter the command in the console, and the console will display the message exchanges between the client and service.

$ ant run
...

Host: localhost:8088
Content-length: 2672
Content-type: multipart/related; type="text/xml"; boundary="uuid:26973efe-2e29-4
36a-8fce-3fa58b6fd91f"
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2,
*/*; q=.2
Connection: keep-alive
Soapaction:
User-agent: JAX-WS RI 2.2 - JEUS 8
--uuid:26973efe-2e29-436a-8fce-3fa58b6fd91f
Content-Type: text/xml

<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envel
ope/"><S:Body><claimForm xmlns="http://tmaxsoft.com/swaref/data">cid:40b15647-3c
0b-4449-90ad-29b1667e940b@example.jaxws.sun.com</claimForm></S:Body></S:Envelope
>
--uuid:26973efe-2e29-436a-8fce-3fa58b6fd91f
Content-Id:<40b15647-3c0b-4449-90ad-29b1667e940b@example.jaxws.sun.com>
Content-Type: text/xml
Content-Transfer-Encoding: binary

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:types="http://tmaxsoft.com/swaref/data"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://tmaxsoft.com/swaref"
    targetNamespace="http://tmaxsoft.com/swaref" name="swaref">
...

10.4. Processing Attachments Using Streaming Method

When transmitting and receiving a SOAP message with an attachment, JEUS 8 JAX-WS web service can send or receive the attachment by using the Streaming method instead of being processed in memory. This function improves the performance of invoking a web service endpoint when the attached file size is large. Especially when the file size is larger than the JVM Heap size, this function can be used to send and receive the attachment without an OutOfMemory error.

This section describes how a web service client transmits an attachment included in the Outbound SOAP message by using the streaming method.

Set a web service client to transmit an outbound request message with chunked transfer-encoding. Set the following property for the requested MessageContext from the service port, before invoking a web service operation on the service port (sending an outbound request message).

  • Property Key: "com.sun.xml.ws.transport.http.client.streaming.chunk.size"

  • Property Value: chunked data size

This property enables JAX-WS HTTP transport to transmit an HTTP request by using the Chunked Streaming method, which is supported by JEUS 8 server.

[Example 10.3] << AttachmentApp.java >>

Hello port = new HelloService().getHelloPort(
    new jeus.webservices.jaxws.api.transport.http.AttachmentFeature());

Map<String, Object> reqCnt = ((BindingProvider)port).getRequestContext();
reqCnt.put("com.sun.xml.ws.transport.http.client.streaming.chunk.size",
            new Integer(4*1024));


Note

Note that this method is not supported by all HTTP servers.