Archive for June, 2005

Thoughts on Web Services, part 5: To serialize or not to serialize

Most SOAP stacks offer some sort of XML serialization. Using this type of serialization, you can transform the parameters of your class to SOAP messages, and back again. This seems very handy: within certain limits, you do not need to change your class to SOAPify it! Useful, yes, but harmless?,

No. As it turns out, things are not so simple when you look up close. Why not?

First, let’s define our concepts a bit more. What is Serialization? I would define serialization as:

The reversible process of encoding a data structure as a sequence of bytes.

The standard Java and C# forms of serialization certainly conform to this definition, as do proprietary frameworks such as Hessian and Burlap. Does XML serialization? I’m a afraid not. Firstly, you cannot serialize any object into XSD-valid XML, and if you can serialize it, you cannot simply de-serialize it and expect the same object back.

The Alpine folks have excellently described why not. I will briefly cite the most important issues here:

  1. The language of XML Schema is much richer than the object model of Java,
  2. Not all XML names can be turned into Java identifiers,
  3. xsd:enumeration declarations cannot be nicely mapped into Java types (even since Java 5),
  4. Some Java types are by nature explicitly unportable.
  5. XML is a hierarchical data structure, and can only describe trees or lists of data, while Java classes almost invariably refer to other objects, often creating cyclic graphs of references.
  6. Each node in an XML message can have a separate namespace, which cannot be expressed in Java.

Read the article if you want the details.

In the end, the Alpine authors rather not talk about XML Serialization, but rather Object-XML Mapping (O/X Mapping). With this, they want to relate it to with Object-Relational Mappings, because it is at least as difficult.

However, I do not wish to go as far as to banish O/X mappings altogether, as the Alpine authors do. As with O/R mapping, a good O/X mapping can certainly be extremely useful, if properly configured. So, a good SOAP stack should facilitate in this configuration, and offer something like Spring’s templates to easily convert XML to objects and vice-versa. You do not expect Hibernate to automatically marshall your objects into SQL, why would you expect it when marshaling to XML?

Comments off

Thoughts on Web Services, part 4: Implementing the Contract

How do you implement a Web Service contract? Basically, there are three ways to do so:

  1. coinciding contract and implemetation
  2. generating stubs, or
  3. 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:

  1. 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)
  2. 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).

Comments (1)

Thoughts on Web Services, part 3: It’s the Contract, stupid!

The most central concept within a Web Service is its Contract. In this contract, you define:

  • the name, and other properties of the service,
  • the operations it supports, and
  • the messages accepted and sent by the operations.

Together with the Binding of the service, this makes a Endpoint, i.e. something you can point a client at.

For SOAP services, the contract is defined in a WSDL definition. It usually contains, or refers to, a XSD schema that defines the messages of the operations.

The most common way to create a WSDL document is to generate it by the SOAP stack. The Alpine people call this contract-last development, and also mention a few issues with it. In my opinion, the most important issue is that:

There is no way to ensure that a service’s published interface remains constant over time. Every redeployment of the service may change the classes, and hence the contract.

The alternative of contract-last development is, of course, contract-first development. Using this approach, you start with the WSDL and schema, and create server-side stubs afterwards, if necessary. Because of the complexity of WSDL, and especially XSD schemas, this approach is not often used, but I think that using contract-first service development should be considered a best practice.

Luckily, this approach is practiced by some. Especially in large corporations, where multiple development teams work together to implement a service, or where one team defines the service while others use it as a client, the contract-first approach is used often. As one of my customers put it: it is not an option to regenerate client stubs every day or so. I totally agree; would you accept monthly changes in a legal, real-life contract? Why should your service contract be any different?

Comments off

Thoughts on Web Services, part 2: It’s not Remoting

When I started using SOAP on Java, I had a simple goal:

I wanted to expose my business interfaces via SOAP. I wanted the WSDLs to be generated automatically, and I wanted the value objects I used as parameters to be converted automatically. Most of all, I didn’t want to change my business interface just to support a remoting protocol. After all, I might want to support another protocol in a year or so, and did not want to change it again then.

Now, almost half a year later, I am starting to realize that it is not so simple. SOAP isn’t just another remoting protocol, such as Java RMI, Caucho’s Hessian Burlap, or .NET remoting. Using such a framework is pretty easy: just implement a specific interface, or extend a subclass, fire up a server process, and you’re done. It is so easy, because these protocols are centered around their respective languages: they support the language natively.

Unfortunately, this goes both ways: remoting frameworks only support the features of their respective frameworks. You can’t do multiple class inheritance in Java RMI, nor create an enumerated type using JDK 1.4, for example.

Web Services, on the other hand, are mostly based on XML. While is is possible to express an XML document in a OO language using something like DOM, there are some differences between XML and OO classes. The article Rethinking the Java SOAP Stack has an excellent summary on the conceptual differences between these two models. I will just mention two of the nine listed there:

  • Most importantly, an XML document is a tree structure, while an class structure is a (cyclic) graph. This means that you cannot simply serialize your objects to XML; you have to do some careful translation. In fact, this translation is so complicated that the Alpine folks refer to it as Object/XML mapping, to mare it comparable to the Object/Relational nightmare.
  • The language of XML Schema is much richer than the object model of Java. Thus, you simply cannot express all schema constructs within Java. For example, you cannot create restricted types in Java the way you can in a schema.

In summary, I think that we can safely say that a XML Service Architecture is a whole different beast than the good old remoting frameworks that we know and love. The question that remains is if it isn’t remoting, than what is it? We will find out in future posts.

Comments off

Thoughts on Web Services, part 1: Introduction

I have been doing a lot of thinking lately on the subject of Web Services. Recent talks I had with customers, my own experiences in the field, some talks I visited during conferences, and some interesting articles I read have changed my opinion of the subject significantly.

Because I have not been blogging for a while, I thought that it might be interesting to create a series of articles on this subject. This is the first post in that series; I don’t know how many will follow, right now I’m thinking of about three to five posts.

Please note that this series is not tied to any specific framework, be it .NET or Java. Additionally, please note that - as of yet - there is not relation with XFire; it might or might not be implemented into XFire, I do not know.

Comments off