I've been developing software for over 15 years working in Delphi and now Java. This site is a home for my open source projects, writings, articles and tutorials mainly focusing on Java and Java EE. Andy is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

A Little Less Conversation…

02.03.2011
| 4250 views |
  • submit to reddit

One thing that I wrote that I haven’t really gotten around to examining and verifying in closer detail and validating my position on is the production of the conversational entity manager in the Knappsack archetypes. This article looks at this and re-evaluates my thinking on the use of conversational contexts in CDI.

Defaulting to Request Scoped

It’s one of those things that you write and it works, but something feels wrong with it, and I haven’t had time to go back and look at it. The entity manager is scoped to the conversation so that it will work with as both conversational and request scoped. When an object is scoped to the conversation and there is no long running conversation then the conversation itself is limited to the request so your data, although conversation scoped becomes request scoped. This was a handy way to default data that was mostly request scoped to a request scope while giving it the ability to partake in active conversations. In Seam, this was fairly standard practice since it allowed your model to live in a conversational entity manager without having to worry about detachment issues. However, CDI conversations are different from Seam conversations and their use needs to be a little more focused.

The problem is that CDI is supported in a number of environments within Java EE 6 while the conversation scope is not. To name a few, servlets and web services don’t have default support for conversations and Arquillian tests doesn’t handle conversations well. While we may be able to work around non-conversational servlets, web services and arquillian tests, the problem really goes deeper.

Logically we are thinking about using these beans as request scoped beans because there is no long running conversation. However, the conversational context still needs to be initialized and available to hold these beans. CDI doesn’t magically know to put the conversational beans in the request scope context when there’s no long running conversation, it always puts it in the conversational context.

So, the answer you say is to use request scoped beans and relegate a conversational scope to those cases where you really do need a conversational scope, and not use it everywhere you want request scoped but might need a conversation scoped bean. While this is true, our request scoped beans depend on business logic beans that in turn use the data layer beans that uses our entity manager to access the database. The problem is that the entity manager is conversation scoped so all our beans that depend on it are broken.

The end result is that using some of the tools and API’s with CDI has been rather frustrating since nearly every bean depends on the entity manager at the end of the day and without conversation support it typically breaks with an obscure error message.

The solution is to treat our entity manager like our beans, we only use conversations where absolutely necessary. The question you may be asking yourselves is how to deal with code that is both request and conversation scoped. For example, you load an entity at the start of a wizard into a conversation scoped bean using a conversation scoped entity manager because you want to keep this bean attached for the duration of the conversation. At the end of the conversation, you might want to use the standard request scoped entity Dao to save the entity. Will the request scoped Dao will use a different entity manager from the conversation scoped bean or not? The good news is that we can re-use the same entity manager sourced from the same place and offered up as a request scoped entity manager to get around this so they will use the same entity manager.

Additionally, the introduction of some of the new JSF 2.0 scopes helps out since we can use the flash or view scopes to pass objects from one page to the next or to maintain state between requests. The only problem here is that these scopes are in JSF and not compatible with CDI, or implemented in CDI by default. The Seam 3 faces module provides CDI compatible alternatives and I would put good money on those scopes making it into the next version of CDI.

Lesson Learned

One take away from this is to always make sure everything will play nice together before committing to a particular strategy or design. It would have been a shame to implement our data access layer and find out that we couldn’t use it in our web services or testing.

I’ll be trying to spend a little time working all this out and seeing what the best strategies are, but hopefully this will remove some of the barriers to demonstrating and adding third party integrations into the Knappsack archetypes. This will probably get changed for the next version of the Knappsack archetypes.

 

From http://www.andygibson.net/blog/article/a-little-less-conversation/

Published at DZone with permission of Andy Gibson, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Thomas Kern replied on Thu, 2012/09/06 - 10:47am

Hi,

I really enjoyed reading this article.
I do have a question regarding the wizard example above: do I really need an entity to model the data the wizard is gathering through all of its pages? I think a DTO is enough. At the end of the wizard, you get an entity manager which will fetch the entity from DB and will update its fields based on the DTO. In this way, all the problems related to request/conversational scope are gone. The DTO will live inside a conversation, but the entity to be updated will live inside a request scope. What do you say ?

http://www.java-tips.org

George Armhold replied on Sun, 2012/04/08 - 9:40am

Hi Andy,

Thanks for the great series. I came here researching the concept of conversation-scoped EntityManagers in CDI. I have a project that was developed around Weld, and takes a similar approach: the EntityManager is scoped as conversational by the producer in order to support "wizard-like" flows.

This worked great in Weld, but my IDE warned that "managed beans declaring a passivating scope must be serializable". I.e. it's complaining because the EntityManager is not Serializable (even though Hibernate's impl is serializable, the interface is not). The CDI spec indicates that session, application and conversation scoped beans must be serializable, though it seems to work fine in Weld despite this.

Sure enough when I tried to run the app under WebSphere (openwebbeans, instead of Weld) it failed because the EntityManager is not Serializable.  I'm curious what your thoughts are on this.

Thanks again for writing this very helpful series. 

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.