I have a custom SOAP message handler for incoming messages that will run different code based on which operation is being called. My first try to get the operation name looked something liket this:
public boolean handleMessage(SOAPMessageContext context)
{
String op = context.get(MessageContext.WSDL_OPERATION);
...
This failed because the property MessageContext.WSDL_OPERATION
appears to never be set. I then tried using this:
public boolean handleMessage(SOAPMessageContext context)
{
Map<?, ?> headers = (Map<?, ?>)context.get(MessageContext.HTTP_REQUEST_HEADERS);
ArrayList<String> SOAPAction = ((ArrayList<String>) headers.get("SOAPAction"));
String opName = SOAPAction.get(0);
//opName will be formatted like "urn#myOperation", so the prefix must be removed
opName = ((opName.replace("\"","").split("#"))[1]);
This works, but I'm concerned there could be situations where the header property "SOAPAction" isn't set (or doesn't even exist), or does not have the value that I'm expecting it to. I'm also a little concerned because I don't know if this is an "official" way to get the operation name - I figured it out by looking at the contents of context
in the debugger.
Is there any better way to get the operation name when handling incoming SOAP messages?
You could call
body.getElementName().getLocalName()
to retrieve the name of SOAP body element of the message payload. It's a little bit verbose and manual but it works. You could have the following in your handlerThe result of the above code is guaranteed to carry the name of the operation as specified in your WSDL
EDIT: This solution is based solely on the condition that the web service is implemented as document/literal-wrapped or RPC/literal
The SOAPMessageContext contains this information and can be retrieved super easily like this:
I'm very late to this party but I tried to do this over the past week. The accepted answer doesn't actually work for every JAX-WS implementation (at least not that I tried).
I have been trying to make this work on standalone Metro in my development environment but also using Axis2 bundled with WebSphere 7 in a real environment.
I found the following works on Metro:
and the following works on Axis2:
What is happening is that Axis2 inserts a Node of type
Text
into the Body as the first child but Metro doesn't. This text node returns a null local name. My solution was to do the following:As described in the comments we're actually looking for the first node of type
SOAPBodyElement
. Hopefully that will help out anyone else looking at this in the future.in case if someone searches for "elegant" way to get needed properties use
then decide what info you need and get it!