3 Replies Latest reply on May 9, 2007 8:24 PM by David Fedchenko

    Help with StaleObjectStateException needed

    Kristoffer Carnmarker Newbie

      I can't understand why I'm getting a StaleObjectStateException in my action. Or rather, I understand why, but I don't understand why the entity is not up to date.

      This is a simplified version of my action:

       @In(create = true)
       EntityManager database;
      
       @In
       @Out
       private User loggedInUser; //created by Authenticator
      
       @DataModel
       private List<ListBidItem> listBidItems = new ArrayList<ListBidItem>();
      
       @Begin(join = true)
       public void addBidItem(ActionEvent event){
       ListBidItem newItem = new ListBidItem();
       listBidItems.add(newItem);
       }
      
       @End
       public void yesConfirmSave() {
       confirming = false;
       //database.refresh(loggedInUser); //doesn't seem to help
       Date now = new Date();
       Bid bid = new Bid();
       bid.setCreatedOn(now);
       bid.setCreatedBy(loggedInUser);
       bid.setBidder((Bidder) loggedInUser);
       ((Bidder) loggedInUser).setBid(bid);
      
       for (ListBidItem lbi: listBidItems) {
       BidItem bi = lbi.getBidItem();
       bi.setCreatedBy(loggedInUser);
       bi.setCreatedOn(now);
       bi.setBid(bid);
       bid.getBidItems().add(bi);
       }
       database.persist(bid);
       loggedInUser = bookBuildingDatabase.merge(loggedInUser);
       }
      


      pages.xml is simple:
       <page view-id="/restricted/createBid.xhtml">
       <restrict>#{s:hasRole('Bidder')}</restrict>
       <navigation from-action="#{bidderBidManager.yesConfirmSave}">
       <end-conversation/>
       <redirect view-id="/restricted/createBid.xhtml"/>
       </navigation>
       </page>
      


      The User entity has a property:

       @Version
       @Column(name="VERSION")
       protected int version;
      


      Now, when yesConfirmSave is called the first time after log in, everything works fine. When the user trues to save a second Bid, however, the StaleObjectStateException is thrown. From debugging the addition of the second bid, I can see that the the loggedInUser's Bid is correctly set, but the version number is not up to date. Adding the database.refresh() call does not seem to help either.

      (I know the use case does not make sense, seeing as a user can only have one bid, but please disregard that :) )

      Thanks


      Here's the stack trace:
      [2007-03-06 18:20:25,781] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/TTS-BookBuilding].[Blocking Servlet] Servlet.service() for servlet Blocking Servlet threw exception
      javax.faces.FacesException: Error calling action method of component with id bidForm:_id64
       at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:74)
       at javax.faces.component.UICommand.broadcast(UICommand.java:106)
       at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:94)
       at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:168)
       at org.apache.myfaces.lifecycle.LifecycleImpl.invokeApplication(LifecycleImpl.java:343)
       at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:86)
       at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.renderCyclePartial(BlockingServlet.java:473)
       at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.receiveUpdates(BlockingServlet.java:442)
       at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.executeRequest(BlockingServlet.java:324)
       at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:186)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
       at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:833)
       at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:639)
       at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1285)
       at java.lang.Thread.run(Thread.java:595)
      Caused by: javax.faces.el.EvaluationException: /restricted/createBid.xhtml @90,154 action="#{bidderBidManager.yesConfirmSave}": javax.ejb.EJBException: javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.ttsme.bb.entities.Bidder#<null>]
       at com.sun.facelets.el.LegacyMethodBinding.invoke(LegacyMethodBinding.java:73)
       at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:63)
       ... 22 more
      Caused by: javax.ejb.EJBException: javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.ttsme.bb.entities.Bidder#<null>]
       at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:69)
       at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
       at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:197)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.stateful.StatefulInstanceInterceptor.invoke(StatefulInstanceInterceptor.java:81)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.stateful.StatefulContainer.localInvoke(StatefulContainer.java:189)
       at org.jboss.ejb3.stateful.StatefulLocalProxy.invoke(StatefulLocalProxy.java:98)
       at $Proxy66.yesConfirmSave(Unknown Source)
       at com.ttsme.bb.actions.BidderBidManagerLocal$$FastClassByCGLIB$$9b740d18.invoke(<generated>)
       at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
       at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:45)
       at org.jboss.seam.intercept.ClientSideInterceptor$1.proceed(ClientSideInterceptor.java:74)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:57)
       at org.jboss.seam.interceptors.SecurityInterceptor.aroundInvoke(SecurityInterceptor.java:37)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.interceptors.RemoveInterceptor.aroundInvoke(RemoveInterceptor.java:40)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:103)
       at org.jboss.seam.intercept.ClientSideInterceptor.intercept(ClientSideInterceptor.java:52)
       at org.jboss.seam.intercept.Proxy$$EnhancerByCGLIB$$e48e6e3d.yesConfirmSave(<generated>)
       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 com.sun.el.parser.AstValue.invoke(AstValue.java:151)
       at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:283)
       at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
       at com.sun.facelets.el.LegacyMethodBinding.invoke(LegacyMethodBinding.java:69)
       ... 23 more
      Caused by: javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.ttsme.bb.entities.Bidder#<null>]
       at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:551)
       at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:210)
       at org.jboss.seam.persistence.EntityManagerProxy.merge(EntityManagerProxy.java:121)
       at com.ttsme.bb.actions.BidderBidManager.yesConfirmSave(BidderBidManager.java:102)
       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.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
       at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
       at org.jboss.seam.intercept.EJBInvocationContext.proceed(EJBInvocationContext.java:37)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:57)
       at org.jboss.seam.interceptors.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:47)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.interceptors.ManagedEntityIdentityInterceptor.aroundInvoke(ManagedEntityIdentityInterceptor.java:37)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.interceptors.ConversationInterceptor.aroundInvoke(ConversationInterceptor.java:54)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.interceptors.BusinessProcessInterceptor.aroundInvoke(BusinessProcessInterceptor.java:51)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.interceptors.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:27)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:69)
       at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:103)
       at org.jboss.seam.intercept.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:53)
       at sun.reflect.GeneratedMethodAccessor333.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:118)
       at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.entity.ExtendedPersistenceContextPropagationInterceptor.invoke(ExtendedPersistenceContextPropagationInterceptor.java:57)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
       ... 58 more
      Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.ttsme.bb.entities.Bidder#<null>]
       at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:240)
       at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:99)
       at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:51)
       at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:679)
       at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:663)
       at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:667)
       at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:201)
       ... 93 more
      


        • 2. Re: Help with StaleObjectStateException needed
          Elmo Novice

          Hi,

          I dont know if this will solve your problem but try calling the action when your page displays to force it, example:

           <page view-id="/restricted/createBid.xhtml" action="#{BidAction.addBidItem}">
          


          This action event occurs everytime you view the createBid.xhtml page. On another note, I noticed that you need to be careful especially handling the @DataModel. You may not have encountered it but I experience you need to re-initialize it so if you have updates on your list it will be refreshed. It seems it is caching data. I'm pretty new with JBoss Seam myself so I dont have a full understanding yet of the technology.

          Regards,

          Elmo

          • 3. Re: Help with StaleObjectStateException needed
            David Fedchenko Newbie

            I had almost exactly the same problem while trying to get a password changing UI working. It would work the first time and lose its optimism the second time.

            I finally noticed while comparing against your code that I had:

            entityManager.merge(currentUser);


            instead of:

            currentUser = entityManager.merge(currentUser);


            With that change it started working and I started backing out all the other things I had tried to get it back to the simplest version.

            I subsequently discovered that I needed:

            @In @Out(scope=SESSION)
            private User currentUser;


            to get the changes all the way back into the shared instance living in the session context. I did not previously know that @Out will not automatically outject back to the context @In injected from.