Skip to Content
Technical Articles

Create MIME Multipart SOAP message in SAP CPI to be delivered to S4 HANA Cloud system accepting MTOM MIME messages

Background

During an implementation of integration between Ariba Cloud Integration gateway  (Using SAP CPI)and S4 HANA Cloud system, we  identified that even though the SOAP adapter in SAP CPI does support MIME messages and is SOAP 1.2 compliant, it doesn’t support MTOM messages. S/4 HANA Cloud system supports MTOM MIME messages received via SOAP adapter and was expecting the SOAP MIME message in MTOM format this integration scenario.

Upon recommendation , we were able to achieve the integration by building a MIME SOAP envelope in compliance with MTOM and delivery via HTTP adapter to S4 HANA Cloud system.

Implementation

I have used groovy script to build custom MIME envelope in compliance with MTOM.

MTOM requirements

For MTOM SOAP content-type should be as below

  • Content-Type: application/xop+xml; charset=utf-8; type=”text/xml”

Integration Flow

Pre-Requisites

S/4 HANA Cloud requires the following additional headers in the MIME

Content-Length of each MIME part

Content-Length of complete MIME Envelope

Here is the iflow implementation of the MIME envelope

 

  • Receive MIME Envelope – via HTTP Sender Adapter
  • Parse the MIME using MIME Multipart Decoder Component provided by CPI
  • Script to get the size of actual payload
  • Script to build the MIME envelope in compliant with MTOM
  • Script to get the size of Complete MIME SOAP Envelope
  • Deliver it to target via HTTP Receiver Adapter using Request/Reply component and capture the Response received .

 

Script to get payload size and to get size of the complete MIME Envelope

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
    //Body 
       long payloadSize = message.getBodySize();
       String PayloadSize  = payloadSize.toString();
       
       message.setHeader("PayloadSize", PayloadSize);
     
       return message;
}

Script to build MIME Envelope

import com.sap.gateway.ip.core.customdev.util.AttachmentWrapper;
import com.sap.gateway.ip.core.customdev.util.Message;
import org.apache.camel.impl.DefaultAttachment;
import javax.mail.util.ByteArrayDataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.camel.Attachment;
import javax.activation.DataHandler;
import java.util.Iterator;
import org.apache.commons.io.IOUtils;
import java.lang.Byte;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.lang.StringBuilder;
import java.util.regex.Pattern;
import java.util.regex.Matcher; 

def Message processData(Message message) {
    //Body 
    
   
    byte[] payload = message.getBody(byte[].class);
    String attType
    String attName
    String attSize
    String attContentId
    String source = null
    def map = message.getHeaders();
    
    String SOAPEnvelopeSize = map.get("PayloadSize")
    
    // Data source
    MimeMessage mimeMessage = new MimeMessage(source);
    def MimeMultipart mimeMultipart = new MimeMultipart("related");
    
    //SOAP Payload
    def MimeBodyPart soapapayload = new MimeBodyPart();
    soapapayload.setHeader("Content-Length", SOAPEnvelopeSize)

    ByteArrayDataSource soapDataSource = new ByteArrayDataSource(payload, "application/xop+xml")
    soapapayload.setDataHandler(new DataHandler(soapDataSource));
    soapapayload.setHeader("Content-Type", "application/xop+xml; charset=utf-8; type=\"text/xml\"")
    mimeMultipart.addBodyPart(soapapayload)
    
    //get and set attachments
    def attMap = message.getAttachments();
    def AttCount = attMap.size()
    if(AttCount > 0)
	 {
	    
	    Map<String, AttachmentWrapper> attMapN = message.getAttachmentWrapperObjects();
        Iterator<Entry<String, AttachmentWrapper>> attIteratorN = attMapN.entrySet().iterator();
        int j = 1; 
           while(attIteratorN.hasNext())
	    	{
				
				Entry<String, AttachmentWrapper> entryN = attIteratorN.next();
				AttachmentWrapper attachment = entryN.getValue();
				DataHandler dataHandler = attachment.getDataHandler();
				InputStream inputStream = dataHandler.getInputStream();
				byte[] bytes = IOUtils.toByteArray(inputStream);
  				int EachAttachmentSize = bytes.length
          		attSize = Long.toString(EachAttachmentSize)
          		def MimeBodyPart soapAttachmentBodyPart = new MimeBodyPart();
          		Collection<String> headerList = attachment.getHeaderNames();
				soapAttachmentBodyPart.setDataHandler(dataHandler)
				for (String attachmentHeaderName : headerList) {
					String attachmentHeaderValue = attachment.getHeader(attachmentHeaderName);
					soapAttachmentBodyPart.addHeader(attachmentHeaderName, attachmentHeaderValue);
				}
                mimeMultipart.addBodyPart(soapAttachmentBodyPart)
                j++;
	    	}
	}
	
	StringBuilder builder
	String searchStr
	String replaceStr	
	String resultString	
    
    String mimeContentType = mimeMultipart.getContentType();
    
    builder = new StringBuilder(mimeContentType);
    searchStr = "multipart/related"
    replaceStr = "Multipart/Related;type=\"application/xop+xml\"; start-info=\"text/xml\""
    resultString = stringReplaceAll(builder, searchStr, replaceStr)
   
	message.setHeader("Content-Type",resultString);
	ByteArrayOutputStream boas = new ByteArrayOutputStream();
	mimeMultipart.writeTo(boas);
	message.setBody(boas); 
	message.setHeader("accept","application/xop+xml ,text/xml")
	return message;
}

def stringReplaceAll(builder, String from, String to)
{
 	int index = builder.indexOf(from);
 	while (index != -1)
 	{
   		builder.replace(index, index + from.length(), to);
   		index += to.length();
   		index = builder.indexOf(from, index);
	}		
	String replacedString = new String(builder);
	return replacedString;	 	   
}

 

Conclusion

This is a substitute solution for implementing MTOM MIME message generation in SAP CPI. The MIME Envelope script can be modified as per requirement .

/
2 Comments
You must be Logged on to comment or reply to a post.
  • Hi Vinay,

    Thanks for your post,

    I have one requirement,

    i.e

    Sender Ariba cxml payload the attachment (“cid:1735239107.1592222922946@cxml.org”)
    document is coming in above format need to extract this content and send to base64 with third party… could you please suggest me with your inputs, that how we can extract the content.

    It’s very helpful.

    Thank you.

    • Hi Rishab,

      You can use the MIME decoder and then use Script API to read the attachments from the exchange and then convert to Base64 and then reassign it back to the exchange .

      Vinay