Although the whole notion of Web Services is for disparate systems to communicate with one another there are always problems. This page details some of those we hit when implementing Java, PHP and .NET clients against a Java (Axis) web service.
After setting up our basic web service stack and testing simple parameters and return types from various clients it was time to try arrays as we had experienced issues on previous attempts to get them working between Axis and .NET when using the document/literal (wrapped) approach.
Passing arrays as input parameters didn't seem to be a problem but returning them still didn't work! .NET would see that there was an array but none of it's member variables were populated.
After reading this page from the Axis wiki and examining the SOAP traffic going over the wire we found what the issue was. Firstly, the server-config.wsdd was specifying one namespace and Axis was putting a different one, generated from the code's package name, in the response. These differing namespaces seemed to confuse .NET.
Secondly, Axis was putting a 'wrapper' element around the array values as follows:
This was caused by the fact that the object holding the array did not implement a couple of required methods. The QueryResult object holding the array of nodes also needed to implement the following methods:
public NodeRef getNodes(int i); public void setNodes(int i, NodeRef nodeRef) ;
as well as the standard JavaBean get/set:
public NodeRef getNodes(); public void setNodes(NodeRef nodes);
With those methods in place, the 'wrapper' element disappeared and .NET seemed happy, the response now looked like:
Maybe it's for these reasons that 'WSDL first' is emerging as the recommended way to develop web services!
We are using the UsernameToken header from WS-Security to authenticate callers of our web services, making use of Apache's WSS4J project plugged into Axis.
Axis also uses WSS4J on the client side to send the header. PHP has support for adding headers but not WS-Security headers so we have manually added the required headers to the test PHP script. This will eventually be formulated into a PHP class to hide all those details from end users. The only issue we hit here was that the PHP would add a SOAP actor attribute to the header. The presence of the attribute caused Axis to ignore the header and obviously authentication failed. Once we found a way to stop PHP from sending the attribute things worked well.
.NET has built in support for WS-Security (once you install WSE) so it was extremely easy to add the headers. However, .NET also adds several other headers including the Timestamp header. With this header present WSS4J throws the following exception: 'WSDoAllReceiver: security processing failed (actions number mismatch)'. The workaround to this problem is to add 'Timestamp' to the list of actions in the handler's configuration:
There doesn't appear to be a way to stop .NET from sending this header (there was in WSE1 but this seems to have been removed in WSE2) so the Timestamp item has to be present in the server side configuration. However, with it present Axis and PHP clients don't work. We therefore still have an outstanding issue here to resolve.