Accessing WS-Addressing Headers inside a Mediation Flow

In many respects, WebSphere ESB mediation modules act as an ‘ultimate endpoint’, which means WS-Addressing (WS-A) headers are normally stripped off on entry to the mediation flow, and so you cannot access them directly in the SOAPHeader section of the SMO. This technote describes the problem and the potential solution: writing a JAX-RPC handler to access the headers. However, it doesn’t go into detail on how this could be implemented. So here’s how you’d implement a simple JAX-RPC handler to extract the WS-A ‘To’ address on an incoming message so you can use it in your mediation flow:

  1. Define a business object that can be used as a pseudo-WS-A SOAP header to contain whatever WS-A content you care about on the incoming message. In our case, we are just interested in the ‘To’ header:

    You must make sure that this BO is available to the mediation module in question at runtime, by placing it in the module itself or a library that it depends on. If you don’t do this, the header will silently fail to appear.
  2. Write a JAX-RPC handler (which is a Java class) to pull out the content of the incoming SOAP header and place it in a new SOAP header of that Business Object’s type. You need to place it somewhere accessible to mediation module in question. It might look something like this:
    import javax.xml.namespace.*;
    import javax.xml.rpc.handler.*;
    import javax.xml.rpc.handler.soap.*;
    import javax.xml.soap.*;
    
    public class WSAHandler extends GenericHandler {
      public boolean handleRequest(MessageContext context) {
        Object object = context
            .getProperty(com.ibm.wsspi.wsaddressing.WSAConstants.WSADDRESSING_INBOUND_TO);
        String to = (object == null ? "" : object.toString());
    
        SOAPMessageContext soapMessageContext = (SOAPMessageContext) context;
    
        try {
          SOAPEnvelope soapEnvelope = soapMessageContext
              .getMessage().getSOAPPart().getEnvelope();
          SOAPHeader soapHeader = soapEnvelope.getHeader();
          SOAPHeaderElement myBO = (SOAPHeaderElement) soapHeader
              .addChildElement("PseudoWSAHeader", "pwsahn",
                  "http://pseudoWSAHeaderNamespace");
          SOAPElement seTo = (SOAPElement) myBO
              .addChildElement("to");
    
          seTo.setValue(to);
        } catch (SOAPException e) {
          e.printStackTrace();
        }
    
        return true;
      }
    
      public QName[] getHeaders() {
        return null;
      }
    }

    The name and namespace of the business object used when creating the new SOAPHeaderElement need to match the name and namespace of the business object you created. Also, be aware that the class in the com.ibm.wsspi.* hierarchy is part of the WebSphere SPI (System Programming Interface); it is not a fully public API and may not be subject to the same terms (please check your license agreement).

  3. Configure the JAX-RPC handler you just wrote on the Web Services export in question:
  4. Now, when you invoke the Web Services export with a message containing a WS-A ‘To’ header, the pseudo-header will appear in the relevant location in the SMO, and you can access it and use it in whatever way you need, perhaps using an XSLT primitive or a custom mediation, for example. Here’s an example of what the SMO looks like when dumped out in the middle of the mediation flow. The value of the WS-A To header is highlighted:
    <p:ServiceMessageObject xsi:type="p:ServiceMessageObject" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:in="wsdl.http://WSADemo/MyInterface" xmlns:in_1="http://WSADemo/MyInterface" xmlns:ps="http://pseudoWSAHeaderNamespace" xmlns:p="http://www.ibm.com/websphere/sibx/smo/v6.0.1">
      <context/>
      <headers>
        <SMOHeader>
          ...
        </SMOHeader>
        <SOAPHeader>
          <nameSpace>http://pseudoWSAHeaderNamespace</nameSpace>
          <name>PseudoWSAHeader</name>
          <value xsi:type="ps:PseudoWSAHeader">
            <to>[http://tomachine:80/toaddress]</to>
          </value>
        </SOAPHeader>
      </headers>
      <body xsi:type="in:operation1RequestMsg">
        <in_1:operation1>
          <input1>Some regular message data</input1>
        </in_1:operation1>
      </body>
    </p:ServiceMessageObject>

Thanks to Chris Markes, Rob Phippen, and David Illsley for the help with this tip.

4 Responses to “Accessing WS-Addressing Headers inside a Mediation Flow”

  1. WS-Addressing Headers in WebSphere ESB v6.2 « SOA Tips ‘n’ Tricks Says:

    [...] Headers in WebSphere ESB v6.2 February 5, 2009 — andrewferrier I wrote previously about how WS-Addressing headers could be accessed in a WebSphere ESB mediation flow, by writing a [...]

  2. rohit reddy Says:

    Hi Andrew.

    I have a use case in which the endpoints (i.e, imports to ESB app) are secured using saml token.

    I wrote a JAX RPC handler for the ESB (export has web service bindings) to intercept the soap message and add the SAML token to it.
    Now to get the saml token from the STS, i need the end point to which ESB will direct the soap message. Is it possible to get the Endpoint URL in the handler?

    I have tried using Object object = context.getProperty(com.ibm.wsspi.wsaddressing.WSAConstants.WSADDRESSING_INBOUND_TO);
    but i’m getting NULL value for this.

    Can you help me in this regard.

    Thanks
    Rohit

  3. andrewferrier Says:

    @Rohit, you might find this posting relevant:

    http://soatipsntricks.wordpress.com/2009/06/25/changing-a-soap-endpoint-on-an-outgoing-message-using-jax-ws/

    It talks about JAX-WS handlers rather than JAX-RPC, but maybe it would be applicable?

  4. rohit reddy Says:

    Thanks Andrew, Will go through it


Leave a Reply