views:

232

answers:

1

I'm in the process migrating a service from Axis to Axis2 (Java). The service responds to a simple SOAP request with a bit of "custom" XML in the body like the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
 <soapenv:Header>
  <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"&gt;
   <UsernameToken Id="MyID">
    <Username>user</Username>
    <Password>pass</Password>
   </UsernameToken>
  </wsse:Security>
  <dstm:ClientType xmlns:dstm="http://schemas.company.com/My_functions"&gt;Messaging.EWS&lt;/dstm:ClientType&gt;
  <dstm:SessionScenario xmlns:dstm="http://schemas.company.com/My_functions"&gt;terminate&lt;/dstm:SessionScenario&gt;
  <dstm:Organization xmlns:dstm="http://schemas.company.com/My_functions"&gt;*&lt;/dstm:Organization&gt;
 </soapenv:Header>
 <soapenv:Body>
  <tt:processBodyMessage xmlns:tt="http://core.ws.com"/&gt;
  <GetZipCode_001 version="1.0" xmlns="http://schema.company.com/Company/1"&gt;
   <Get>
    <ActionExpression>getEntity</ActionExpression>
   </Get>
   <ZipCodeID>
    <Id>10003</Id>
   </ZipCodeID>
  </GetZipCode_001>
 </soapenv:Body>
</soapenv:Envelope>

In Axis1, the service took an array of org.wc3.dom Elements as a parameter and processed them, e.g.

public Element[] processMessage(Element [] elems) { ... }

If I migrate the service to Axis2, I'm able to invoke it, but debugging reveals that the elems array is empty. This is using RPCMessageReceivers in a mostly vanilla services.xml:

<service name="Connector">
 <Description>
  Connector Service ported to Axis2
 </Description>
 <messageReceivers>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
  <messageReceiver  mep="http://www.w3.org/2004/08/wsdl/in-out"  class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
 </messageReceivers>
 <parameter name="ServiceClass" locked="false">com.ws.core.Service</parameter>
</service>

From what I've read about Axis2, it is generally not a good idea to have DOM objects in your service signature, so I tried using AXIOM OMElements:

public OMElement processMessage(OMElement e) { ... }

in conjunction with the RawXMLINOutMessageReceiver:

<service name="Connector">
 <Description>
  Connector Service ported to Axis2
 </Description>
 <operation name="processMessage">
      <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
 </operation>
 <parameter name="ServiceClass" locked="false">com.ws.core.Service</parameter>
</service>

This works a little better, but the only thing that gets passed into "e" is the first element of the SOAP body.

If I try to change the method signature to accept an array of OMElements:

public OMElement processMessage(OMElement[] e) { ... }

I get an Axis2 fault complaining that there is no method that implements the required method signature.

I have also tried using an array of OMElements with RPCMessageReceiver, but this results in an empty array being passed in.

Can anyone offer advice about what sort of receiver/method signature combination I can use to get access to all XML elements in the body of the SOAP request? Thanks in advance.

+1  A: 

The real issue here was that the Axis1 service was processing valid DOM, but malformed SOAP requests. According to http://msdn.microsoft.com/en-us/magazine/bb985060.aspx, "A root element is a distinguished element that is an immediate descendant of either the soap:Body or soap:Header element. soap: Body has exactly one root element, which represents the call, response, or fault object." You can see that the SOAP body had multiple root elements, which does not adhere to the standard:

<soapenv:Body>
  <tt:processBodyMessage xmlns:tt="http://core.ws.com"/&gt;
  <GetZipCode_001 version="1.0" xmlns="http://schema.company.com/Company/1"&gt;
   ...
  </GetZipCode_001>
 </soapenv:Body>

In the end, I chose to go with the RAWXMLINOutMessageReceiver and its standard service entry signature:

public OMElement processMessage(OMElement e) { ... }

If you need access to other pieces of the SOAP envelope inside this method, you can access them via the MessageContext, e.g.

SOAPEnvelope envelope = MessageContext.getCurrentMessageContext().getEnvelope();
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
Segphault