Monday, October 6, 2008

HTTP content negotiation in Axis2

Keith Chapman has written a nice blog explaining how to set up and configure content negotiation support in Axis2.

I thought I will take the opportunity to explain some of Axis2's design so you understand how all of this works.

The way this works in Axis2 is with a pluggable message formatter concept. Basically, when a message hits the wire in Axis2, two key decisions need to be made: (a) what transport protocol to use (HTTP, SMTP, FTP, File, UDP, etc. etc. [yeah, I know .. calling HTTP a transport protocol is heresy]) and (b) how to format the message to bits on the wire.

The decision on how to format the message can be influenced via content negotiation. So if you send a message saying "hey I prefer JSON" (by sending an Accept: header with a JSON media type) then the runtime can look for a JSON formatter and if its available, then the response will be sent in JSON. If you say I want it in plain text, then again if such a formatter is available that's used. What parts of the internal message model is serialized into the wire is up to the message formatter to decide. If no preferred content information is available then the system figures out what it thinks is the right media type (typically based on the incoming media type) and uses the corresponding message formatter to write the bits.

Message reading happens in the exact opposite way in Axis2- you write a MessageBuilder which can "unformat" a media type and register that with the runtime. Then when a message comes its incoming media type is used to figure out who can read the message and create a canonical message in Axis2 represented in Axiom (as a SOAP Infoset).

The use of a the SOAP Infoset (aka an Axiom tree with s:Envelope as the outer element) as the internal message model has bothered some people. Two key things to remember: (1) this does not mean that every message is actually converted to an XML Infoset and (2) it does not mean the application or the wire message ever have to be SOAP aware or at all related to SOAP. Every runtime like Axis2 needs a canonical message representation and we've chosen the SOAP Infoset as the canonical message representation. No more, no less.

We avoid converting every message to even an XML Infoset by using Axiom's ability to provide an XML facade to any bit of data without actually making that facade real. Thus a message can come into Axis2 via Smooks say and can go out via another EDI message without ever being converted AT ALL into any XML representation. The bits can literally stay in the socket buffer and be streamed right out. That's key to achieving high performance. Apache Synapse (and WSO2 ESB, the open source ESBs built on Axis2, live on that capability to deliver incredible performance.

The beauty of this approach is that the message format decision and the transport protocol selection are totally orthogonal. What that means is that if you add say XMPP support, then instantly we can send/receive SOAP, JSON, plain text etc. etc. over XMPP with absolutely zero cost. Oh BTW Axis2 does have XMPP support already.

No comments: