Saturday, January 3, 2009

Using MTOM with Axis2

MTOM provides a way to send binary data as it is without encoding it to a text format. Axis2 ADB has built in support for MTOM. Therefore it is almost a trivial task to send and receive binary data using axis2.

Here is an sample wsdl

<definitions xmlns:tns="http//tempuri.org/sample"
xmlns:ns1="http//tempuri.org/sample/types"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http//tempuri.org/sample">
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http//tempuri.org/sample/types"
targetNamespace="http//tempuri.org/sample/types"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="echoBinaryData">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="param" type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="echoBinaryDataResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="param" type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>

<message name="EchoBinaryDataRequest">
<part name="part1" element="ns1:echoBinaryData"/>
</message>
<message name="EchoBinaryDataResponse">
<part name="part1" element="ns1:echoBinaryDataResponse"/>
</message>

<portType name="SamplePortType">
<operation name="echoBinaryData">
<input message="tns:EchoBinaryDataRequest"/>
<output message="tns:EchoBinaryDataResponse"/>
</operation>
</portType>

<binding name="SampleSoap11Binding" type="tns:SamplePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="echoBinaryData">
<soap:operation style="document" soapAction="urn:echoBinaryData"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<binding name="SampleSoap12Binding" type="tns:SamplePortType">
<soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="echoBinaryData">
<soap12:operation style="document" soapAction="urn:echoBinaryData"/>
<input>
<soap12:body use="literal"/>
</input>
<output>
<soap12:body use="literal"/>
</output>
</operation>
</binding>

<service name="SampleService">
<port name="Soap11Port" binding="tns:SampleSoap11Binding">
<soap:address location="http://localhost:8080/axis2/services/SampleService"/>
</port>
<port name="Soap12Port" binding="tns:SampleSoap12Binding">
<soap:address location="http://localhost:8080/axis2/services/SampleService"/>
</port>
</service>
</definitions>

then both client and server side code can be generated with the wsdl2java tool.

it sends and receives a binary file. Following client and server side code can be used to send and receive binary data.
try {
SampleServiceStub stub = new SampleServiceStub("http://localhost:8080/axis2/services/SampleService");
stub._getServiceClient().getOptions().setProperty(Constants.Configuration.ENABLE_MTOM, Constants.VALUE_TRUE);
String clientFolder = "/home/amila/work/articles/binary/samples/mtom/client/";
DataSource dataSource = new FileDataSource(clientFolder + "client.jar");
DataHandler request = new DataHandler(dataSource);
DataHandler response = stub.echoBinaryData(request);
FileOutputStream fileOutputStream = new FileOutputStream(clientFolder + "server.jar");
response.writeTo(fileOutputStream);
fileOutputStream.flush();
System.out.println("Saved the file to client folder");
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

Skelton code.
public javax.activation.DataHandler echoBinaryData
(
javax.activation.DataHandler param
) {

String serverFolder = "/home/amila/work/articles/binary/samples/mtom/server/";
try {
FileOutputStream fileOutputStream = new FileOutputStream(serverFolder + "client.jar");
param.writeTo(fileOutputStream);
fileOutputStream.flush();
System.out.println("Saved the file to client.jar");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

FileDataSource fileDataSource = new FileDataSource(serverFolder + "server.jar");
DataHandler dataHandler = new DataHandler(fileDataSource);
return dataHandler;
}