2 Replies Latest reply on Aug 6, 2008 9:54 AM by Alexander Torstling

    Issue with Hibernate cascade types and merging a detached entity into a long running conversation

    Richard Ogin Newbie

      I recently posted a question here about getting a detached entity working with a long running conversation. I believe I'm now having a problem with the cascading operations with its collections which is causing a StaleObjectStateException. I think this may need to go under a Hibernate forum, but it involves Seam so I'm wary of going straight to them.


      My test case is very simple. Click a button to edit an object:


      <s:button value="Edit" action="#{Manager.requestEdit}" propagation="begin" pageflow="edit-test"/>
      



      The Manager.java class that gets called:


      @Name("Manager")
      @Scope(ScopeType.CONVERSATION)
      @Restrict("#{identity.loggedIn}")
      public class Manager implements Serializable
      {
           @In(required=false)
           private Session session;
           
           @In(required=false)
           @Out(required=false)
           private Client activeClient;
      
           @Create
           public void init() {System.err.println("cm.init()");}
           
           @Destroy
           public void destroy() {System.err.println("cm.destroy()");}
           
           public String requestEdit()
           {
                System.err.println("cm.requestEdit() version: " + activeClient.getVersion());
                session.setFlushMode(FlushMode.MANUAL);
                
                session.refresh(activeClient);
                activeClient = (Client)session.merge(activeClient);
                
                return "start";
           }
      
              public String save()
           {
               ...if valid
               session.saveOrUpdate(activeClient);
               session.flush();
               return "save";
           }
      ...
      



      Click save on that page which calls save() defined above and kicks me back to the start page. My annotated debug follows (NOTE: I didn't change any fields during the edit page, so only the version is incrementing):


      <click edit button>
      14:17:58,806 ERROR [STDERR] cm.init()
      14:17:58,820 ERROR [STDERR] cm.requestEdit() version: 114
      <click save>
      14:18:07,716 ERROR [STDERR] cm.destroy()
      <click edit button>
      14:18:11,115 ERROR [STDERR] cm.init()
      14:18:11,142 ERROR [STDERR] cm.requestEdit() version: 115
      <click save>
      14:18:19,497 WARN  [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@267eaba4<rs=org.postgresql.jdbc3.Jdbc3ResultSet@67057f08>
      ...about x50 of these fail-safe cleanups
      14:18:19,508 ERROR [STDERR] cm.destroy()
      <click edit>
      14:18:39,837 ERROR [STDERR] cm.init()
      14:18:39,850 ERROR [STDERR] cm.requestEdit() version: 115
      14:18:40,960 ERROR [SeamPhaseListener] uncaught exception
      javax.el.ELException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [acme.Client#1]
           at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:332)
           at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:341)
           at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58)
           at org.jboss.el.parser.AstValue.invoke(AstValue.java:96)
           at org.jboss.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
           at org.jboss.seam.core.Expressions$2.invoke(Expressions.java:174)
           at org.jboss.seam.navigation.Pages.callAction(Pages.java:634)
           at org.jboss.seam.navigation.Pages.preRender(Pages.java:289)
           at org.jboss.seam.jsf.SeamPhaseListener.preRenderPage(SeamPhaseListener.java:544)
           at org.jboss.seam.jsf.SeamPhaseListener.beforeRenderResponse(SeamPhaseListener.java:455)
           at org.jboss.seam.jsf.SeamPhaseListener.beforeServletPhase(SeamPhaseListener.java:146)
           at org.jboss.seam.jsf.SeamPhaseListener.beforePhase(SeamPhaseListener.java:116)
           at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:222)
           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.MultipartFilter.doFilter(MultipartFilter.java:85)
           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:44)
           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:60)
           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.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.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
           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:595)
      Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [acme.Client#1]
           at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:261)
           at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
           at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
           at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
           at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
           at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
           at org.jboss.seam.persistence.HibernateSessionProxy.merge(HibernateSessionProxy.java:310)
           at acme.Manager.requestEdit(ObjectA.java:120)
           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:585)
           at org.jboss.seam.util.Reflections.invoke(Reflections.java:21)
           at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
           at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:46)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.persistence.ManagedEntityIdentityInterceptor.aroundInvoke(ManagedEntityIdentityInterceptor.java:48)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:31)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.bpm.BusinessProcessInterceptor.aroundInvoke(BusinessProcessInterceptor.java:49)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:42)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.security.SecurityInterceptor.aroundInvoke(SecurityInterceptor.java:40)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:106)
           at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:155)
           at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:91)
           at acme.Manager_$$_javassist_3.requestEdit(Manager_$$_javassist_3.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:585)
           at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:328)
           ... 51 more
      14:18:41,182 INFO  [lifecycle] WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
      sourceId=null[severity=(INFO 0), summary=(Unexpected error, please try again), detail=(Unexpected error, please try again)]
      sourceId=null[severity=(WARN 1), summary=(Illegal navigation), detail=(Illegal navigation)]
      14:33:08,630 WARN  [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@4ef44447<rs=org.postgresql.jdbc3.Jdbc3ResultSet@3ccc9ff5>
      ...again, about 50 of these fail-safe cleanups
      
      



      I'm doing the refresh() then merge() as activeClient is a detached entity that I want associated with the current conversation. If I remove refresh(), the StaleObjectStateException happens immediately on the merge() on the second edit click if I recall correctly. As stated before, I'm changing nothing in the activeClient and no one else is on the system to make simultaneous changes. Oh, and my activeClient has several collections that are all set to CascadeType.ALL. I know it's long so thanks for reading :p