If Flex is dominting RIA world, CXF is dominating SOA world with its feature rich framework. CXF not only makes developers life easy by abstracting many complex task through a set of APIs but also adheres to WS-* standards without a need to having dependency on other frameworks.
On an average to develop a webservices using CXF, would hardly require 5 minutes (If developers use Code First Approach). Developer need to declare a business interface, implementation class for same and annotate both these entities with JAX-WS annotation, configure the webeservice and pufff, you are done. You don’t even need to run Webservices, plug the configuration with built-in web container and you can test Webservices right from your IDE.
Well to explain all the features of CXF, this articles won’t be enough (I would rather end up writing 1000’s of pages.). While working on one of the project involving CXF, Blaze DS, Spring and Flex, we faced one problem and that turned out to be worst nightmare. We had created a set of webservices exposed through CXF and deployed with its own WAR file. On the other hand, we had created one more application, holding Flex SWF files, JAX-WS client configured through CXF – Spring configuration in XML. The clients were injected in Remoting Destination, using SPRING dependency injection feature. Finally the remoting destinations were exposed through SPRING – Blaze DS integration project.
So far, everything worked well except one problem, each time remoting destination invokes webservice operation, a new session was getting created and hence webservices were not able to maintain state of the Client.
After visiting to various forums and going through the CXF documentation we found that, CXF does provide a way to maintain session and same is explained at
- http://stackoverflow.com/questions/1741314/jaxwsproxyfactorybean-sharing-http-session (Check first reply, second reply provided by me for handler does work perfectly.)
While both the approach are able to maintain session at client side, it requires that the client code should be aware of webservices API. In our case, since JAXWS:Client was injected through SPRING configuration, making beans aware of WS API would break the architecture. Also using both the above discussed approach are having there own problem, first solution will not be suitable if the number of webservices is huge. This means it would require tracking all the webservices in application. Second approach works well for a single webservice, the moment you use another webservice of same application, voilaaa.. you will see a new session is again created.
Well, we didnt had an option but to somehow maintain session between WS-Client and WS. A thought came in my mind to check how CXF maintains session for a single webservice using BindingProvider, I started going through HTTPConduit.
After carefully reading the source code, I realised that if I could able to add Message.PROTOCOL_HEADERS to every webservice context in a generic way, my job is done. Adding Message.PROTOCOL_HEADERS to webservice context, gives developer a chance to play with HTTP headers. I developed a JAX-WS handler and tracked the request/response for every webservice invocation and added a logic to cofigure Message.PROTOCOL_HEADERS. And yippy!!! my webservice clients are now able to maintain session and that too without a need of modifying webservice client.
All I need to do is,
- Create JAX-WS handler and configure it in SPRING configuration file.
- Add handler to Webservice client.
- Use BlazeDS API to hold/retrieve reference of WS session cookies and play with Message.PROTOCOL_HEADERS.
I like the extension points provided by CXF to accomplish tasks which are not so easily available in other frameworks.