MTOM Interoperability between Oracle Application Server and Windows Communication Foundation Part1: From WCF to Oracle

By Jesus Rodriguez

This article is part of a series intended to illustrate WS-* protocols interoperability scenarios between Windows Communication Foundation (WCF) and different J2EE Web Services platforms. Particularly this article focus on MTOM interoperability between WCF and Oracle Application Server v10.1.3.1.

Optimizing XML data transmission: The need for interoperability

The use of XML vs. binary data has been the eternal argument since the early days of XML-RPC and the subsequent SOAP specifications. In some scenarios, XML data formats can add significant overhead compared with the processing of binary data.  This is cause for concern with many architects. However, the use of XML has made vendors agree for first time in a series of protocols and standards for data transmission.

To assume that binary messages are always smaller than XML messages is overlooking one of the most complex challenges in data transmission today. However, binary data is present in a significant percent of data exchange scenarios.

From the Web Services viewpoint, the standards to encode binary data as part of SOAP messages had been evolving for a few years now. However at every step of that evolution, the implementation of interoperable Web Services that can exchange binary data across multiple platforms had raised as an interesting and difficult challenge for developers. Finally, after WS-Attachments and DIME, MTOM has gained acceptance among the different vendors as the main protocol to represent optimized binary data in a SOAP envelope.

MTOM

MTOM, the acronym that identifies the unpronounceable Message Transmission Optimization Mechanism, enables you to send binary data as part of a SOAP message in an efficient and optimized manner.  The classic solution for embedding  binary data in a XML document is to use a base64 encoded representation. Although, the based64 format presents severe limitations in regards to optimizing a binary representation. These limitations are primarily due to the use of 6 out of every 8 bits to encode a base64 character. That factor alone represents a 4:3 extra encoding overhead plus the addition of extra characters. The result is a significant increase in the size of a base64 encoded string.

MTOM avoids this overhead, attaching the binary data to the XML file in the original format without any extra encoding. MTOM relies on the XML Optimized Processing (XOP) Standard as the serialization mechanism to represent binary data as a MIME/Multipart Related package. For more information about MTOM you should read this great post by John Evdemon.

Despite of the fact that MTOM is W3C Standard; the need for interoperable implementations is key for MTOM to become a widely adopted protocol. During the last year different vendors had provided MTOM implementations as part of their Web Services platforms making MTOM interoperability a need and a challenge for the industry. This is even more significant when dealing with Web Services interoperability between.NET and J2EE, given that both platforms have followed different evolution paths.

The following sections are intended to illustrate an interoperability scenario using Oracle App Server and Windows Communication Foundation (WCF).

MTOM and WCF

MTOM is supported in WCF as part of the encoder model. An encoder implements a set of basics rules to represent the message on the wire. Encoders exist at both the client and the service side and are typically configured using encoding binding elements.

Oracle App Server and MTOM

With the recent release of the Application Server 10.1.3.1, Oracle adds supports for MTOM in addition to the existent MIME and DIME attachments. MTOM is now supported at both the client and the service side, only however, using SOAP 1.2.

The following sections illustrate how to build an Oracle Web Service and a WCF client that exchange binary messages optimized using MTOM

Using MTOM in Oracle App Server

As the center of our example lets use the following Web Service that returns a byte[] representing a binary file.

public class FileTransmitter {

    public FileTransmitter() {

    }

    public byte[] GetImg(String path)

      {

          try {

                  ReadableByteChannel channel = new FileInputStream(path).getChannel();

                  ByteBuffer buf = ByteBuffer.allocateDirect(12000);

                  byte[] result= new byte[12000];

                  int numRead = 0;

                  while (numRead >= 0) {

                      buf.rewind();

                      numRead = channel.read(buf);

                      buf.rewind();

                      for (int i=0; i<numRead; i++) {

                          byte b = buf.get();

                          result[i]= b;

                      }

                    

                  }

                  return result;

              }

              catch (Exception e)

              {

                return null;

              }

      }

}

Without using MTOM the response of this Web Service looks like the following.

<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://wsprj/types/"><env:Body><ns0:GetImgResponseElement><ns0:result>a2V5dG9vbCAtZ2Vua2

