Tuesday, April 14, 2009

MTOM (Message Transmission Optimization Mechanism)

MTOM (Message Transmission Optimization Mechanism)

MTOM allows send and receives attachments (such as document, pdf and images) efficiently and in an interoperable manner. It uses XOP (XML-binary Optimized Packaging) to transmit binary data (attachments like PDF, Doc and images etc)


Advantage of MTOM:

Base64Binary encoded data bloats the attachment by ~33%. MTOM converts the Base64Binary data to raw bytes over MIME, thus reducing the wire foot-print for transmission. The reciever can optinally convert the raw bytes back to Base64Binary encoding.


MTOM Process

The Consumer application begins by sending a SOAP Message that contains complex data in Base64Binary encoded format. Base64Binary data type represents arbitrary data (e.g., Images, PDF files, Word Docs) in 65 textual characters that can be displayed as part of a SOAP Message element. For the Send SOAP Message Step 1 in the Figure above, a sample SOAP Body with Base64Binary encoded element


Next it tried convert the Base64Binary data to MIME data with an XML-binary Optimization Package (xop) content type.

A Simple MTOM using Apache CXF:

Server implementation:

package com.javatch.service;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import javax.activation.DataHandler;

import javax.jws.WebService;

import com.javatch.bean.Upload;

@WebService(endpointInterface = "com.javatch.service.MTOMServiceImpl",

serviceName = "MTOMService")

public class MTOMServiceImpl implements MTOMService {

public void uploadFile(Upload upload) {

DataHandler handler = upload.getFile();

try {

InputStream is = handler.getInputStream();

OutputStream os = new FileOutputStream(new File("c:\\"

+ upload.getFile()+"."+

upload.getExtn()));

byte[] buf = new byte[100000];

int len;

while ((len = is.read(buf)) > 0){

os.write(buf, 0, len);

}

is.close();

os.close();

System.out.println("File copied.");

} catch (IOException e) {

e.printStackTrace();

}

}

}

Service Interface:

@WebService

public interface MTOMService {

void uploadFile(@WebParam(name="upload") Upload upload);

}

Pojo:

package com.javatch.bean;

import javax.activation.DataHandler;

public class Upload

{

private String fileName;

private String extn;

private DataHandler file;

public String getFileName()

{

return this.fileName;

}

public void setFileName(String fileName)

{

this.fileName = fileName;

}

public DataHandler getFile()

{

return this.file;

}

public void setFile(DataHandler file)

{

this.file = file;

}

public String getExtn() {

return extn;

}

public void setExtn(String extn) {

this.extn = extn;

}

}

Cxf file:

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:jaxws="http://cxf.apache.org/jaxws"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://cxf.apache.org/jaxws

http://cxf.apache.org/schemas/jaxws.xsd">

<import resource="classpath:META-INF/cxf/cxf.xml" />

<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>

<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<jaxws:endpoint id="uploadresume"

implementor="com.javatch.service.MTOMServiceImpl"

address="MTOMService">

<jaxws:properties>

<entry key="mtom-enabled" value="true"/>

jaxws:properties>

jaxws:endpoint>

beans>

The structure of application looks like this,

Webapps

--FileUpload

--WEB-INF

--classes

--com.javatch.bean

--Upload

--com.javatch.service

--MTOMService

--MTOMServiceImpl

--cxf.xml

--lib

--web.xml

We have to modify web.xml to include cxf with this application

Web.xml

xml version="1.0"?>

DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<display-name>ResumeUploaddisplay-name>

<context-param>

<param-name>contextConfigLocationparam-name>

<param-value>classpath:com/thea/service/cxf.xmlparam-value>

context-param>

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

listener-class>

listener>

<servlet>

<servlet-name>CXFServletservlet-name>

<servlet-class>

org.apache.cxf.transport.servlet.CXFServlet

servlet-class>

servlet>

<servlet-mapping>

<servlet-name>CXFServletservlet-name>

<url-pattern>/services/*url-pattern>

servlet-mapping>

web-app>

We are done with server files J

Client :

package com.javatch.client;

import java.io.File;

import java.util.HashMap;

import java.util.Map;

import javax.activation.DataHandler;

import javax.activation.DataSource;

import javax.activation.FileDataSource;

import org.apache.cxf.interceptor.LoggingInInterceptor;

import org.apache.cxf.interceptor.LoggingOutInterceptor;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.javatch.bean.Upload;

import com.javatch.service.MTOMService;

public final class Client {

private Client() {

}

public static void main(String args[]) throws Exception {

Map props = new HashMap();

props.put("mtom-enabled", Boolean.TRUE);

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

factory.setProperties(props);

factory.getInInterceptors().add(new LoggingInInterceptor());

factory.getOutInterceptors().add(new LoggingOutInterceptor());

factory.setServiceClass(MTOMService.class);

factory.setAddress

("http://localhost:8081/resumeupload/services/UploadResumeWS");

MTOMService client = (MTOMService) factory.create();

Upload upload=new Upload();

upload.setFileName("EnterpriseAOP_Free-seminar_July_2006");

upload.setExtn("pdf");

DataSource source = new FileDataSource(new File("C: \\EnterpriseAOP_Free-seminar_July_2006.pdf"));

upload.setFile(new DataHandler(source));

client.uploadFile(upload);

System.exit(0);

}

}

Copy FileUpload folder in to the webapps directory and restart the server.

Now use the client code to test the application.