Arch2Arch Tab BEA.com
Syndicate this blog (XML)

Processing mustUnderstand Headers with the ServiceControl

Bookmark Blog Post

del.icio.us del.icio.us
Digg Digg
DZone DZone
Furl Furl
Reddit Reddit

Chris Hogue's Blog | February 1, 2007   5:24 PM | Comments (0)


Meta-information about web service messages is often transmitted in the header of the message (within the SOAP envelope, not in the transport headers). These are typically used for information such as user credentials, callback endpoint addresses, etc. Services that send these messages can flag each header with a mustUnderstand attribute that indicates that they require the receiver of the message to understand that header. If the receiver doesn't understand that header, the message fails.

In the world of the ServiceControl and JAX-RPC in general, the client stack will typically throw an exception if it encounters a mustUnderstand header that hasn't been processed. It's up to the client to process that header on the incoming message before the underlying stack checks it.

The way this is done is with a handler. The handler runs before the underlying JAX-RPC stub processes the message. Handlers are supposed to take whatever the appropriate action is for that header, then either remove the mustUnderstand attribute from the header or change its value to false. It takes a bit of code, but nothing special.

For information on how to add a handler to a ServiceControl, see my earlier post on the subject.

The question now is what the handler actually looks like. Here it is:

 

public class ClientHandler extends GenericHandler {

	...

  @Override
  public boolean handleResponse(MessageContext context) {
    return setUnderstoodHeader(context,"http://services","SomeHeader");
  }
	
  private boolean setUnderstoodHeader(MessageContext context, String namespace, String local) {
    SOAPMessageContext smc = (SOAPMessageContext)context;
    SOAPMessage msg = smc.getMessage();
    SOAPPart sp = msg.getSOAPPart();
    try {
      SOAPEnvelope se = sp.getEnvelope();
      SOAPHeader sh = se.getHeader();
      Iterator iterator = sh.examineAllHeaderElements();
      while (iterator.hasNext()) {
        SOAPHeaderElement el = (SOAPHeaderElement) iterator.next();
        if(namespace.equals(el.getNamespaceURI()) &&
                       local.equals(el.getLocalName())) 
        {
          
          // Do processing of the header information here
		  
          el.setMustUnderstand(false);
          return true;
        }
      }
    } catch (SOAPException e) {
      e.printStackTrace();
    }
	return false;
  }
}

 

It looks like a lot of code but it's not as scary as it looks. Most of the code here is boiler plate code for iterating through the SAAJ DOM to grab the header. First, the handleResponse method is called on the handler. This is the callback API that the JAX-RPC plumbing calls.

Next there's a method for setting a particular header's mustUnderstand attribute as understood. It simply looks through the DOM to get the header section. Then it looks through the headers for the one specified by the namespace and local name sent to the method.

Finally it does whatever processing is appropriate for the header, then sets mustUnderstand to 'false' to indicate that it has processed the header. Alternatively, you could remove the mustUnderstand attribute by calling el.removeAttributeNS(...) rather than setting the value to false.

Once this call is complete the underlying JAX-RPC infrastructure will continue processing the message, ultimately making the message available to the ServiceControl (or JAX-RPC stub) client.

 


Comments

Comments are listed in date ascending order (oldest first) | Post Comment



Only logged in users may post comments. Login Here.

Powered by
Movable Type 3.31