Access to SOAP Header from response payload

As I was trying to explain the difference between SOAPElement (a.k.a. XMLElement or Element in the java world) and Document, I got to realized that this know-how could be usefull when you need to access the content of the soap:header that is comming back from the service endpoint on the response.

To illustrate this technique, I'll be using WS-Addessing and the .NET endpoint Microsoft exposes for testing purposes (http://131.107.72.15/WSAddressingCR_Service_WCF/WSAddressing10.svc).

In my test scenario, the request looks like this
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://example.org/action/echoIn</wsa:Action>
<wsa:ReplyTo xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://131.107.72.15:80/WSAddressingCR_Service_WCF/WSAddressing10.svc/Soap12</wsa:To>
</env:Header>
<env:Body>
<ans12:echoIn xmlns:ans12="http://example.org/echo">test1132</ans12:echoIn>
</env:Body>
</env:Envelope>


For now, I'll assume that you can figure out the way to send the proper SOAP Header in the request, and point you at the documentation if you need further information about JAX-RPC handlers.

To construct the client, you can use the following ant target:
<target name="genproxy">
 <delete dir="./gen_src"/>
  <o:genproxy wsdl="./etc/wcf-server/WSAddressingCR.wsdl" output="./gen_src" debug="true" classpath="./classes">
   <o:handler name="AddressingClientHandler" class="org.w3c.addressing.ClientHandler">
    <o:soapheader value="{http://www.w3.org/2005/08/addressing}Action">
     <o:initparam name="test" value="testValue"/>
    </o:soapheader>
   </o:handler>
  </o:genproxy>
</target>


The trick to get access to the soap:header in the response is as follow:
  1. use the databinding="false" option on the o:genProxy command - this will change the method signature of your java code, and give you access to the raw XML.
  2. from the SOAPElement you are getting in return, get back to the containing XML Document - the soap:envelope. Once you have it, you can access any value from the soap:header
It's that simple. The draw back of this is on the java side - now, you have to construct the SOAP request and decode the SOAP response by hand. It's only a temporary solution, until we get to J2SE 6.0 and JAX-WS.

code snippet:
SOAPElement result = myPort.echo(input);
System.out.println("result as SOAPElement");
((XMLElement) result).print(System.out);
System.out.println("result as Document");
((XMLElement) result.getOwnerDocument().getDocumentElement()).print(System.out);

output:

result as SOAPElement
<echoOut xmlns="http://example.org/echo">test1132</echoOut>
result as Document
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://example.org/action/echoOut </a:Action>
</s:Header>
<s:Body>
<echoOut xmlns="http://example.org/echo">test1132</echoOut>
</s:Body>
</s:Envelope>

In this example, the a:Action header is not that usefull, but imagine you can gain access to a:RelatesTo or a:MessageID using the same technique.

Have fun!!!

Comments

Popular posts from this blog

Changing the version of JDK used by JDeveloper

Connection reset from a WCF Web Service

unexpected null value for literal data