9 Replies Latest reply on Jun 30, 2006 10:09 PM by javajedi

    How do I reattach entities using a ManagedHibernateSession?

      I'm using a ManagedHibernateSession with a SeamExtendedManagedPersistencePhaseListener. When Seam renders the view, it starts the 2nd transaction successfully. However, it is not attaching any of my entities to a Hibernate Session. This causes LazyInitializationExceptions whenever I try to access a lazily-initialized property on one of my entities from my view.

      The workaround that I am currently using is to reattach my entities manually. Basically, in the first getter that is called from the view, I'm calling sessionFactory.getCurrentSession().update(myEntity). But from what I can tell looking at the Seam docs, this shouldn't be necessary.

      Any suggestions as to how I might try to track down the problem?

        • 1. Re: How do I reattach entities using a ManagedHibernateSessi
          gavin.king

          Are you using a conversation?

          • 2. Re: How do I reattach entities using a ManagedHibernateSessi

            Yes, sorry I neglected to mention that. Here is the relevant code:

            @Stateful
            @Scope(ScopeType.CONVERSATION)
            @Name("campaignEditor")
            public class CampaignEditorBean implements CampaignEditor {
            
             @Valid @In(required=false) @Out
             private Campaign campaign;
            
             @In(create=true)
             private Session session;
            
             @Begin(join=true)
             public String select() {...
            
             @End
             public String update() {...
            ...
            
            @Entity
            @Name("campaign")
            @Scope(ScopeType.SESSION)
            public class Campaign {
            ...
            


            In my view, I reference properties on "campaign". Whenever I try to reference any property that is lazily initialized, I get the LazyInitializationException unless I first manually call sessionFactory.getCurrentSession().update(campaign).

            • 3. Re: How do I reattach entities using a ManagedHibernateSessi
              gavin.king

              The problem is the ScopeType.SESSION bit. This functionality is only for conversation-scoped data.

              • 4. Re: How do I reattach entities using a ManagedHibernateSessi

                Thanks for the reply. I modified the entity as follows:

                @Entity
                @Name("campaign")
                @Scope(ScopeType.CONVERSATION)
                public class Campaign {
                ...
                


                However, I still have the same problem. Here is the debug output from Seam where it looks like it's resolving "campaign":

                2006-06-30 16:34:08,471 DEBUG [org.jboss.seam.jsf.SeamVariableResolver] resolving name: campaign
                2006-06-30 16:34:08,471 DEBUG [org.jboss.seam.contexts.Contexts] found in conversation context: campaign
                2006-06-30 16:34:08,471 DEBUG [org.apache.myfaces.el.VariableResolverImpl] Variable 'campaign' could not be resolved.
                2006-06-30 16:34:08,471 DEBUG [org.jboss.seam.jsf.SeamVariableResolver] resolved name to seam component
                


                Any other suggestions?

                • 5. Re: How do I reattach entities using a ManagedHibernateSessi
                  gavin.king

                  Did you actually retrieve the Campaign from the conversational persistence context? Or is it some other object you had lying around before the conversation started?

                  It is really not helpful when you chop out the actually intersting code in select() and update().

                  • 6. Re: How do I reattach entities using a ManagedHibernateSessi

                    Sorry. The Campaign came from another SFSB (CampaignManager), where it came from a list using @DataModelSelection. Here's the code without the omissions:

                    @Stateful
                    @Scope(ScopeType.CONVERSATION)
                    @Name("campaignEditor")
                    public class CampaignEditorBean implements CampaignEditor {
                    
                     @In
                     private CampaignManager campaignManager;
                    
                     @Valid @In(required=false) @Out
                     private Campaign campaign;
                    
                     @In(create=true)
                     private Session session;
                    
                     @Begin(join=true)
                     public String select() {
                     campaign = campaignManager.getSelectedCampaign();
                     return "editCampaign";
                     }
                    
                     @End
                     public String update() {
                     session.update(campaign);
                     return "campaigns";
                     }
                    }
                    
                    @Stateful
                    @Scope(ScopeType.SESSION)
                    @Name("campaignManager")
                    public class CampaignManagerBean implements CampaignManager {
                    
                     @DataModel
                     private List<Campaign> campaigns;
                    
                     @DataModelSelection
                     private Campaign campaign;
                    
                     public Campaign getSelectedCampaign() {
                     return campaign;
                     }
                    }


                    So yes, I guess you could say the Campaign was "lying around" before the campaign started. Is there any way that I can use the @DataModelSelection campaign in the conversation, so I can get around the LazyInitializationExceptions?

                    • 7. Re: How do I reattach entities using a ManagedHibernateSessi
                      gavin.king

                      Thats what I guessed. So you need to do:

                       @Begin(join=true)
                       public String select() {
                       campaign = session.lock( campaignManager.getSelectedCampaign(), LockMode.NONE );
                       return "editCampaign";
                       }
                      


                      In order to get a Campaign that is associated with the conversation. After doing this once at the beginning of the conversation, you will not need to do it again.

                      • 8. Re: How do I reattach entities using a ManagedHibernateSessi

                        Awesome. That works great. Thanks so much for the help.

                        • 9. Re: How do I reattach entities using a ManagedHibernateSessi

                          I spoke a little too soon. The second time that I try to invoke CampaignEditorBean.select on the same campaign, I get a "reassociated object has dirty collection" HibernateException from the session.lock call.

                          Caused by: org.hibernate.HibernateException: reassociated object has dirty collection
                           at org.hibernate.event.def.OnLockVisitor.processCollection(OnLockVisitor.java:45)
                           at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
                           at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
                           at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
                           at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
                           at org.hibernate.event.def.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:78)
                           at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:59)
                           at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:583)
                           at org.hibernate.impl.SessionImpl.lock(SessionImpl.java:575)
                           at CampaignEditorBean.select(CampaignEditorBean.java:61)