Seam3 Conversation SPI

Posted by    |      

When Pete handed over the Weld helm he said I should blog a lot. :-) As much as I would like to do this, it’s actually impossible to squeeze massive blogging into my working hours. But of course that doesn’t mean I won’t blog completely. Here for a change, not being MC related, is my first blog whose theme is Weld/CDI based. ;-)

Seam3’s aim is to be CDI implementation agnostic. One of the hurdles standing in its way of achieving this 100% is how CDI handles conversation scope. For some reason, Pete will probably know better why, generic conversation handling escaped final spec release. Atm, afaik, only JSF conversation handling is mandatory. With Weld we already tackle this in a generic way, which helps some of the Seam3 modules to take advantage of this; e.g. Remoting being one of them. But this means that any Seam3 sub-project that uses this isn’t portable across CDI implementations.

To get my feet wet with Seam3 and to learn to some extent how other non-Weld CDI implementations actually work, I set off with a task of implementing Seam3 conversation handling in a CDI implementation agnostic and generic way.

In order not to re-invent the wheel, and the fact this is already used, hence proven to work to some extent, I simply used existing Weld generic conversation handling SPI and checked if I can make it work on other known CDI implementations as well. And I’m pleased to say that I did succeed :-), making this “new” SPI a valid candidate for upcoming CDI 1.1 spec.

I’m sure there are still some bugs, specially in non-Weld based SPI implementations, so any feedback appreciated. Also, currently CanDI’ conversation handling is tightly coupled with JSF API, so I had to use some JSF hacks to get past this tight coupling.

Now let me explain, show and list a few details.

The code is now part of Seam3 project:

As you can see, there is a module for each known CDI implementation (in case I missed some, let me know) and a simple SPI module.

The SPI is basically a single interface, the other classes are mostly helpers.

public interface SeamConversationContext<T>
{
 /**
  * Associate storage with conversation context.
  *
  * @param storage the current storage
  * @return the flowing current SeamConversationContext instance
  */
 SeamConversationContext<T> associate(T storage);

 /**
  * Activate conversation with given id.
  *
  * @param conversationId the conversation id to activate
  * @return the flowing current SeamConversationContext instance
  */
 SeamConversationContext<T> activate(String conversationId);

 /**
  * Invalidate conversation context.
  *
  * @return the flowing current SeamConversationContext instance
  */
 SeamConversationContext<T> invalidate();

 /**
  * Deactivate conversation context(s).
  *
  * @return the flowing current SeamConversationContext instance
  */
 SeamConversationContext<T> deactivate();

 /**
  * Dissociate storage with conversation context.
  *
  * @param storage the current storage
  * @return the flowing current SeamConversationContext instance
  */
 SeamConversationContext<T> dissociate(T storage);
}

Actual implementation depends on underlying storage type, by default this is HttpServletRequest, to which we already provide implementations for all known CDI implementations, but can be anything you like, as long as you have a backing implementation. e.g. in Weld there is a Map based implementation as well

There is still a TODO in SeamConversationContextFactory (see its match()), on how to best find matching implementation based on storage type. Any ideas welcome.

To get a hold of SeamConversationContext instance, simply @Inject it, or use SeamConversationContextFactory::getContext.

Another quite useful thing I hacked, if you ask me :-), and which is probably a must-have, is to have a proper test for all implementations. I’m testing the SPI against Weld and OpenWebBeans in embedded Tomcat6, where Resin4 is already a CanDI container by itself. All this testing wouldn’t be possible w/o fantastic Arquillian project. Here I would also like to thank Dominik Dorn for providing initial Resin4 integration, which is what I borrowed and fixed a bit, and it’s a must-have for doing CanDI testing. You can find my Arquillian Resin4 branch here:

I’m gonna try to do a proper release in the next days, so this can already be used in other Seam3 modules that might need it or any other conversation handling code that wants to take advantage of being CDI implementation agnostic. And as such, with wider usage, we should also be able to fix any issues that come along.

For any issues either drop a comment here, email me, open-up a JIRA issue in http://issues.jboss.org/browse/SEAM under Conversation Management component or best, create a github pull request against upstream master.


Back to top