Processing mustUnderstand Headers with the ServiceControl
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
|