Version 7

    Seam solves the problem of LazyInitializationExceptions (LIE) for Conversations using a Seam Managed Persistence Context (SMPC).  Seam's EntityHomes make it trivial to solve this problem for 'longer' scopes - SESSION, APPLICATION AND BUSINESS_PROCESS.

     

    How to use it

     

    @Name("currentUserHome")
    public class CurentUserHome extends EntityHome<User> {
       
       @Out(scope=ScopeType.SESSION, required=false)
       @In(required=false)
       private Integer currentUserId;
    
       @Factory(value="currentUser")
       public User produceUser() {
          return getInstance();
       }
         
       @Override
       protected User createInstance() {
          if (currentUserId != null) {
             return getEntityManager().find(User.class, currentUserId);
          } else {
             return new User();
          }
       }
    
    }
    

     

    How does it work?

     

    Well, if you simply annotate your entity with @Name and @Scope, then, when loaded (using a SMPC) and outjected, it is stored in the desired context.  BUT, if you then leave the conversation in which it was loaded, you will get an LIE if you access a property which was not initialised inside that conversation. Ouch.

     

    So, instead of storing the entity in a scope longer than Conversation, we store the id of the entity in the long running scope and the entity in the conversation.  Using a @Factory we initialise the entity context variable.  If the id is null a new entity is created, otherwise a fresh copy of the entity is loaded  and attached to this conversation.

     

    Configuring via components.xml

     

    In the above example currentUserId is never changed, so the @Out has only the effect to transfer currentUserId to session scope. So you can set currentUserId in any scope and after accessing currentUser you will find the currentUserId automatically bound to session scope.

    But nothing hinders you to set the currentUserId directly in session scope.

    If you do this, it is possible to achieve the same by configuration in components.xml. Code:

        <factory name="currentUser" value="#{currentUserHome.instance}"></factory>
        <framework:hibernate-entity-home name="currentUserHome" entity-class="class.for.User">
             <framework:id>#{currentUserId}</framework:id>
        </framework:hibernate-entity-home>     
    

    (Note: in this example a HibernateEntityhome is used instead of an EntityHome)

     

    This behaves exactly the same,iff you set currentUserId in the correct scope(here session).

    This works with seam1.1.6