Sending attachments using MTOM/XOP
Message Transmission Optimization Mechanism (MTOM)/XML-binary Optimized Packaging (XOP) is standard to way by World Wide Web Consortium (W3C), to optimize the transmission/wire format of a SOAP message while maintaining the XML infoset. Below are some of the advantages of following MTOM/XOP approach:
For a very simple Web service which allows attachments (Axis2 supports byte[] as an argument in case of attachments):
public class WSAttachmentService {
public void sendAttachments(String customerId, byte[] attachment){
try{
System.out.println(" attachment 0 "+new String(attachment));
}catch(Exception ex){
ex.printStackTrace();
}
}
}
|
In the sample code above, once the runtime prints the System print statement, the attachment parameter will be initialized and as a result it is not necessary to have to use Axis2's MessageContext API to get the attachment out. This is true for both MTOM/XOP or without MTOM, but there are the advantages as stated above of using an MTOM/XOP enabled approach.
The code listing below highlights the difference between the wire formats of a MTOM/XOP enabled message versus a non-MTOM message for quick reference.
MTOM/XOP enabled vs Non-MTOM wire format
With the MTOM/XOP approach, the attachment while physically being outside of the
SOAP envelope still remains logically inside the SOAP envelope with a
<xop:Include> tag.
<attachment>
<xop:Include
href="cid:1.urn:uuid:CDA722FAE92D8929D81261259412433@apache.org"
xmlns:xop="http://www.w3.org/2004/08/xop/include" />
</attachment>
--MIMEBoundaryurn_uuid_CDA722FAE92D8929D81261259411181
Content-Type: text/plain
Content-Transfer-Encoding: binary
Content-ID: <1.urn:uuid:CDA722FAE92D8929D81261259412433@apache.org>
...binary content...
|
Without MTOM it will be an inline binary content as:
<attachment>
...binary content...
</attachment>
|
With the MTOM enabled SOAP message, the service will be able to obtain the Attachment transparently.
Axis2 runtime looks at Content-Type to be "Content-Type: multipart/related;" and the type (in the Content-Type only) to be "type="application/xop+xml";" to know if it is MTOM/XOP enabled or not.
POST /IdMWSAttachment/services/WSAttachmentService HTTP/1.1
Content-Type: multipart/related;
boundary=MIMEBoundaryurn_uuid_CDA722FAE92D8929D81261259411181;
type="application/xop+xml";
start="<0.urn:uuid:CDA722FAE92D8929D81261259411182@apache.org>";
start-info="text/xml"
SOAPAction: "urn:anonOutInOp"
User-Agent: Axis2
Host: localhost:8181
Transfer-Encoding: chunked
1ecf
--MIMEBoundaryurn_uuid_CDA722FAE92D8929D81261259411181
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.urn:uuid:CDA722FAE92D8929D81261259411182@apache.org>
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body><impl:sendAttachments xmlns:impl="http://attachment.ws.idm.sample.com">
<customerId>Vikas</customerId>
<attachment>
<xop:Include
href="cid:1.urn:uuid:CDA722FAE92D8929D81261259412433@apache.org"
xmlns:xop="http://www.w3.org/2004/08/xop/include" />
</attachment>
</impl:sendAttachments></soapenv:Body></soapenv:Envelope>
--MIMEBoundaryurn_uuid_CDA722FAE92D8929D81261259411181
Content-Type: text/plain
Content-Transfer-Encoding: binary
Content-ID: <1.urn:uuid:CDA722FAE92D8929D81261259412433@apache.org>
...binary...
|
The runtime uses the "href" attribute's value <xop:Include> which in the above case is cid:1.urn:uuid:CDA722FAE92D8929D81261259412433@apache.org, and the uses the value of "cid" to associate that to the attachment which is there in the SOAP message after "--MIMEBoundaryurn_uuid_CDA722FAE92D8929D81261259411181".
The following code listings demonstrate how Axis2 could be used to send a MTOM enabled message:
opts.setProperty(Constants.Configuration.ENABLE_MTOM,Constants.VALUE_TRUE); |
Also, the crucial point when using OMElement to build the attachment Element is the use of "true" in method call below on SOAPFactory as shown below:
createOMText(new DataHandler(fileDataSource), true);
// Start, Use with MTOM
FileDataSource fileDataSource = new FileDataSource("c:/dev2_aud.txt");
OMText data = fac.createOMText(new DataHandler(fileDataSource),
true); // parameter "true" is crucial
attachmentOM.addChild(data);
// End, Use with MTOM
|
WS-Signature and WS-Encryption
Next we begin to generate the WS-Signature and WS-Encrypted when using MTOM/XOP enabled attachments.
public OperationClient createSOAPRequestMsg(){
OperationClient operationClient = null;
String serverEPR =
"http://localhost:8181/IdMWSAttachment/services/WSAttachmentService";
try{
ServiceClient client = new ServiceClient();
operationClient = client.createClient(ServiceClient.ANON_OUT_IN_OP);
MessageContext outMsgCtx = new MessageContext();
Options opts = outMsgCtx.getOptions();
opts.setTo(new EndpointReference(serverEPR));
//opts.setProperty(Constants.Configuration.ENABLE_SWA,Constants.VALUE_TRUE);
opts.setProperty(Constants.Configuration.ENABLE_MTOM,Constants.VALUE_TRUE);
SOAPEnvelope envelope = creatSOAPEnvelopeAndReturnDocument();
// Now as the WSS4J API takes W3C Document object to work with, so now we have to cre
// W3C document using the above "envelope" (which is Axis2's API).
ByteArrayOutputStream baos = new ByteArrayOutputStream();
envelope.serialize(baos);
byte[] byts = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(byts);
// Here JAXP API
DocumentBuilderFactory docFac = DocumentBuilderFactory.newInstance();
docFac.setValidating(false);
docFac.setNamespaceAware(true);
DocumentBuilder builder = docFac.newDocumentBuilder();
Document document = builder.newDocument();
// Here now we would get the W3C document Object.
document = builder.parse(bais);
document = signSOAPEnvelopeMTOM(document);
outMsgCtx.setEnvelope(soapEnvelope);
// Next we convert the above W3C document object back to SOAPEnvelope
ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
OutputFormat of = new OutputFormat("XML","UTF-8",true);
of.setIndenting(true);
XMLSerializer serializer = new XMLSerializer(baos1,of);
serializer.asDOMSerializer();
serializer.serialize(document.getDocumentElement());
StringReader sr = new StringReader(baos1.toString());
OMXMLParserWrapper omBuilder = getOMBuilderStringReader(sr);
SOAPEnvelope soapEnvelope = (SOAPEnvelope) omBuilder.getDocumentElement();
// very important step
outMsgCtx.setEnvelope(soapEnvelope);
//outMsgCtx.setEnvelope(envelope); // Non-Signed
operationClient.addMessageContext(outMsgCtx);
}catch(Exception ex){
ex.printStackTrace();
}
return operationClient;
}
|
How to generate the WS-Signature and WS-Encrypted
In part 1 of this article series, we discuss how to generate WS-Signature and WS-Encrypted messages in detail. Below is a sample of the code:
signSOAPEnvelopeMTOM(document); |
Sample WS-Signature SOAP Message with MTOM/XOP
POST /IdMWSAttachment/services/WSAttachmentService HTTP/1.1
Content-Type: multipart/related;
boundary=MIMEBoundaryurn_uuid_AD3F29B8C627E2FE371261519053021; type="application/xop+xml";
start="<0.urn:uuid:AD3F29B8C627E2FE371261519053022@apache.org>"; start-info="text/xml"
SOAPAction: "urn:anonOutInOp"
User-Agent: Axis2
Host: localhost:8181
Transfer-Encoding: chunked
20e5
--MIMEBoundaryurn_uuid_AD3F29B8C627E2FE371261519053021
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.urn:uuid:AD3F29B8C627E2FE371261519053022@apache.org>
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security
xmlns:wsse=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
soapenv:mustUnderstand="1">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#id-1">
<ds:Transforms>
<ds:Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>ufKMxezZOs7P68NINmvWCRN3hYE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
mW5oBhMCiH9RU0+VFcBWy+Ce7RjmwjubQic7eE2z9OcHpcBkpGJc9QDliVtaaStmAUBWFbHPvG56
ZcAxXoQB0tJ+QS8Du+lvyKoKQ41AfEe91chOK5K0dz1x71ttaplRB3oGveETq6RAPPeBAAjh1PK3
IAsqg/R7QI4YZyQhkRM=
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-3AE1F9051C9DBDD6C812615190528592">
<wsse:SecurityTokenReference
xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="STRId-3AE1F9051C9DBDD6C812615190528593">
<wsse:KeyIdentifier
EncodingType=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0
#Base64Binary"
ValueType=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">
MIICKDCCAZECBEspM08wDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRIwEAY
DVQQHEwlXb29kIERhbGUxDjAMBgNVBAoTBURlVnJ5MQswCQYDVQQLEwJJVDEOMAwGA1UEAxMFVmlrYXMwHh
cNMDkxMjE2MTkyMTUxWhcNMTAwMzE2MTkyMTUxWjBbMQswCQYDVQQGEwJVUzELMAkGA1UECBMCSUwxEjAQB
gNVBAcTCVdvb2QgRGFsZTEOMAwGA1UEChMFRGVWcnkxCzAJBgNVBAsTAklUMQ4wDAYDVQQDEwVWaWthczCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArQFF9a+2DmMW2mWlSo3OA722ejV1cq+XDOc4iEaLEdPni8w
GBv1VX/WGKXmem6Xjp6UfqMF3UPKk8qOV/vThzZPJVO+HVfrTqZ2cFAxEgFwgrYFFirrKgoGlyIuiMD7Xrn
0A2vl2o2dBY4LUDQSrJ2YoBSs/K9QVj0lfGKn5gksCAwEAATANBgkqhkiG9w0BAQQFAAOBgQAhx8EN8Riea
1mg0wJCalkcMc5U60HlBQb2BDNMh+e6qUGGJey6ry6GM1RKBH5ewW5Cx7ZxLxSTUiHUvc7vDJz6PfxNQ
GuKESlwK7IrThuHamJo7nsAXpj8obsCjoGVDIR8yTTVEwFYfbvVZ54koyAJWKYA7SkCzJf8ouJNc3ZtLA==
</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body
xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="id-1">
<impl:sendAttachments xmlns:impl="http://attachment.ws.idm.sample.com">
<customerId>Vikas</customerId>
<attachment>
...Q0UgIlhYRFZfSURNIiA7...
</attachment>
</impl:sendAttachments>
</soapenv:Body>
</soapenv:Envelope>
|
Learn
- Learn more about Message Transmission Optimization Mechanism.
- In the SOA and Web
services area on
developerWorks, get the resources you need to advance your skills.
- Stay current with developerWorks technical events
and webcasts focused on a variety of IBM products and IT industry
topics.
- Attend a free developerWorks Live!
briefing to get up-to-speed quickly on IBM products and tools as
well as IT industry trends.
- Follow developerWorks on
Twitter.
- Watch developerWorks on-demand demos
ranging from product installation and setup demos for beginners, to
advanced functionality for experienced developers.
Get products and technologies
-
Evaluate IBM products in the
way that suits you best: Download a product trial, try a product online,
use a product in a cloud environment, or spend a few hours in the SOA Sandbox learning how to
implement Service Oriented Architecture efficiently.
Discuss
- Get involved in the My developerWorks community.
Connect with other developerWorks users while exploring the
developer-driven blogs, forums, groups, and wikis.

Vikas has extensive experience working with J2EE, WebSphere Application Server 5.1/6.0/7.0, WebSphere MQ 5.3/6.0, WebSphere ESB, Mule ESB, Oracle, ORM Tools, Spring for the past 10 years. Vikas was also the Sr Developer for WebSphere Partner Gateway Express 6.0/ Enterprise 6.0 at IBM, India. Interests include J2EE, Web Services Architectures including Security, TX, Address, WebSphere App Server/ESB/MQ, Mule ESB, and exploring more innovative ways for solving different things using languages/scripts like Java, Perl, C. Currently exploring the features of SAXON XSLT parser for it's Java extensibilities.




