cancel
Showing results for 
Search instead for 
Did you mean: 

Axis SOAP Adapter - Setting MIME headers for attachements (Handlers?)

Former Member
0 Kudos

Hello,

I need to know if/how it is possible to set the individual MIME headers of the parts making up a multipart/related SOAP message using only standard Axis Handlers e.g. "com.sap.aii.axis.xi.XI30DynamicConfigurationHandler" (as described in the Axis FAQ in Note 1039369).

I know I can insert transport headers using "com.sap.aii.axis.xi.XI30DynamicConfigurationHandler", but I can't see a way of setting a MIME header for, say, the first part (i.e. the SOAP part) or the second part (e.g. an attachement). Is this possible without writing your own Axis handler? The Axis FAQ, in "Advanced usage question 31" implies that you can set MIME Headers but only shows an example of setting the transport header.

I am using the SOAP Adapter to send a message comprising and XML message (in the SOAP body) and a PDF document (as an attachement). The external company this is being sent to requires that we have specific values for the "Content-Id" MIME header in each part of the multipart/related document. This is why I need to understand if we can do this without writing our own Axis Handler.

Incidentally, I have tried to write a custom Axis Handler but couldn't get PI to find it after deployment. I did this by inserting my JAR file in the "com.sap.aii.adapter.lib.sda" (as per Notes 1039369 / 1138877) and then using JSPM. After deployment, though, when I tried to start the SOAP Adapter I got the following error in the RWB: "failed to initialize: org.apache.axis.ConfigurationException: java.lang.ClassNotFoundException: com.hp.gerryaxis.GerryAxis..." (my class was called "GerryAxis" and I placed this in package "com.hp.gerryaxis"). I'm not an experienced Java programmer (my background is in ABAP), so if anyone can suggest whey I'm getting this error, I'd be very grateful (for example, could my choice of package be causing the problem?).

Thanks for your help.

Accepted Solutions (0)

Answers (4)

Answers (4)

Former Member
0 Kudos

Hi all.

Could anyone help me how to depoy Axis custom handler to AS Java?