V5IC1hbGlhcyB0ZXN0IC1rZXlhbGcgIlJTQSIgLXNpZ2F

sZyAiU0hBMXdpdGhSU0EiIC1kbmFtZSAiQ049dGVzdCwgQz1VUyIgLWtleXBhc3MgdGVzdDEyMyA

ta2V5c3RvcmUgdGVzdC5qa3MgLXN0b3JlcGFzcyB0ZXN0MTIzDQoNCmtle

XRvb2wgLWNlcnRyZXEgLWFsaWFzIHRlc3QgLXQxMjMAAAAAAAAA ... binary file</ns0:result></ns0:GetImgResponseElement></env:Body></env:Envelope>

As you can see the entire file is serialized as a base64 string and embedded into the SOAP message.

In order to configure MTOM at the service side is necessary to set the mtom-support setting to true in the web services configuration file.

<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="OraMtomWS">

        <port-component name="OraMtomWSSoap12HttpPort">

        <mtom-support>true</mtom-support>

            <operations>

                <operation name="GetImg" input="{http://wsprj/types/}GetImgElement"/>

            </operations>

        </port-component>

    </webservice-description>

</oracle-webservices>

With those two simple steps the Web Service is ready to deploy to the Oracle Application Server.

Building the WCF client

The first step to create a WCF client is to generate the proxy using the SvcUtil tool. The following code is a sample client that invokes the Oracle Web Service.

static void Main(string[] args)

        {

            GetImgClient();

        }

        private static void GetImgClient()

        {

            OraMtomWSClient proxy = new OraMtomWSClient();

                byte[] result = proxy.GetImg("c:\\temp\\test2.file");

                Console.ReadLine();

         }

In order to achieve interoperability with Oracle App Server, the WCF client needs to encode the messages using SOAP 1.2 and MTOM. The following code illustrates the client configuration file.

<configuration>

          <system.serviceModel>

                   <bindings>

                             <customBinding>

                                      <binding name="OraMtomWSSoap12Http">

                                                <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://server/WSInterop-WSPrj-context-root/OraMtomWSSoap12HttpPort"

                binding="customBinding" bindingConfiguration="OraMtomWSSoap12Http"

                contract="OraMtomWS" name="OraMtomWSSoap12HttpPort" />

                   </client>

          </system.serviceModel>

</configuration>

The above settings configure the server to receive MTOM messages using SOAP 1.2. Executing the client produces the following messages on the wire.

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Body><GetImgElement xmlns="http://wsprj/types/"><path>file path…</path></GetImgElement></s:Body></s:Envelope>

Figure SOAP request produced by the WCF client

<?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://wsprj/types/"><env:Body><ns0:GetImgResponseElement><ns0:result>

<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:7cfa880ad11d4faa90eadbc06de797c5"/></ns0:result></ns0:GetImgResponseElement>

</env:Body></env:Envelope>

Figure SOAP response produced by the Oracle Web Service

As you can see there is notable size difference between this response and the message produced when MTOM is not used. Regardless of the size factor, containing the message in its original binary format makes the MTOM message optimal when processing the binary data.

Where are we?

MTOM provides a standard and optimized mechanism to represent binary data in a SOAP envelope. This article explained the required steps create a Windows Communication Foundation client that can achieve MTOM interoperability with an Oracle Application Server web Service.  The second part of this article will complement this scenario demonstrating interoperability between Oracle client and a Windows Communication Foundation service.

1 Comment

  • Jesus,

    I have implemented onterop between WCF and Oracle a while back, following the steps on this blog. The webservice is on a standalone OC4J server and WCF is the client. Evrything was working fine till we updated .Net Framework 3.0 from SP1 to SP2.

    The error we are getting is:
    Error creating a reader for the MTOM message.
    Inner exception is:
    Invalid MIME content-type header encountered on read.

    The MTOM content type looks like as below:
    Content-Type: application/xop+xml;charset=UTF-8;type="application/soap+xml;action=\"\";charset=UTF-8"

    I know axis folks had the same issue where WCF doesn't recognise the optional "action" parameter and the axis2 code was changed. Have you seen the same issues with oracle webservices and if they is a way to prevent this parse error in WCF.

    Any help is appreciated.

    Thanks,
    Jai

Comments have been disabled for this content.