4 Replies Latest reply on Dec 5, 2008 8:01 PM by sbyrne.sb.ezftz.com

    New Session or EntityManager for nested conversation?

    sbyrne.sb.ezftz.com

      I am not sure if I misunderstand how nested conversations work, or if I mis-configured Seam.


      I am doing the following (across multiple requests):



      1. Create (long-running) conversation 1.

      2. Obtain Session from conversation Context.

      3. Load Object a with Session.

      4. Modify a

      5. Outject a

      6. Create (nested) conversation 2.

      7. Obtain Session from conversation Context.

      8. Load Object b with Session.

      9. Modify b

      10. Flush Session.

      11. End (nested) conversation 2.

      12. End conversation 1 (without flushing Session).



      I have default-flush-mode=MANUAL set on <core:manager /> in my components.xml.


      I expected that my modifications to a would not be committed, but my modifications to b would be committed.


      In my example above, I expected that I would get a new Session when I started my nested conversation.  I understand that if this were the case, if I wanted to use a with the Session from conversation 1, I would have to merge it with my Session from conversation 2.


      More generically, I thought that:



      •   A nested conversation gets a new Context.

      • Asking for a Component from the conversation Context first checks the current conversation's Context, then the parent conversation's Context (if the current conversation is nested), then the grandparent conversation's Context, and so on up to the root conversation's Context.

      • When outjecting a Component to the conversation Context, it is put in the current conversation's context. After a redirect to the parent conversation, the Component is no longer accessible.

      • When starting a nested Conversation, Seam would create new Sessions for the configured ManagedHibernateSessions (or EntityManagers for the configured ManagedPersistenceContexts if using JPA).



      Where have I gone wrong?

        • 1. Re: New Session or EntityManager for nested conversation?
          sbyrne.sb.ezftz.com

          My testing tells me that the first three bullets in the More generically, I thought that: list are correct and the fourth is not.


          Is there a way to configure seam to create a new Hibernate Session for each Conversation, or should I write an Observer that creates one?

          • 2. Re: New Session or EntityManager for nested conversation?
            sbyrne.sb.ezftz.com

            I tried this to create a new Session for nested conversations:


            @Scope(ScopeType.STATELESS)
            @Name("persistenceConversationObserver")
            public class PersistenceConversationObserver {
            
                @Logger
                private Log log;
            
                @In
                private Conversation conversation;
            
                @Out(required = false, scope = ScopeType.CONVERSATION)
                private Session mySession;
            
            
                @Observer(value="org.jboss.seam.beginConversation")
                public void newSessionForNestedConversation() {
                    if ( conversation.isNested() ) {
                        log.debug( "New nested conversation:" + conversation.getId() );
                        try {
                            mySession = newSession( "hibernateSessionFactory" );
                        } catch ( Exception e ) {
                            log.warn( "Error creating Session for nested Conversation."
                                    + " This conversation will use the parent's Session."
                                    + " (" + e.getMessage() + ")", e );
                        }
                    }
            
                }
            
            
                private Session newSession( String sessionFactoryComponentName )
                    throws Exception {
                    SessionFactory sessionFactory = (SessionFactory)
                        Component.getInstance( sessionFactoryComponentName );
                    Session session = sessionFactory.openSession();
                    log.debug( "New Session for " + sessionFactoryComponentName
                            + ": " + session.hashCode() );
                    return session;
                }
            
            
            }
            



            It creates new Sessions as expected when nested conversations are created.
            But soon after I get this error:


            java.lang.ClassCastException: org.jboss.seam.persistence.FullTextHibernateSessionProxy
                 at org.jboss.seam.persistence.PersistenceContexts.changeFlushModes(PersistenceContexts.java:100)
                 at org.jboss.seam.persistence.PersistenceContexts.changeFlushMode(PersistenceContexts.java:93)
                 at org.jboss.seam.core.ConversationInterceptor.setFlushMode(ConversationInterceptor.java:205)
                 at org.jboss.seam.core.ConversationInterceptor.beginConversationIfNecessary(ConversationInterceptor.java:167)
                 at org.jboss.seam.core.ConversationInterceptor.aroundInvoke(ConversationInterceptor.java:57)
                 at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                 at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
                 at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                 at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
                 at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166)
                 at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102)
                 at com.mycompany.AdmissionManager_$$_javassist_12.findAdmissionList(AdmissionManager_$$_javassist_12.java)
                 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                 at java.lang.reflect.Method.invoke(Method.java:597)
                 at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
                 at org.jboss.seam.util.Reflections.invokeAndWrap(Reflections.java:138)
                 at org.jboss.seam.Component.callComponentMethod(Component.java:2171)
                 at org.jboss.seam.Component.getInstanceFromFactory(Component.java:2003)
                 at org.jboss.seam.Component.getInstance(Component.java:1938)
                 at org.jboss.seam.Component.getInstance(Component.java:1910)
                 at org.jboss.seam.Component.getInstance(Component.java:1904)
                 at org.jboss.seam.Namespace.getComponentInstance(Namespace.java:55)
                 at org.jboss.seam.Namespace.getComponentInstance(Namespace.java:50)
                 at org.jboss.seam.el.SeamELResolver.resolveBase(SeamELResolver.java:166)
                 at org.jboss.seam.el.SeamELResolver.getValue(SeamELResolver.java:53)
                 at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:53)
                 at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64)
                 at org.jboss.el.parser.AstIdentifier.getValue(AstIdentifier.java:44)
                 at org.jboss.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
                 at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
                 at javax.faces.component.UIData.getValue(UIData.java:582)
                 at org.ajax4jsf.component.UIDataAdaptor.getValue(UIDataAdaptor.java:1620)
                 at org.ajax4jsf.component.SequenceDataAdaptor.getDataModel(SequenceDataAdaptor.java:48)
                 at org.ajax4jsf.component.SequenceDataAdaptor.createDataModel(SequenceDataAdaptor.java:42)
                 at org.richfaces.component.UIDataTable.createDataModel(UIDataTable.java:123)
                 at org.ajax4jsf.component.UIDataAdaptor.getExtendedDataModel(UIDataAdaptor.java:622)
                 at org.ajax4jsf.component.UIDataAdaptor.getRowCount(UIDataAdaptor.java:249)
                 at org.richfaces.component.UIDatascroller.getRowCount(UIDatascroller.java:343)
                 at org.richfaces.component.UIDatascroller.getPageCount(UIDatascroller.java:318)
                 at org.richfaces.component.UIDatascroller.setupFirstRowValue(UIDatascroller.java:433)
                 at org.richfaces.component.DataScrollerViewPhaseListener.beforePhase(DataScrollerViewPhaseListener.java:225)
                 at org.ajax4jsf.component.AjaxViewRoot.processPhaseListeners(AjaxViewRoot.java:184)
                 at org.ajax4jsf.component.AjaxViewRoot.encodeBegin(AjaxViewRoot.java:500)
                 at javax.faces.component.UIComponent.encodeAll(UIComponent.java:884)
                 at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
                 at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
                 at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:189)
                 at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)
                 at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
                 at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)
                 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
                 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                 at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:38)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:154)
                 at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:260)
                 at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:366)
                 at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:493)
                 at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:51)
                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                 at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                 at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
                 at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
                 at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                 at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
                 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
                 at java.lang.Thread.run(Thread.java:619)
            



            Any other ideas on how to accomplish this?

            • 3. Re: New Session or EntityManager for nested conversation?
              stefanotravelli

              Wrapping the session in a FullTextHibernateSessionProxy before outjecting could help, but I think that this hack will give you some other error, sooner or later.


              Nested conversations share session/entitymanager with parents otherwise you couldn't work with persistent entities without incurring in lazy loading error, etc. 


              Take a look at this thread and how my assumptions was wrong: wiki://49253


              stefano

              • 4. Re: New Session or EntityManager for nested conversation?
                sbyrne.sb.ezftz.com

                Stefano Travelli wrote on Dec 05, 2008 17:41:


                Nested conversations share session/entitymanager with parents otherwise you couldn't work with persistent entities without incurring in lazy loading error, etc. 


                I understand that if the nested conversation had its own Session/EntityManager that I would have to merge any persistent entities managed by the parent conversation's Session/EntityManager.


                That is exactly the behavior I want. If a nested conversation is not separate from the parent conversation as far the the database transaction is concerned, nested conversations are useful only for page flow, not for business logic separation.


                The idea of a transactionally independent nested conversation was the compelling reason for using Seam for me.