7 Replies Latest reply on Nov 4, 2005 2:38 PM by starksm64

    setRollbackOnly problem

    eldavio

      I have a SLSB running within a container managed transaction.
      When I call the sessioncontext setRollbackOnly() I can no longer
      access any CMP entity beans within my method.

      Now am I correct in assuming setRollbackOnly() should indicate to
      the container to perform a rollback at the end of the method invocation
      and not at the time I call setRollbackOnly ?

      Offending Code:

       if(! conflictingBookings.isEmpty()) // the new booking will conflict with an existing booking for another group
       {
       sessionContext.setRollbackOnly();
      
       BookingLocal conflictingBooking = (BookingLocal)conflictingBookings.iterator().next();
      
      
       ConflictingBookingException cbe =
       new ConflictingBookingException("Cannot create booking because a conflicting booking already exists");
      
       cbe.setAccountId(accountId);
       cbe.setChildId(childId);
       cbe.setGroupId(groupId);
       cbe.setTimeIn(timeIn);
       cbe.setTimeOut(timeOut);
       cbe.setConflictingBookingId(conflictingBooking.getBookingId());
      
       throw cbe;
       }
      



      Exception
      java.lang.RuntimeException: Transaction marked for rollback, possibly a timeout
       at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.doSchedule(QueuedPessimisticEJBLock.java:228)
       at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.schedule(QueuedPessimisticEJBLock.java:183)
       at org.jboss.ejb.plugins.EntityLockInterceptor.invoke(EntityLockInterceptor.java:85)
       at org.jboss.ejb.plugins.EntityCreationInterceptor.invoke(EntityCreationInterceptor.java:53)
       at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
       at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:105)
       at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:363)
       at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:166)
       at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:139)
       at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
       at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
       at org.jboss.ejb.EntityContainer.internalInvoke(EntityContainer.java:514)
       at org.jboss.ejb.Container.invoke(Container.java:873)
       at org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invoke(BaseLocalProxyFactory.java:413)
       at org.jboss.ejb.plugins.local.EntityProxy.invoke(EntityProxy.java:50)
       at $Proxy269.getBookingId(Unknown Source)
       at net.economicoutlook.spike.services.booking.ejb.BookingManagerEJB.createAttendance(BookingManagerEJB.java:777)
       at sun.reflect.GeneratedMethodAccessor413.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at org.jboss.invocation.Invocation.performCall(Invocation.java:345)
       at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:214)
       at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
       at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:130)
       at org.jboss.webservice.server.ServiceEndpointInterceptor.invoke(ServiceEndpointInterceptor.java:51)
       at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
       at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:105)
       at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:335)
       at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:166)
       at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:139)
       at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
       at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
       at org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:624)
       at org.jboss.ejb.Container.invoke(Container.java:873)
       at org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invoke(BaseLocalProxyFactory.java:413)
       at org.jboss.ejb.plugins.local.StatelessSessionProxy.invoke(StatelessSessionProxy.java:88)
       at $Proxy285.createAttendance(Unknown Source)
       at net.economicoutlook.spike.facades.itol.ejb.ItolEJB.createAttendance(ItolEJB.java:813)
       at sun.reflect.GeneratedMethodAccessor411.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at org.jboss.invocation.Invocation.performCall(Invocation.java:345)
       at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:214)
       at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
       at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:130)
       at org.jboss.webservice.server.ServiceEndpointInterceptor.invoke(ServiceEndpointInterceptor.java:106)
       at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
       at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:105)
       at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:335)
       at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:166)
       at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:139)
       at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
       at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
       at org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:624)
       at org.jboss.ejb.Container.invoke(Container.java:873)
       at sun.reflect.GeneratedMethodAccessor407.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:141)
       at org.jboss.mx.server.Invocation.dispatch(Invocation.java:80)
       at org.jboss.mx.server.Invocation.invoke(Invocation.java:72)
       at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:249)
       at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:644)
       at org.jboss.webservice.server.InvokerProviderEJB.invokeServiceEndpoint(InvokerProviderEJB.java:131)
       at org.jboss.webservice.server.InvokerProvider.invokeMethod(InvokerProvider.java:238)
       at org.jboss.axis.providers.java.RPCProvider.invokeTarget(RPCProvider.java:176)
       at org.jboss.axis.providers.java.RPCProvider.processMessage(RPCProvider.java:121)
       at org.jboss.axis.providers.java.JavaProvider.invoke(JavaProvider.java:358)
       at org.jboss.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:73)
       at org.jboss.axis.SimpleChain.doVisiting(SimpleChain.java:160)
       at org.jboss.axis.SimpleChain.invoke(SimpleChain.java:123)
       at org.jboss.axis.handlers.soap.SOAPService.invoke(SOAPService.java:560)
       at org.jboss.webservice.server.ServerEngine.invokeInternal(ServerEngine.java:200)
       at org.jboss.webservice.server.ServerEngine.invoke(ServerEngine.java:89)
       at org.jboss.axis.transport.http.AxisServlet.doPost(AxisServlet.java:905)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
       at org.jboss.axis.transport.http.AxisServletBase.service(AxisServletBase.java:370)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       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.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:153)
       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
       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.Http11Processor.process(Http11Processor.java:856)
       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
       at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
       at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
       at java.lang.Thread.run(Thread.java:595)
      


      This seems to be triggered by this line
      cbe.setConflictingBookingId(conflictingBooking.getBookingId());
      


      Which is trying to access the entitly bean 'conflictingBooking.getBookingId()' accessor method.

      This has been raised once before
      http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3857249
      With a work around that should not be neccessary.

      Any help with this would be greatly appreciated.

        • 1. Re: setRollbackOnly problem
          eldavio

          Just wondering, if any of the JBoss team are monitoring, should I add this into JIRA
          to escalate the problem ?

          Cheers

          • 2. Re: setRollbackOnly problem
            starksm64

            The ejb spec does not indicate whether or not any additional work can be performed in the essentially invalidate transaction, but its somehwat implied that once setRollbackOnly is called the business method work should be completed:


            17.3.4.2 javax.ejb.EJBContext.setRollbackOnly Method
            An enterprise bean with container-managed transaction demarcation can use the setRollbackOnly
            method of its EJBContext object to mark the transaction such that the transaction can never commit.
            Typically, an enterprise bean marks a transaction for rollback to protect data integrity before throwing
            an application exception, because application exceptions do not automatically cause the container to
            rollback the transaction.


            Why isn't the rollback done after accessing bean?



            • 3. Re: setRollbackOnly problem
              eldavio

              Hi Scott thanks for the reply.

              Your right in my described example I could perform setRollbackonly()
              after I access the entity bean to get around the issue.

              But this is not the only place I may want to access business functions.
              I actually catch this exception further up stream, to throw a new
              application exception.

              Each public api set the middleware exposes has its own exceptions and
              transfer objects independant of my service layer.

              It is imperative I dont expose any service or domain level objects to my
              client applications, for api stability / deprecation management etc...

              As such I would need to perform additional business operations after the
              original exception is thrown to better describe the exception with context
              to the client app.

              I suppose I could stop calling setRollbackOnly in my Service layer and call it
              when I catch the Exception upstream. But this would just be a workaround,
              it really should be marked for rollback by the business rules.

              I hope this better describes my situation.

              • 4. Re: setRollbackOnly problem

                You cannot access any transactional resource once the transaction
                is marked for rollback. This includes entity beans, datasources
                or anything that wants to do things with the transaction state.

                • 5. Re: setRollbackOnly problem

                   

                  "eldavio" wrote:
                  Just wondering, if any of the JBoss team are monitoring, should I add this into JIRA
                  to escalate the problem ?

                  Cheers


                  http://wiki.jboss.org/wiki/Wiki.jsp?page=JBossHelp
                  No you should read the spec, even if it is buried in the referenced JTA/OTS specs.

                  • 6. Re: setRollbackOnly problem
                    eldavio

                    Hi Adrian

                    Your right I didnt look at the spec as stated.
                    But I did read up on transaction usage in general.

                    Most of the tutorials stated rollback would be deferred
                    until the completion of the method that started the transaction.
                    As the function name 'setRollbackOnly' I initially thought
                    implied.

                    These were obviously not JBoss specific resources
                    but from Sun and IBM which I know doesnt neccessarily
                    mean they apply to JBoss.

                    I'm not saying the JBoss container is behaving incorrectly
                    since the spec states it isnt.

                    I just thought it made sense for the container to defer its
                    rollback to the end of the method invocation. Especially
                    in my situation where it means I can mark the transaction
                    for rollback deep within my business rules, rather than
                    by the service endpoint.

                    Just a thought but this behaviour may help other developers
                    with the task of migrating from other containers that do
                    implement this.

                    • 7. Re: setRollbackOnly problem
                      starksm64

                      Just delaying the rollback to the end of a method seems of little use in the general case of an arbitrarly deep stack. I would also argue that propagation of the ejb context and its setRollbackOnly method to the business layer is an improper propagation of a concern (transactions) that should only be dealt with at the ejb facade layer.

                      In general, these "lack of portability" issues should be raised to the corresponding j2ee spec mailing list as feedback to the effectiveness of the specs definition of semantics.