Categories
Programming software

Axis2 and WCF .Net Interoperability (Interop)

Recently I created an Axis2 SOAP/JSON service in Java that actually works with a .NET WCF SOAP client.

Axis2 has support for building JSON SOAP services.

However, I could not find an implementation that worked with WCF clients.

Here are some tweaks that I had to implement on the Axis 2 stack to get this scenario working since I had no control on the WCF client calls or the .NET WCF stack.

1. No way to specify a null target namespace for the Axis2 service.

The .NET WCF client by default assumes a service target namespace of http://tempuri.org for XML SOAP messages. .NET JSON formatters do not have the concept of the JSON namespaces and so the JSON requests generated on the .NET stack do not have any namespaces.

And to be fair, JSON is not suited for creating namespace qualified messages.

The invokeServiceClass() method in RPCUtil.java on the Axis2 source was modified to accept SOAP service requests with no target namespace.

2. Axis2 JSON message receivers expect a wrapper around the incoming request message

Strangely even setting the service type in service.xml to “doclitbare” still does not deserialize the JSON into the correct Java request object.

For the example class below,

public class GetQuoteIn
{
private String ticker;

public String getTicker()
{
return ticker;
}

public void setTicker(String _ticker)
{
ticker = _ticker;
}
}

public GetQuoteOut GetQuote(GetQuoteIn getQuoteIn)
{
...
}

This object gets serialized into { “ticker”: “msft”} by the .Net WCF JSON Serializers.

On the server side the Axis 2 JSONMessageFormatter (org.apache.axis2.json.JSONMessageFormatter.java) expects a JSON message with a wrapper

{“GetQuoteIn”: {“ticker”:”msft”}}

I found it ideal to add the wrapper in the HTTPTransportUtils.java class (org.apache.axis2.transport.http.HTTPTransportUtils.java) before the incoming Message Context was built.

The processHTTPPostRequest() method was modified to get the SOAP operation name, added the wrapper name using the convention operationName + “In” and write back the modified JSON message with the wrapper into a newly created Input Stream.

3. WCF JSON message receivers do not expect a wrapper in the response message.

The MappedXMLStreamWriter.java (org.codehaus.jettison.mapped.MappedXMLStreamWriter.java) had to be modified to strip out the “wrapper” element in the JSON output. I modified the writeEndDocument() method in MappedXMLStreamWriter.java class to remove the wrapper in the serialized JSON output.

4. Capitalize JSON property names in the response.

The JSONObject.java (org.codehaus.jettison.json.JSONObject.java) write() method as modified to capitalize property names in the JSON response sent to the WCF client.

The changes could have been made at the various layers of the Axis 2 service stack. But the Axis2 stack is built to rely on the Message Context which means that any message semantics that need to be altered has to happen before the Message Context is established. Customizing the stack using phases and handlers conflicts with this heavy reliance on the Message Context.

In my next post I will explain how to create an Axis2 REST client that communicates with a WCF service (not necessarily a SOAP service) using JSON.
Call a WCF service (non-SOAP) that consumes JSON formatted messages.

Leave a Reply

Your email address will not be published. Required fields are marked *