Implementing MTOM in Oracle Application Server (Oracle AS)
The first to do is to launch Oracle JDeveloper IDE, create a new Empty project from File| New on the main menu and name it MTOM_Server. Then go to the Applications Navigator windows, right-click on the project MTOM_Server and select the New option from the context menu. In the New Gallery windows, select Java Class from Items as shown in Figure 1. Then you must enter a name for the class such as BinaryFileTransferService.
Figure 1: Creation of a Java class.
Now we're going to define the behavior of the service for returning a byte array representing a binary file as shown in Listing 1.
- package mtom_server;
- import java.io.FileInputStream;
- import java.nio.ByteBuffer;
- import java.nio.channels.ReadableByteChannel;
- Public Class BinaryFileTransferService
- {
- Public BinaryFileTransferService()
- {
- }
- public byte[] getFile(String strPath)
- {
- byte[] barrResult=null;
- try
- {
-
- ReadableByteChannel objChannel = new FileInputStream(strPath).getChannel();
- barrResult = new byte[6144];
- ByteBuffer objBuffer = ByteBuffer.allocateDirect(6144);
- int nTotalRead = 0;
- while(nTotalRead>=0)
- {
- objBuffer.rewind();
- nTotalRead = objChannel.read(objBuffer);
- objBuffer.rewind();
- for(int i=0;i<nTotalRead;i++)
- {
- barrResult[i]=objBuffer.get();
- }
- }
- }
- catch(Exception ex)
- {
- barrResult=null;
- }
- return barrResult;
- }
- }
Listing 1: The BinaryFileTransferService class definition.
In order to create the Web Service you must go to the Applications Navigator windows, right-click on the BinaryFileTransferService.java file as shown in Figure 2, select the Create J2EE Web Service option from the context menu and the Create Java Web Service wizard is launched.
Figure 2: Creation of the Web Service.
On the first page enter a name for the service such as BinaryFileTransferService and set the checkbox SOAP 1.2 Binding as shown in Figure 3. Then follow the ongoing pages with the default values.
Figure 3: Creation of the service BinaryFileTransferService.
In order to configure MTOM in the server, you need to set the mtom-support setting to true in the Web Service configuration file as shown in Listing 2 (highlighted in yellow).
- <oracle-webservices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/oracle-webservices-10_0.xsd">
- <webservice-description name="BinaryFileTransferService">
- <port-component name="BinaryFileTransferServiceSoap12HttpPort">
- <mtom-support>true</mtom-support>
- <operations>
- <operation name="getFile" input="{http://mtom_server/types/}getFileElement"/>
- </operations>
- </port-component>
- </webservice-description>
- </oracle-webservices>
Listing 2: Configuring the Web Service to support MTOM.
Now deploy the solution to Oracle AS, and we're ready to create the client in WCF.
Implementing the client in Windows Communication Foundation
The first step is to launch Visual Studio.NET IDE and create a console application for hosting the client components. Now we're going to create the Web Service proxy using the svcutil.exe tool from the command windows as shown in Listing 3.
svcutil http://localhost:8888/MTOM_Server-context-root/BinaryFileTransferServiceSoap12HttpPort?wsdl
Listing 3: Creating the Web Service proxy using the svcutil tool.
And now, add to the project the generated file BinaryFileTransferService.cs with the definition of the proxy as well as a reference to the System.ServiceModel assembly.
To achieve interoperability between the two platforms we need to encode the message using SOAP 1.2 and MTOM. The following listing (Listing 4) shows the settings in the application configuration file to specify the former requirement. Highlighted in yellow you can see the how to specify MTOM support in WCF.
- <?xml version="1.0" encoding="utf-8"?>
- <configuration>
- <system.serviceModel>
- <bindings>
- <customBinding>
- <binding name="BinaryFileTransferServiceSoap12HttpMTOM">
- <mtomMessageEncoding messageVersion="Soap12" />
- <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
- maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
- bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
- keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
- realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
- useDefaultWebProxy="true" />
- </binding>
- </customBinding>
- </bindings>
- <client>
- <endpoint address="http://crvc18.crvc.tel.etecsa.cu:8888/MTOM_Server-context-root/ BinaryFileTransferServiceSoap12HttpPort"
- binding="customBinding" bindingConfiguration="BinaryFileTransferServiceSoap12HttpMTOM"
- contract="BinaryFileTransferService" name="BinaryFileTransferServiceSoap12HttpPort" />
- </client>
- </system.serviceModel>
- </configuration>
Listing 4: The configuration file.
And finally, we have the application which invokes the service operations as shown in Listing 5.
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace MTOM_WCF_Client
- {
- class Program
- {
- static void Main(string[] args)
- {
- BinaryFileTransferServiceClient objProxy = new BinaryFileTransferServiceClient();
- byte[] arrByte = objProxy.getFile(@"c:\temp\input.iso");
- System.Console.WriteLine("The file length in bytes is {0}",arrByte.Length);
- }
- }
- }
Listing 5: The console application's code.
If you check the message on the wire with a sniffer the server response is the following (Listing 6.)
------=_Part_5_14490978.1180972531141
Content-Type: application/xop+xml;charset=UTF-8;type="application/soap+xml;action=\"\";charset=UTF-8"
Content-Transfer-Encoding: 8bit
Content-ID: <0236726142d343a7ab61c2dac8b7405f>
<?xml version="1.0" encoding="UTF-8" ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://mtom_server/types/"> <env:Body> <ns0:getFileResponseElement> <ns0:result> <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:b9d75a3086524defb0c9ec02477ed7fd"/> </ns0:result></ns0:getFileResponseElement> </env:Body> </env:Envelope>
------=_Part_5_14490978.1180972531141
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-Id: <b9d75a3086524defb0c9ec02477ed7fd>
Binary Data.
------=_Part_5_14490978.1180972531141--
Listing 6: The service response's message on the wire.
You can see that the binary data is attached to the response SOAP message which contains a reference (highlighted in yellow) to the binary data identified by its content id (highlighted in green). MTOM relies on XML Optimizer Processing (XOP) standard specification and MIME/Multipart Related package. If you don't use MTOM transfer mode, then the binary data is embedded within the SOAP message using Base64 encoding, but this method has some overhead due to the use of 6 out of every 8 bits to encode a character, thus representing a 4:3 factor of extra encoding.
Conclusion
In this article, I covered with an example how to use MTOM related mechanism to send binary data in an interoperable environment. Although MTOM is a standard specification, the need for interoperable implementation is today a key point to follow.