Processessing SOAP Headers with Message Handlers

This topic explains how to extract and process web service message metadata inside of the SOAP message headers.

SOAP Headers and the mustUnderstand Attribute

Metadata about web service messages is often transmitted in the header of the message (within the SOAP envelope headers, 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.

For a Service Control the client stack will 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. You should design your handler to take appropriate action for a given header and then either remove the mustUnderstand attribute from the header or change its value to false.

For information on how to register a handler with a service control, see Adding Handlers to a Service Control.

The following example shows a handler that sets the mustUnderstand attribute to false.

public class ClientHandler extends GenericHandler {
  
  ...
  
  //  (1) The handleResponse method is called: this is the callback called by JAX-RPC. 
  @Override
  public boolean handleResponse(MessageContext context) {
    return setUnderstoodHeader(context,"http://services","SomeHeader");
  }
	
  private boolean setUnderstoodHeader(MessageContext context, String namespace, String local) {
    //  (2) Get the header. 
    SOAPMessageContext smc = (SOAPMessageContext)context;
    SOAPMessage msg = smc.getMessage();
    SOAPPart sp = msg.getSOAPPart();
    try {
      SOAPEnvelope se = sp.getEnvelope();
      SOAPHeader sh = se.getHeader();
      //  (3)  Get the header element specified.
      Iterator iterator = sh.examineAllHeaderElements();
      while (iterator.hasNext()) {
        SOAPHeaderElement el = (SOAPHeaderElement) iterator.next();
        if(namespace.equals(el.getNamespaceURI()) &&
                       local.equals(el.getLocalName())) 
        {
          
          //  (4)  Do processing of the header information here.
		  
          el.setMustUnderstand(false);
          return true;
        }
      }
    } catch (SOAPException e) {
      e.printStackTrace();
    }
	return false;
  }
}

(1) First , the handleResponse method is called on the handler. This is the callback API that JAX-RPC calls.

(2) Next the code iterates through the SAAJ DOM to get the header.

(3) 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.

(4) 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 service control (or JAX-RPC stub) client.

Related Topics

Creating and Using a Service Control

Adding Handlers to a Service Control


Still need help? Post a question on the Workshop newsgroup.