The attachment model for JAX-RPC is Sw/A. Since JAX-RPC was written, a new attachment model has come onto the scene: MTOM. JAX-WS provides Sw/A support just as JAX-RPC does, but adds support for MTOM. JAX-WS supports MTOM via the Java Architecture for XML Binding (JAXB) specification, which includes APIs for marshalling and unmarshalling both Sw/A and MTOM attachments. In this tip, you examine both models through examples. Note: This tip compares only the WSDLs and the Java programming models; comparing the wire-level messages is left as an exercise to the reader.
Listing 1 shows the WSDL from an attachment tip written a few years ago (see Resources). Listing 2 shows the Java interface, which the JAX-RPC mapping produces from this WSDL.
Listing 1. JAX-RPC Sw/A WSDL
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://attachment.tip/">
<types/>
<message name="sendImage">
<part name="image" type="xsd:base64Binary"/>
</message>
<message name="sendImageResponse"/>
<message name="sendOctet">
<part name="octet" type="xsd:base64Binary"/>
</message>
<message name="sendOctetResponse"/>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</operation>
</portType>
<binding name="AttachmentBinding" type="tns:AttachmentTip">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="sendImage">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body parts="" namespace="http://attachment.tip/" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="image" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body parts="" namespace="http://attachment.tip/" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="octet" type="application/octet-stream"/>
</mime:part>
</mime:multipartRelated>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/SwAService/services/AttachmentTip"/>
</port>
</service>
</definitions> |
Listing 2. JAX-RPC Sw/A Java interface
package tip.attachment;
import java.awt.Image;
import java.rmi.Remote;
import java.rmi.RemoteException;
import javax.activation.DataHandler;
public interface AttachmentTip extends Remote {
public void sendImage(Image image) throws RemoteException;
public void sendOctet(DataHandler octet) throws RemoteException;
}
|
The Java interface mapping from the WSDL is fairly straightforward: The
sendImage operation's
image/jpeg part is mapped to a
java.awt.Image parameter; the
sendOctet operation's
application/octet-stream is mapped to a
javax.activation.DataHandler parameter. However,
there's a cost to this mapping: The Multipurpose Internet Mail Extensions (MIME) type information isn't in the interface
portion of the WSDL (the portType, message, and types sections). You must dip into
the binding to find the MIME information. This is unfortunate because different
bindings for the same WSDL interface could result in different types and,
therefore, map to different Java interfaces. It would be better if there were a
one-to-one mapping from WSDL interface to Java interface. If you have more than
one binding, each simply maps to an implementation, all of which implements the
same Java interface. With Sw/A, you can't do that; the mapping from
WSDL to Java interfaces is not one to one.
A secondary issue with Sw/A is that it doesn't lend itself well to the industry convention of document/literal wrapped WSDL (you'll notice that the WSDL in Listing 1 is an rpc/literal WSDL). Adding Sw/A content to a document/literal wrapped message requires specifying additional message parts beyond the single operation wrapper.
Does MTOM fix these issues? Let's move on to the next section to find out.
In Listing 3, we've modified the Sw/A WSDL from Listing 1 to produce an equivalent MTOM WSDL.
Listing 3. JAX-WS MTOM WSDL
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<types/>
<message name="sendImage">
<part name="image" type="xsd:base64Binary"/>
</message>
<message name="sendImageResponse"/>
<message name="sendOctet">
<part name="octet" type="xsd:base64Binary"/>
</message>
<message name="sendOctetResponse"/>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</operation>
</portType>
<binding name="AttachmentBinding" type="tns:AttachmentTip">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="sendImage">
<soap:operation soapAction=""/>
<input>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/>
</port>
</service>
</definitions>
|
The only real difference between the MTOM WSDL in Listing 3 and the Sw/A WSDL in Listing 1 is the binding. The MTOM binding contains no MIME information. In fact, there's no way to tell, from the WSDL, that you're dealing with attachments; the WSDL's binding looks like a normal binding.
Listing 4 shows the Java interface, which a JAX-WS mapping produces from this WSDL.
Listing 4. JAX-WS MTOM Java interface
package tip.attachment;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface AttachmentTip {
@WebMethod
public void sendImage(
@WebParam(name = "image", partName = "image")
byte[] image);
@WebMethod
public void sendOctet(
@WebParam(name = "octet", partName = "octet")
byte[] octet);
}
|
Because the WSDL is a normal-looking WSDL with no hint of attachments, you end up
with a Java interface that reflects that as well. Given parts of type
base64Binary (or hexBinary),
JAX-WS maps those to parameters of type byte[]. With MTOM, the MIME-ness of the
types has all been extracted from the WSDL with the burden placed on the client or
server run time to format the content appropriately.
The JAX-RPC Sw/A section noted two drawbacks to Sw/A:
- The MIME type info is in the WSDL binding, not the WSDL interface.
- It's difficult to create a document/literal wrapped attachment WSDL.
Let's discuss the document/literal wrapped style first.
document/literal wrapped style and attachments
We left the MTOM WSDL in Listing 3 as rpc/literal WSDL for comparison purposes; but it's an easy matter to turn this WSDL into document/literal wrapped WSDL. Listing 5 in the next section shows the document/literal wrapped equivalent of the WSDL in Listing 3 (see Resources for more information about the differences between various WSDL styles).
Because the MTOM WSDL's binding doesn't have any MIME information, you don't have to dip into the binding to determine the part types. You have everything you need in the WSDL interface to generate the Java interface. However, as you can see by comparing the Java interfaces in Listing 2 and Listing 4, we've lost some information.
The interface portion of both WSDLs shows that the data type in the operations
is base64Binary, which maps to byte[]. In the JAX-RPC
Sw/A WSDL, however, you know from the binding that the part types are a MIME image
and a MIME octet stream. In the JAX-WS MTOM WSDL, this information is lost. This
may seem like a bad thing, but the positive spin is that this completely cleans up
the interface. No matter what the binding, the interface is always the same. In
fact, the implementors of the client and the server codebases shouldn't be
bothered with the notion of whether the parameter is an attachment. That's
merely a detail of the SOAP message, and the writers of the WSDL-to-Java mappings
have tried their best to abstract the programmer away from the details of the SOAP
message.
However, if you really want to know what the MIME type is—if you want to get
back to the information you lost—JAX-WS provides support for an
attribute that
you can inject into an XML element:
expectedContentTypes. This special attribute is
highlighted in Listing 5. Listing 6 shows the corresponding Java interface.
Ignoring the annotations, this Java interface is essentially the same as the
interface in Listing 2.
Listing 5. JAX-WS MIME attribute
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<types>
<xsd:schema
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<xsd:element name="sendImage" type="tns:sendImage"/>
<xsd:complexType name="sendImage">
<xsd:sequence>
<xsd:element
xmlns:ns1="http://www.w3.org/2005/05/xmlmime"ns1:expectedContentTypes="image/*"
name="image"
type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sendImageResponse" type="tns:sendImageResponse"/>
<xsd:complexType name="sendImageResponse">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="sendOctet" type="tns:sendOctet"/>
<xsd:complexType name="sendOctet">
<xsd:sequence>
<xsd:element
xmlns:ns1="http://www.w3.org/2005/05/xmlmime"ns1:expectedContentTypes="application/octet-stream"
name="octet"
type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sendOctetResponse" type="tns:sendOctetResponse"/>
<xsd:complexType name="sendOctetResponse">
<xsd:sequence/>
</xsd:complexType>
</xsd:schema>
</types>
<message name="sendImage">
<part name="parameters" element="tns:sendImage"/>
</message>
<message name="sendImageResponse">
<part name="parameters" element="tns:sendImageResponse"/>
</message>
<message name="sendOctet">
<part name="parameters" element="tns:sendOctet"/>
</message>
<message name="sendOctetResponse">
<part name="parameters" element="tns:sendOctetResponse"/>
</message>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</operation>
</portType>
<binding name="AttachmentBinding" type="tns:AttachmentTip">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="sendImage">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/>
</port>
</service>
</definitions> |
Notice that this new attribute is wholly contained within the WSDL interface. It's not in the binding, so all of the type information is where you want it.
Listing 6. JAX-WS Java interface mapped from the MIME attribute
package tip.attachment;
import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
public interface AttachmentTip {
@WebMethod
@RequestWrapper(localName = "sendImage",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendImage")
@ResponseWrapper(localName = "sendImageResponse",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendImageResponse")
public void sendImage(
@WebParam(name = "image", targetNamespace = "")
Image image);
@WebMethod
@RequestWrapper(localName = "sendOctet",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendOctet")
@ResponseWrapper(localName = "sendOctetResponse",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendOctetResponse")
public void sendOctet(
@WebParam(name = "octet", targetNamespace = "")
DataHandler octet);
}
|
As mentioned earlier, JAX-WS relies on JAXB to handle the data binding for
most of its Web services content. The mapping for the
expectedContentTypes element is defined in Appendix H
of the JAXB 2.0 specification (see Resources). The JAXB 2.0 mappings are similar to the JAX-RPC
mappings. Compare these mappings in Table 1.
Table 1. MIME type to Java type mappings
| MIME type | JAX-RPC mapping | JAX-WS/JAXB mapping |
|---|---|---|
| image/gif | java.awt.Image | java.awt.Image |
| image/jpg | java.awt.Image | java.awt.Image |
| text/plain | java.lang.String | javax.xml.transform.Source |
| text/xml | javax.xml.transform.Source | javax.xml.transform.Source |
| application/xml | javax.xml.transform.Source | javax.xml.transform.Source |
| multipart/* | javax.mail.internet.MimeMultipart | javax.activation.DataHandler |
| all other types | javax.activation.DataHandler | javax.activation.DataHandler |
enabling/disabling attachment support
One of the of additional benefits of MTOM is the fact that you can turn it on or off. In the case of Sw/A, if one side or the other doesn't support sending Sw/A attachments, then the contract defined by the WSDL cannot be honored. On the other hand, if you have an MTOM WSDL such as that in listing 3 or 5, a client could choose to send data as an MTOM attachment or inline in the SOAP message. No matter what the client chooses, it can still interact with the Web service. MTOM is just an optimization of sending content, not a mandate like Sw/A.
JAX-WS still supports the Sw/A model. By default, JAX-WS maps a Sw/A attachment
to a byte[] on the Java interface, like the sample in Listing 4. To get the
mapping you are used to in JAX-RPC, you can use the
enableMIMEContent WSDL binding definition (see section
8.7.5 of the JAX-WS specification for more details). Listing 7 shows the JAX-WS
version of the Java interface equivalent to the JAX-RPC version of the interface
in listing 2.
Listing 7. JAX-WS Java interface with Sw/A attachments mapped from the mime:content
package tip.attachment;
import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface AttachmentTip {
@WebMethod
public void sendImage(
@WebParam(name = "image", partName = "image")
Image image);
@WebMethod
public void sendOctet(
@WebParam(name = "octet", partName = "octet")
DataHandler octet);
} |
JAX-RPC supports the Sw/A model. JAX-WS supports Sw/A as well, but it has also stepped up to the new MTOM model. MTOM is an improvement upon Sw/A in a number of ways:
- Everything necessary to create a Java interface is now available in the WSDL interface.
- MTOM is usable in a document/literal wrapped WSDL.
- MTOM allows optimization to attachments, but it doesn't force attachments like Sw/A does.
Learn
- Get the specification, API classes, and Javadocs
for:
- Learn about all the features of
Java 5.
- Read the
WSDL 1.1 specification.
- Check out the
SOAP version 1.2 primer.
- Learn about the
different styles of WSDL,
particularly the document/literal wrapped pattern.
- Get more details about
Sw/A and JAX-RPC.
- You can begin to evaluate JAX-WS features with
the
IBM®
WebSphere®
Application Server Version 6.1 Feature Pack for Web Services.
- The SOA and Web services zone on IBM developerWorks hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials on how to develop Web services
applications.
- Play in the IBM SOA Sandbox! Increase your SOA skills through practical, hands-on experience with the IBM SOA entry points.
- The IBM SOA Web site offers an overview of SOA and how IBM can help you get there.
- Stay current with developerWorks technical events and webcasts. Check out the following SOA and Web services tech briefings in particular:
- Get started on SOA with WebSphere's proven, flexible entry points
- Building SOA solutions and managing the service lifecycle
- SCA/SDO: To drive the next generation of SOA
- SOA reuse and connectivity
- Browse for books on these and other technical topics at the
Safari bookstore.
- Check out a quick Web services on demand demo.
- Get an RSS feed for this series. (Find out more about RSS.)
Get products and technologies
- Innovate your next development project with
IBM trial software, available for download or on DVD.
Discuss
- Participate in the discussion forum.
- Get involved in the developerWorks community
by participating in developerWorks blogs, including the following SOA
and Web services-related blogs:
- Service Oriented Architecture -- Off the Record with Sandy Carter
- Best Practices in Service-Oriented Architecture with Ali Arsanjani
- WebSphere SOA and J2EE in Practice with Bobby Woolf
- Building SOA applications with patterns with Dr. Eoin Lane
- Client Insights, Concerns and Perspectives on SOA with Kerrie Holley
- Service-Oriented Architecture and Business-Level Tooling with Simon Johnston
- SOA, ESB and Beyond with Sanjay Bose
- SOA, Innovations, Technologies, Trends...and a little fun with Mark Colan
Russell Butek is an IBM SOA/Web services consultant. He has been one of the developers of IBM's WebSphere Web services engine. He has also been a member the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache's Axis SOAP engine, driving Axis 1.0 to comply with JAX-RPC.
Nick Gallardo is an IBM software engineer working on the WebSphere platform. He has worked on various aspects of the Websphere Web services run time, with a concentration on the programming models. In addition, Nick is a member of the Apache Software Foundation and helped shape the support for JAX-WS within the Axis2 community.




