Example: Passing SOAP messages with attachments using WSIF
Information and example code for using the Web Services Invocation Framework (WSIF) SOAP provider to pass attachments within a MIME multipart/related message in such a way that the SOAP processing rules for a standard SOAP message are not changed. This includes how to write the WSDL extensions for SOAP attachments, and how to work with types and type mappings.
The W3C SOAP Messages with Attachments document describes a standard way to associate a SOAP message with one or more attachments in their native format (for example GIF or JPEG) using a multipart IME structure for transport. It defines specific use of the "Multipart/Related" MIME media type, and rules for the use of URI references to entities bundled within the MIME package. It thereby outlines a technique for carrying a SOAP 1.1 message within a MIME multipart/related message in such a way that the SOAP processing rules for a standard SOAP message are not changed.
WSIF supports passing attachments in a MIME message using the SOAP provider to link a WSIF service to a SOAP over HTTP service. The attachment is a javax.activation.DataHandler object. The mime:multipartRelated, mime:part and mime:content tags are used to describe the attachment in the WSDL.
- Example: Writing the WSDL extensions for SOAP attachments
- Example: Using WSIF to pass SOAP attachments
- SOAP attachments - Working with types and type mappings
- SOAP attachments - scenarios that are not supported
Example: Writing the WSDL extensions for SOAP attachments
The following example WSDL illustrates a simple operation that has one attachment called attch:
<binding name="MyBinding" type="tns:abc" > <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="MyOperation"> <soap:operation soapAction=""/> <input> <mime:multipartRelated> <mime:part> <soap:body use="encoded" namespace="http://mynamespace" encodingStyle="http://schemas.xmlsoap.org/soap/encoding"/> </mime:part> <mime:part> <mime:content part="attch" type="text/html"/> </mime:part> </mime:multipartRelated> </input> </operation> </binding>In this type of WSDL extension:
- There must be a part attribute (in this example attch) on the input message for the operation (in this example MyOperation). There can be other input parts to MyOperation that are not attachments.
- In the binding input there must either be a <soap:body> tag or a <mime:multipartRelated> tag, but not both.
- For MIME messages, the <soap:body> tag is inside a <mime:part> tag. There must only be one <mime:part> tag containing a <soap:body> tag in the binding input and that must not contain a <mime:content> tag as well, because a content type of text/xml is assumed for the <soap:body> tag.
- There can be multiple attachments in a MIME message, each described by a <mime:part> tag.
- Each <mime:part> tag that does not contain a <soap:body> tag contains a <mime:content> tag that describes the attachment itself. The type attribute inside the <mime:content> tag is not checked or used by the Web Services Invocation Framework (WSIF). It is there to suggest to the application that uses WSIF what the attachment contains. ultiple <mime:content> tags inside a single <mime:part> tag means that the backend service expects a single attachment with a type specified by one of the <mime:content> tags inside that <mime:part> tag.
- The parts="..." attribute (optional) inside the <soap:body> tag is assumed to contain the names of all the MIME parts as well as the names of all the SOAP parts in the message.
Example: Using WSIF to pass SOAP attachments
The following code fragment can invoke the service described by the example WSDL in Example: Writing the WSDL extensions for SOAP attachments:
import javax.activation.DataHandler; . . . DataHandler dh = new DataHandler(new FileDataSource("myimage.jpg")); WSIFServiceFactory factory = WSIFServiceFactory.newInstance(); WSIFService service = factory.getService("my.wsdl",null,null,"http://mynamespace","abc"); WSIFOperation op = service.getPort().createOperation("MyOperation"); WSIFMessage in = op.createInputMessage(); in.setObjectPart("attch",dh); op.executeInputOnlyOperation(in);The associated type mapping in the DeploymentDescriptor.xml file depends upon your SOAP server. For example if we use Tomcat with SOAP 2.3, then the DeploymentDescriptor.xml file contains the following type mapping:
<isd:mappings> <isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:x="http://mynamespace" qname="x:datahandler" javaType="javax.activation.DataHandler" java2XMLClassName="org.apache.soap.encoding.soapenc.MimePartSerializer" xml2JavaClassName="org.apache.soap.encoding.soapenc.MimePartSerializer" /> </isd:mappings>In this case, the backend service is invoked with the following signature:
public void MyOperation(DataHandler dh);We can also use stubs to pass attachments into the Web Services Invocation Framework (WSIF):
DataHandler dh = new DataHandler(new FileDataSource("myimage.jpg")); WSIFServiceFactory factory = WSIFServiceFactory.newInstance(); WSIFService service = factory.getService("my.wsdl",null,null,"http://mynamespace","abc"); yInterface stub = (MyInterface)service.getStub(MyInterface.class); stub.MyOperation(dh);Attachments can also be returned from an operation, but only one attachment can be returned as the return parameter.
SOAP attachments - Working with types and type mappings
By default, attachments are passed into WSIF as DataHandler objects. If the part on the message that is the DataHandler object maps to a <mime:part> tag in the WSDL, then WSIF automatically maps the fully qualified name of the WSDL type to the DataHandler class and sets up that type mapping with the SOAP provider.
In the WSDL, we might have defined a schema for the attachment (for instance as a binary[] type). WSIF silently ignores this mapping and treats the attachment as a DataHandler object, unless you explicitly issue a mapType() method. WSIF lets the SOAP provider set the MIME content type based on the type of the DataHandler object, instead of the type attribute specified for the <mime:content> tag in the WSDL.
SOAP attachments - scenarios that are not supported
The following scenarios are not supported:
- Use DIME.
- Passing in javax.xml.transform.Source and javax.mail.internet.MimeMultipart.
- Use the mime:mimeXml WSDL tag.
- Nesting a mime:multipartRelated tag inside a mime:part tag.
- Use types that extend DataHandler, Image, and so on.
- Use types that contain DataHandler, Image, and soon.
- Use Arrays or Vectors of DataHandlers, Images, and so on.
- Use multiple in/out or output attachments.
The MIME headers from the incoming message are not preserved for referenced attachments. The outgoing message contains new MIME headers for Content-Type, Content-Id and Content-Transfer-Encoding created by WSIF.
Use complex types Use WSIF to bind a JNDI reference to a web service Linking a WSIF service to the underlying implementation of the service Linking a WSIF service to a SOAP over HTTP service Interacting with the Java EE container in WAS Running WSIF as a client Use WSIF to invoke web services W3C SOAP essages with Attachments