I`ve created new thread for my quastion http://scn.sap.com/thread/3601244

Thanks.

Regards,

Sergey.

Former Member
0 Kudos

I now have a technical solution to this. Whether it is the most appropriate method is another question. I installed the Axis 1.4 libraries on an ordinary XP laptop as well as the Apache Tomcat server. I used a customised version of the Axis "EchoAttachment" Client sample to represent PI, and Tomcat to represent our external party. In this fashion I was able to test whether my problem was rooted in SAP PI or in the Axis libraries, themselved. I found that the same problem (inability to influence the SOAP Part MIME headers) was evident. This means that the problem I have is purely down to the Axis libraries.

On my local installation, I then analysed the Axis source code and found that when sending a multipart message with attachments, any changes you make to the MIME headers via the SOAPPart are thrown away. The fundamental reason for this is that the SOAPPart is propograted in the Axis code as a string (produced via the SOAPPart.getAsString() method e.g. in the org.apache.axis.attachments.AttachmentsImpl.java class, method writeContentToStream()). This string holds all the XML of the SOAP envelope but not the MIME headers, thus the Axis source code generates the relevant MIME headers independently of any changes made earlier via the SOAPPart.setMimeHeader() method. You can see this happening in the source code of org.apache.axis.attachments.MimeUtils.java, method CreateMP(), where you see, for example, "messageBodyPart.setHeader("Content-Id", "<" + rootCID + ">");", where the variable rootCID is the GUID. This code can't be influenced by any calls you make in a custom Axis Handler using the SOAPPart.setMimeHeader() method.

In summary, therefore, I've solved my problem by customising the Axis 1.4 libraries, recompiling them and deploying to PI. This then gave me the flexibility to control the MIME headers of all Parts of the SOAP message. My lack of experience with Java and SOAP may mean I've completely misunderstood something and done a lot of work for nothing! Even if this is the case, I'd still like to know. So, if someone out there can tell me a better way of meeting this requirement, please do let me know.

Thanks,

Edited by: Gerry Deighan on Oct 13, 2010 4:14 PM

Former Member
0 Kudos

I've noticed something else. If I use the Axis API, "SOAPPart.getContentID", and print this to my debug output, the value is not the same as the Content-Id in the transmitted message (I'm monitoring the transmitted message using the Apache "TCPMON" utility). It looks, therefore, like the MIME headers of the SOAP Part of the message are being completely refreshed at some point after my handler is called. This would explain why my changes have no effect and whey the Content-Id returned by SOAPPart.getContentId differs from the value actually sent.

Can anyone confirm if the SOAP Part's MIME headers are always overwritten subsequent to any bespoke Handers? The next Handler called is the transport one, "HTTPSender", so is this changing the MIME headers of the SOAP Part? The Content-ID of the SOAP Part is references in the HTTP header, "Content-Type" via the "start" attribute, so I wonder whether the process which builds the HTTP header also overwrites the SOAP Part mime header? I even tried using the standard Axis "org.apache.axis.transport.http.HTTPSender" Handers (rather than the standard SAP one), as I have the source code for this. This still behaved the same way, but I couldn't see anything explicit in the Java code of org.apache.axis.transport.http.HTTPsender which was overwritting the SOAP Part's MIME header.

Again, if anyone knows where I'm going wrong please let me know.

Thanks

Former Member
0 Kudos

I went ahead and wrote a simple bespoke Axis Handler. By invoking this from the standard "HandlerBean" in the module processor of my communication channel, I was able to overwrite and set new MIME headers in the Attachment Parts of my SOAP Message. I was also able to change the contents of the SOAP Envelope; for example, I found I could easily delete the SOAP Header. However, I've encountered a problem when I try and update the MIME headers of the SOAP Part i.e. the Part of the multipart/related message containing the SOAP Envelope.

Does anyone know why I can't seem to change the MIME headers of the SOAP Part?

The Axis API calls I used were as follows:

(1) To update the MIME headers of attachements in my SOAP message:

(a) Message = MessageContext.getCurrentMessage()

(b) Iterator = Message.getAttachments()

(c) AttachmentPart = Iterator.getNext()

(d) AttachmentPart.setMimeHeader(name, value)

This works.

(2) To update the MIME headers of the SOAP (root) Part:

(a) Message = MessageContext.getCurrentMessage()

(b) SOAPPart = Message.getSOAPPart()

(c) SOAPPart.setMimeHeader(name, value)

This DOESN'Twork - the MIME headers of the SOAP Part never change.

(3) To update the SOAP Envelope (delete the SOAP Header):

(a) Message = MessageContext.getCurrentMessage()

(b) SOAPPart = Message.getSOAPPart()

(c) SOAPEnvelope = SOAPPart.getEnvelope()

(d) SOAPHeader = SOAPEnvelope.getHeader()

(e) SOAPHeader.removeContents()

This works.

I just don't understand why the call to SOAPPart.setMimeHeader() doens't work when I try and insert new MIME headers to the SOAP Part (e.g. "Content-Name") or when I try and change existing MIME headers there (e.g. "Content-ID"). I don't get any errors.

The code of my handler is:

/*

  • @(#)GerryAxis.java

  • Set MIME headers in the SOAP and specified attachment part of a message

*/

package com.hp.handlers;

import org.apache.axis.handlers.BasicHandler;

import org.apache.axis.AxisFault;

import org.apache.axis.attachments.AttachmentPart;

import org.apache.axis.Message;

import org.apache.axis.MessageContext;

import java.util.Iterator;

import javax.xml.soap.SOAPMessage;

import javax.xml.soap.SOAPEnvelope;

import javax.xml.soap.SOAPHeader;

import javax.xml.rpc.handler.soap.SOAPMessageContext;

/**

  • The <code>GerryAxis</code> handler class sets MIME headers.

  • <p>

  • This handler accepts the following parameters:

  • <ul>

  • <li><b>name</b>: Name of header

  • <li><b>value</b>: Value for header

  • <li><b>attachment</b>: Attachment number

  • </ul>

*/

public class GerryAxis extends BasicHandler {

/* (non-Javadoc)

  • @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)

*/

public void invoke(MessageContext msgContext) throws AxisFault {

int i=0;

boolean found = false;

AttachmentPart ap = null;

javax.xml.soap.SOAPPart sp = null;

StringBuffer debug = new StringBuffer();

try {

// The MIME header change is controlled from the parameters "name", "value", "attachment" which are

// set in the module processor as parameters.

String name = (String)getOption("name");

String value = (String)getOption("value");

String attachment = (String)getOption("attachment");

Message msg = msgContext.getCurrentMessage();

// Get the SOAP Part (the part holding the SOAP Envelope

sp = msg.getSOAPPart();

if (sp == null)

debug.append("getSOAPPart returned <null> / ");

// Set a MIME header in the SOAP Part - THIS DOES NOT WORK - WHY?

sp.setMimeHeader(name,value);

// Remove the SOAP Header for the Envelope - this works fine

SOAPEnvelope se = sp.getEnvelope();

SOAPHeader sh = se.getHeader();

sh.removeContents();

// For debugging - writes some debuggin information to a "DEBUG" MIME header in the first Attachement Part

debug.append("name = " + name +" / ");

debug.append("value = " + value +" / ");

debug.append("attachment = " + attachment + " / ");

debug.append("getMimeHeader for SOAPPart returned " + sp.getMimeHeader(name)[0] + " / ");

debug.append("getContentId for SOAPPart returned " + sp.getContentId() + " / ");

// Update the specified attachement's MIME header - this works fine

Iterator it = msg.getAttachments();

while (it.hasNext()) {

i++;

ap = (AttachmentPart) it.next();

if (i == new Integer(attachment).intValue()) {

found = true;

break;

}

}

if (found) {

ap.removeMimeHeader(name);

ap.setMimeHeader("DEBUG",debug.toString());

ap.setMimeHeader(name,value);

}

msg.saveChanges();

}

catch (Exception e) {

throw AxisFault.makeFault(e);

}

}

}

Thanks

Edited by: Gerry Deighan on Oct 3, 2010 10:27 PM

Former Member
0 Kudos

Hi,

Can you please suggest me if I can generate nested header at runtime.

I need to generate header like below:

<soapenv:Header>

      <HeaderAuthenticate xsi:type="soap:HeaderAuthenticate">

         <reactid xsi:type="xsd:string">?</reactid>

      </HeaderAuthenticate>

      <HeaderLogin xsi:type="soap:HeaderLogin">

         <!--You may enter the following 2 items in any order-->

         <username xsi:type="xsd:string">?</username>

         <password xsi:type="xsd:string">?</password>

      </HeaderLogin>

   </soapenv:Header>

Please let me know how to write and use the handler for the same.

Regards,

Akshay