Back to Web Services Resources and Tutorials
The addition of attachments (and the desire to provide integrity, confidentiality, and so on) makes for a significantly more complex web service than the "ping" tutorials elsewhere on this site. For this reason, this attachments tutorial will be relatively self-contained (describing both service-side and client-side components)
There are a couple of ways available to describe SOAP messages with attachments in WSDL, and the choice you make affects the complexity of the implementation of your service, including introducing platform-specific (e.g., Axis vs Sun) service- side code. For this reason, this detailed overview is provided to describe the structure of a SOAP message with attachments, and the options available for accessing it and the attachment parts..
Structure of a SOAP Message with Attachments
SOAP messages with attachments are typically transmitted as multipart/related messages, where the SOAP body, with content type text/xml, is sent as the first part and attachments are sent as related attachment parts. Below is an example of such a message, consisting of a SOAP body, a text attachment, and a base64-encoded binary attachment. The binary attachment has a content type of "text/plain" because it has been base64-encoded and the default mime types file does not include a generic type for application octet streams.
------=_Part_0_26210109.1137707495730 Content-Type: text/xml; charset=utf-8 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><tutorial:PingRequest xmlns:tutorial="h ttp://example.com/schema/tutorial"><requestParam>ping</requestParam></tutorial:PingRequest></SOAP-ENV:Body></SOAP-ENV:Envelope> ------=_Part_0_26210109.1137707495730 Content-Type: text/plain Content-Id: C:/dev/SAAJ_Tutorial/plainText.txt This is a file with plain text content. ------=_Part_0_26210109.1137707495730 Content-Type: text/plain Content-Id: C:/dev/SAAJ_Tutorial/next.png iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMA ... H3ABF0I0VWXbmVpJRgrAj7iIcyGa/Nf+zRzMs+SE3FRTTTVKPwFMB4uc7mE45AAAAABJRU5ErkJggg== ------=_Part_0_26210109.1137707495730--The SOAP body, as packaged, then, is "unaware" of the existence of the other parts (except for possibly containing elements referencing the attachments). Note that this packaging convention does not on the surface appear to mesh well with the skeleton/tie-generation approach used by most WSDL-to-Java tools. In other words, while the operations of the WSDL portTypes may be implemented as Java methods, that pattern may or may not provide access to the entire message sent, depending on how you structure the WSDL. It is usually possible to access the attachment parts in this scenario, but the code to do so is very web-service-platform specific, as will be described below.
There are two common approaches for describing operations involving attachments. One approach is to include the attachment directly in the WSDL message as a part, and to manipulate it directly in the resulting generated tie. In the second approach, you do not directly describe the attachment parts in the WSDL messages but include references to them. Your service-side code will then retrieve the attachments by reference. These two approaches produce fundamentally different WSDL and generated code, so they are discussed in separate subsections, below.
Direct description of the attachments:
In the following WSDL snippet,
<wsdl:message name="DocumentIn">
<wsdl:part name="body" element="swa:DocumentSubmission" />
<wsdl:part name="document" type="xsd:hexBinary"/>
</wsdl:message>
...
<input>
<mime:multipartRelated>
<mime:part>
<soap:body use="literal" />
</mime:part>
<mime:part>
<mime:content part="document" type="binary" />
</mime:part>
</mime:multipartRelated>
</input>
The input message of a document-submission request is constructed of a body
element, based on a schema defined within the WSDL document, and a binary
attachment. When the input of the document-submission operation is defined,
the "body" part is defined a a document/literal SOAP body, and the binary
"document" is referenced as a separate MIME part, all within the context of a
multipart-related message. The example WSDL file being discussed here can be
found at swaDirect.wsdl.
Using the Sun wscompile utility to generate bean classes and the service-side classes with the command
wscompile -import -keep -classpath . -d src/server -f:documentliteral,wsi configWsaDirect.xml -mapping descriptors/jaxrpc-mapping.xml(where the wscompile config file can be found at configWsaDirect.xml) yields the following method signature for the "DocumentIn" message:
public com.example.DocumentSubmissionConfirmationType documentSubmission(com.example.DocumentSubmissionType body, javax.activation.DataHandler document) throws java.rmi.RemoteException;Note that a DataHandler has been supplied to deal with the document. You can get an input stream on this DataHandler and obtain the document contents directly.
Defining attachment references:
The other commonly-used method to specify SOAP messages with attachments is to reference the attachment, rather than create a message-definition part for it. To support this method, the WS-I defines a swaRef reference type in its Basic Profile 1.1 (see Resources); the definition of this type is
<xsd:schema targetNamespace="http://ws-i.org/profiles/basic/1.1/xsd">
<xsd:simpleType name="swaRef">
<xsd:restriction base="xsd:anyURI"/>
</xsd:simpleType>
</xsd:schema>
We will use this schema to reference the attachment in the types section
of the WSDL file; there will then be no WSDL part defined in the "DocumentIn"
message for the document, as the main SOAP body will contain a reference to the
document. The service-side implementation code will then use the reference value
to locate the document in the multipart-related message. An example WSDL file which
uses this approach can be found at swaRef.wsdl. The
input document is defined as
<xsd:complexType name="DocumentSubmissionType">
<xsd:sequence>
<xsd:element name="DocumentName" type="xsd:string" />
<xsd:element name="Document" type="ref:swaRef" />
</xsd:sequence>
</xsd:complexType>
where the "ref" prefix refers to the Basic Profile schema which is imported
within the types section. Note that the reference is now part of the
SOAP body; meanwhile, the "document" part in the message
definition is gone, as is the MIME part referring to it in the binding:
<message name="DocumentIn">
<part name="body" element="swa-schema:DocumentSubmission" />
</message>
...
<input>
<mime:multipartRelated>
<mime:part>
<soap:body use="literal" />
</mime:part>
</mime:multipartRelated>
</input>
Again running the wscompile utility, this time with a config file which references the new WSDL file (an example is at configWsaRef.xml), using the command
wscompile -import -keep -classpath . -d src/server -f:documentliteral,wsi configWsaRef.xml -mapping descriptors/jaxrpc-mapping.xmlyields the following method signature for the "DocumentIn" message:
public com.example.DocumentSubmissionConfirmationType documentSubmission(com.example.DocumentSubmissionType body) throws java.rmi.RemoteException;Note that the DocumentHandler argument is gone, as expected. The obvious next question is, how to access the attachments from within the method implementation? Since the attachment is "outside" of the SOAP body, how can the service access it from a method which essentially only knows about the SOAP body? At this point, the answers depend on the web service platform; the next sub-section describes three possible approaches.
You might notice that there is nothing to stop the WSDL author from both using approaches -- that is, using the reference and describing the attachment as a part and MIME attachment. The only problem, and this is from an interoperability standpoint, is that there is no way in WSDL 1.1 to correlate the reference to the WSDL attachment part. For this reason, the WS-I Attachments Profile (see Resources) recommends that you use only one of the approaches defined here (see requirements R2940 and R2928 in that profile).
Accessing attachments via references:
If you need to access a MIME attachment that is not referenced as a WSDL message part, the process for doing so is typically platform-specific. This sub-section describes this process for the Sun Application Server and the Axis platform, as well as a generic servlet-based approach which is valid for any Java-based web service platform. Note that standardizing access to the SOAP message is a goal of JAX-WS 2.0, the next generation of JAX-RPC; see Resources).
On the Sun platform you can gain access to the message attachments with the following procedure:
In Apache Axis, the org.apache.axis.MessageContext is available from anywhere within Java code that you deploy as a web service, as described in the Axis User's Guide (see Resources). The context is retrieved using the static getCurrentContext() method:
/**
* Get the active message context.
*
* @return the current active message context
*/
public static MessageContext getCurrentContext() {
return AxisEngine.getCurrentMessageContext();
}
That said, it is always possible to deploy a Java servlet which has access to the entire message, SOAP body and attachments; the manipulation of the resulting SOAP message is quite straightforward using the SOAP with Attachments API for Java (SAAJ). And, it is also possible to implement a web service in this way without any need for "helper" tools. In most cases, though, it will still be helpful to at least generate Java class bindings for the web services documents. These points will be discussed and resolved in the course of the tutorial.
Once you have access to the attachments of a SOAP message, you can then locate a reference via its content ID. Specific examples of how to do this are outlined in the various platform tutorials. Note that the WS-I Attachments Profile specifies the format of these content IDs, to promote interoperability.
Back to Top
Back to Web Services Resources and Tutorials