Every year we see that web services are becoming more and more the norm for exchanging data between systems and gone are the days when we only had to deal with simple SOAP text messages. There is often the need to transport more complex messages like documents or images. This blog explains how to use the Message Transmission Optimization Mechanism (MTOM) to send and receive messages that include binary data using the SAP NetWeaver Composition Environment.
Setting the stage
There are of course many ways to exchange data between systems but in the last decade we have experienced an explosion around the standardization of SOAP. This has lead to much easier means to exchange data between systems and have taken out a lot of the guess work. Although SOAP was responsible for the standardization of the HTTP protocol the data format is still limited to XML text and therefore incompatible with binary data. Let’s take a look at some of the different options to incorporate binary data within your text SOAP message.
The simplest approach is just to dump the binary data into a text node as follows.
Unfortunately this approach could break the parser as some of the binary characters could represent XML characters; for example, there could be a XML bracket “>” somewhere in the middle of the binary data. You can overcome this by wrapping the binary data within a character data (CDATA) section and ignore XML characters completely. Unfortunately the parser still has to figure out where the CDATA section ends, and therefore has to scan the entire message looking for the ending “]]>” brackets. This task adds to processing time and there could also potentially be binary data that represents such ending brackets again breaking the parser.
Another solution to the task of incorporating binary data that has been around for while is to use Base 64 encoding.
The binary character representation would not interfere with XML characters as Base 64 only consists of both uppercase and lower case a-z, 0-9, the + and / characters. Unfortunately one of the downfalls of this approach is that Base 64 makes the entire message larger by about 1/3. To overcome this dilemma there are GZIP utilities to reduce the size of the message. Keep in mind that the consuming client application will need to be aware of both Base 64 and GZIP and be able to uncompress and decode the message. Thus, there is still a need for something that is more standardized and efficient.
SOAP with Attachments
You might have heard of the SOAP with Attachments (SAAJ) specification that’s used quite often to transport binary data using SOAP. The idea here is that rather than adding the binary data to the message it’s kept completely outside the SOAP message similar how files are attached to email messages.
The SOAP message contains a reference to the binary file that is attached to the message. GZIP functionality can also be used to compress large attachments. This is much more efficient but unfortunately there is some bad news. First, the binary data is not part of the SOAP message so the client application must retrieve the binary data. Second, this method also causes issues dealing with WS-Security. Finally MTOM came along as an improved solution to over come the inherent issues with the methods described above.
MTOM stands for SOAP Message Transmission Optimization Mechanism. It is very similar to SOAP with Attachments but with MTOM the binary data is kept in the SOAP message.
This is done using XOP (XML-binary Optimized Packaging). XOP allows first for the binary data to be included as part of the XML Infoset and second for the binary data to be stored outside of the XML document, just like in SOAP with Attachments. It uses a special XOP:include element to tell the processor to replace the contents with the referenced binary data. The SOAP parser then treats the binary data as part of the XML document, with no special retrieval logic necessary.
CE and MTOM
Let’s now go through a specific example using the Composition Environment and create a web service that receives images and stores them on the server. This basically mimicking the legacy FTP (file transport) protocol but instead uses SOAP to transport the images. The binary image data will be imbedded as an attachment using MTOM. The good thing is that since the SAP NetWeaver Composition Environment supports Java EE 5, much of the work is already done for you. You just have to make sure that the Web Service is capable of receiving binary data and then you have to ensure that the client application that sends the binary image data is capable of leveraging the MTOM API functions.
File Upload Example
Our scenario starts off on the left hand side with a WebDynpro form that will be used to upload the image. We will be incorporating an Enterprise Java Bean Model into the WebDynpro application referencing a standard Java EE 5 Session Bean. The Session Bean will act as the client proxy and will be interacting with the File Upload Web Service and will be responsible to send the binary image data using MTOM.
Referring to the above pictorial representation lets start off at the top right hand side by using the Enterprise Services Repository to design the File Upload web service. In the image below you will see we have modeled a method “upload” within a Service Interface “ImageUtil” and then connected it to a business object “Image”
Request Data Type
The most important step is when you create the input Data Type parameters for the upload method. We will be passing 3 fields in to the upload method; binary, name and type. The binary field will contain the actual image binary data therefore the data type used is base64Binary.
Response Data Type
Finally, to keep things simple create a single boolean output parameter that will be an indication if the file upload were successful.
Once you have completed the Service Interface you can move on to create the actual implementation. The good thing is that because you modeled the service within the Enterprise Services Repository you can simply proceed to focus on the piece of functionality that stores the image somewhere on the server. You do not have to be concerned with the communication layer of the web service; the tools will take care of that implicitly. You do not even have to be concerned with any specific SOAP technicalities including the messages signatures. The SAP NetWeaver Composition Environment includes functionality to automatically create the glue code or proxy implementation so that you as a developer can focus on the business logic without having to be concerned with the web service plumbing code.
The easiest way to create the Web Service Implementation is to use the Composite Application Framework (CAF) within SAP NetWeaver Developer Studio. Once you have created a CAF project right click on the External node and proceed to create a Web Service Provider. This will enable you to access your previously created service interface within in the ESR.
Create Web Service Provider Implementation
Select your Service Interface and complete the wizard to create the client classes.
In addition, this will also automatically create the Java representation data types and message types. Most importantly you will find a Session Bean Implementation class that is wrapped within a Web Service; this is where you need to add your specific code to save the uploaded file to the server. To see the client proxy implementation file simply click on the Java file; notice the upload method where you need to add your code. <br />
Server Side Upload Method
Proceed to add the necessary code to write the binary data out into a file somewhere on the server. Notice the “byte array” image data part of the input parameters of the upload method that corresponds to the data types that you modeled in the Enterprise Services Repository.
Don’t forget to compile and deploy the CAF project; this will automatically create a Web Service that you can test using the WS Navigator.
Proceed to create an Enterprise Application that will interact directly with the web service you created in the previous step. You create a Session Bean so that you can manipulate the SOAP message and attach the binary data as an attachment using MTOM. Eventually you will call the Enterprise Java Bean from within the WebDynpro screen using the Enterprise Java Bean Model Functionality.
Continue to create a J2EE Enterprise Application including an EJB Module.
Proceed to import the WSDL file of the ImageUtil Web Service that you created earlier using CAF. Once you have done that, right click on the WSDL file and generate the client proxy code.
Proceed to create a FileUpload Enterprise Session Bean 3.0 and add the following code, referencing the client proxy classes created in the previous step. Take note how to enable MTOM, you have to explicitly set the MTOM enabled flag to true. Keep in mind by default MTOM is disabled and thus the binary data will be sent using standard base64 and will be included within a SOAP message element as described earlier.
Proceed to build and deploy the Enterprise Application. Within your Web Dynpro user interface you will incorporate the Session Bean using the Enterprise Java Bean model functionality.
WebDynpro User Interface
Let’s now turn our attention to the user interface, by proceeding to create a simple file upload form. The good thing is that you can leverage the WebDynpro wizards to do much of the work for you. Proceed to create an Enterprise Java Bean model referencing the EJB created in the previous step. (This is of course assumes you have created the necessary dependencies to the Enterprise Application). Once you have imported the model you can use the Apply Template Wizard functionality provided, by right clicking on the Component Controller and User Interface to create the form and data mapping accordingly.
The final result should look something like this. The Upload button will simply upload the file into the WebDynpro application’s context and then the Publish button will interact directly with the Enterprise Session Bean that will in turn call the Web Service.
Upload the file
Finally let’s go ahead and run a test by first selecting a file. Then press the upload button followed by Publish.
Without MTOM</p><p>Let’s first take a step back and see how the actual SOAP message looks if we do not enable MTOM transmission for our sample upload scenario. As described earlier one of the non-preferred methods of attaching binary data within the SOAP message is shown below; pay attention to the content of the <binary> element.</p><p>!https://weblogs.sdn.sap.com/weblogs/images/251848367/20.JPG|height=139|alt=|width=647|src=https://weblogs.sdn.sap.com/weblogs/images/251848367/20.JPG|border=0!</p><br />
If you enable MTOM transmission within our EJB as described earlier you can see that the binary data is included as part of the XML Infoset and stored outside the XML document. Notice the special XOP:include element to tell the processor to replace the contents with the referenced binary data.
After pressing Publish you will see the image is uploaded successfully to the server.