Table of Contents
This chapter describes how to transmit a message with a MIME attachment.
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 6, 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.
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-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 |
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.
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.
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)
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);
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âäàåçêëèÆôöòûùÿÖÜ óúñѪº¿⌐¬▓│┤╡╢╖╕╣║┬├─┼╞╟╚╔╩╥╙╘╒╓╫╪┘┌ßΓπΣσµτΦΘΩ± ≥≤⌠⌡÷≈°∙· ─
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.
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 7 --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 ...
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.
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>
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.
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 7 --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"> ...
When transmitting and receiving a SOAP message with an attachment, JEUS 7 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 7 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 that this method is not supported by all HTTP servers.