How do you implement a Web Service contract? Basically, there are three ways to do so:
- coinciding contract and implemetation
- generating stubs, or
- handling raw messages,
Let’s go over these options one by one, using SOAP as our prime service architecture.
Coinciding Contract and Implementation
If the contract is generated out of the implementation, the implementation of the contract is a no-brainer: it’s already there to begin with! For example, in Microsoft’s Indigo, you define the contract using by marking a class with the ServiceContract attribute, and its operations with OperationContract. In Java land, things are relatively similar. In Axis, you define the contract using either a plain Java file (.jws deployment), or by specifying it in a Web Service Deployment Descriptor (wsdd deployment). Some Java SOAP stacks also support JSR-181 annotations.
But wait a minute, didn’t we just decide that contract-last service development is not the way to go? Clearly, there must be better, contract-first implementation option?
Generating Stubs
Another option is to generate service-side stubs out of the (WSDL) contract. This is mostly done using some sort of tool (WSDL2Java for Axis, WsContractFirst for .NET). Clearly, this approach fits more within our contract-first mantra. The basic idea is that such a tool generates interfaces, classes, and possible deployment descriptors out of the service contract.
But what about the mismatch between XML and OO languages? Obviously, you cannot expect a generation tool to create (nice-looking) code for things like XSD restrictions, or multiple out parameters. And besides that, I wonder whether the Object-XML mapping problem is something that should be solved within a SOAP stack at all. But I’ll get back to that in a future post.
Handling Raw XML Messages
It seems that the only way left to implement a service contract is to handle the raw XML messages. Let’s see how three SOAP stacks offer this option.
Axis
Axis provides raw access to its MessageContext through the Handler interface. According to the documentation, you specify which handlers to use at the service-level in the deployment descriptor. I would prefer a more flexible approach, where you can also specify handlers at the operation-level (especially when using WS-Security). The concept of reusable handlers and handler chains does powerful, however.
Additionally, Axis offers Message Services. When creating a Message Service, you expose your service operation using one of the four predefined method signatures. Within the method, you have access to the raw XML of the request, either as a whole envelope or just the SOAP body. The disadvantage of this approach is that operations are tightly coupled with methods.
Indigo
According to Don Box, Indigo offers a similar Plain Old XML mechanism via the Message class:
[…] when your service contracts use System.ServiceModel.Message directly […] you [get] “POX”-like access to SOAP messages without imposing any additional interpretation […]
Conceptually, this is similar to the Axis’ Message Service explained above. In Indigo, there seems to be no way to define and reuse a (chain of) Message handlers, at least not without doing so in C# code.
Alpine
Alpine also seems to favor the raw POX method. The Alpine article states:
Alpine will be a SOAP stack reduced to its essentials: a system for managing the flow of messages through a set of handlers.
Even though there is little implementation information available for Alpine, the article’s authors do give a hint as to how these handlers are to be implemented:
Developers will be expected to use XPath specifications to work with contents of the message.
In other places in the article, the suggestion is made that an API similar to JAX-M/SAAJ will be provided, tightly integrated with a handler chain based on the JAX-RPC/Axis model. We’ll have to see what comes out.
In summary, there seem to be two ways to handle raw SOAP messages:
- by implementing a handler or handler chain interface, which either results in lots of handlers (at least one per operation), or careful inspection of the SOAP message in the handler (to determine the operation requested)
- by using a specific signature for your methods, which tightly couples methods to service operations
I would like to suggest a third method, which is similar to to Spring’s MultiActionController. Using this option, multiple operation types can be handled by the same class. A separate operation mapping controls which operations are mapped to which specific method. Refer to this section of the Spring reference documentation if you are unfamiliar with this concept. Clearly, this method offers the best of both worlds (i.e. it does not result in lots of handlers, and does not tightly couple methods to operations).