Tuesday, August 3, 2010

My Take on the Document/Literal 'Wrapped' Idiom

If you've designed and built web services you've more than likely come across the "wrapped" idiom.  I like the wrapped idiom - we're talking of course with the assumption that the binding used is the SOAP binding (one of 2 out-of-the-box supported bindings from the WSDL specification - the other being an HTTP-based binding; there is a 3rd, MIME - but MIME extensibility-elements only extend the <input> and <output> sections of the operation of a binding).

I'm not going to speak at all about the merits of using the document style of SOAP along with literal parts - a quick Google search will yield dozens of articles that speak about why, generally speaking document/literal is the preferred approach when designing web services (of course there are those scenarios in which RPC style with SOAP-encoded parts would be preferable - it all depends on your specific requirements and situation).

In addition to document/literal, there is also the "wrapped" idiom.  This idiom basically stipulates that the root element of the SOAP body of a message should correspond to the operation being invoked - to achieve this the <input> message of the associated <operation> (of a port type) within the WSDL will map back to a type defined in the <types> section that semantically represents the OPERATION to be invoked, and not really the INPUT of the operation (I know - it's a little complicated and hard to explain - again, if you Google 'document/literal wrapped' you'll get a bunch of hits and pages that describe it better than I can).

So - why am I writing about this?  I just want to put out there that I don't view the "root" element of the SOAP payload to be the target METHOD or OPERATION of FUNCTION to be invoked.  Semantically, I view the root element of the payload, at the most basic level, to simply be a verb, or an action, or a command (whatever you want to call - just DON'T call it the operation or the method or the function being invoked on the service).  The reality is, it is up to the service HOW the message is to be processed.

But then I read a blog post by James Webber - in it he makes some very interesting points in his criticism of the wrapped idiom.  His main point is that document/literal is about passing application-level messages around and getting away from an RPC programming model.  Futhermore the consumer of the service should not have to tell the service what action or command to carry-out.  The service should figure this out on its own when it receives a message.  I understand his point completely, and I actually AGREE with him.  I think that one can absolutely argue that the 'wrapped' idiom is basically RPC with a different hat - you do get the bonus of gaining the ability to validate messages, but your back to this RPC world - and it is this world that we're trying to get away from.  Besides, if you need RPC, there are many alternatives - many of which are probably better than a SOAP-based one.

So here's the next question - if we abandon the wrapped idiom, HOW does the service know what to do with a message if there is no verb or command associated with it?  If I have a web service for calculating the estimated shipping cost of a potential order, and the service publishes itself such that it simply receives an <ShoppingCart> element, how does the service know what to do with it?  If we conform to the spirit of Jim's dislike of the wrapped idiom, then there shouldn't be anything about the SOAP request message itself that indicates the operation or action to be taken by the service when we send it an <ShoppingCart> message.  The fact that we sent a SOAP message to the service's endpoint in which the body contains an <ShoppingCart> should be enough.  In talking with my colleague, Dave Read about this, we likened the situation to paying your bill at a restaurant.  When the waiter gives you your bill, he does not have to explicitly instruct you that you now have to pay for your meal.  Nor do you have to explicitly instruct the waiter to use your credit card you just gave him to pay for it.  No - instead inferencing is used.  The mere fact that the waiter handed you your bill AT THE END of your meal, means that you now have to pay your bill.  You inferred this; the waiter did not have to explicitly tell you that you now have to pay your bill.

Our web service should also be able to infer, based on the content of the <ShoppingCart> message, that it needs to calculate the estimated shipping cost.  This inferencing can be implemented in any number of ways; it can be implemented in a low-tech way - i.e. the inferencing logic can be written directly in your programming code (e.g. Java, C#, Python, etc), or, you could use a more elegant approach such as using a rules engine (which is great at inferencing).  

With all that said, if you're just starting out and learning about web services, and learning about good service design, for the time being my advice would be to use the document/literal wrapped convention.  Again, there is a coupling that is created between consumer and service with this approach (again, as Jim points out in his blog entry), but at the end of the day this approach will simplify your service implementation - you won't need to deal with inferencing to understand how to process a message.  In using the wrapped idiom, I would recommend that you resist the urge to design the WSDL operations in terms of them being functions or methods; instead, think of them as commands or actions to be taken, that your service will fulfill.  I think if you follow this advice, your service will be easier to use and *feel* more natural to use by consumers and will minimize the coupling.

Perhaps in the future I'll write a blog entry on how to effectively migrate away from using the wrapped idiom, and instead use a rules engine, such as JBoss Drools, to leverage inferencing as the internal dispatch mechanism of your web services...stay tuned!

No comments:

Post a Comment