8 Replies Latest reply on Feb 8, 2003 9:54 AM by hvoss

    transaction deadlock with multiple clients

      I am using JBoss 3.0.4 together with DB2 as the backend. I have the standard session facade pattern in which the web client talks only to session bean methods and the session bean methods call on the entity beans to do the work.

      All methods of the session beans are tagged:

      <trans-attribute>RequiresNew</trans-attribute>

      and all methods of each of the entity beans is tagged:

      <trans-attribute>Required</trans-attribute>

      A while ago, I opened a sourceforge bug report on this topic and Scott Stark closed it as being invalid. I can believe this problem is my own doing, but how do I fix it and what do I change?

      I never see this problem with a single client but when we run Apache JMeter and start banging away at the server with multiple clients, we notice many of these deadlock exceptions come up. We are only doing reads and not updates to the data.

      Can any kind person who has encountered this problem and fixed it, please point me in the right direction?

      Many thanks,
      Joe


        • 1. Re: transaction deadlock with multiple clients

          The exception is :

          javax.transaction.TransactionRolledbackException: Application deadlock detected: Two or more transactions contention.; CausedByException is: Application deadlock detected: Two or more transactions contention.; nested exception is: org.jboss.ejb.plugins.lock.ApplicationDeadlockException: Application deadlock detected: Two or more transactions contention.

          • 2. Re: transaction deadlock with multiple clients

            Below is the stack trace from the deadlock exception we encounter ...

            javax.transaction.TransactionRolledbackException: Application deadlock detected: Two or more transactions contention.; CausedByException is:
            Application deadlock detected: Two or more transactions contention.; nested exception is:
            org.jboss.ejb.plugins.lock.ApplicationDeadlockException: Application deadlock detected: Two or more transactions contention.
            at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:271)
            at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:208)
            at org.jboss.ejb.StatelessSessionContainer.invoke(StatelessSessionContainer.java:313)
            at org.jboss.ejb.Container.invoke(Container.java:712)
            at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:517)
            at org.jboss.invocation.local.LocalInvoker.invoke(LocalInvoker.java:98)
            at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:102)
            at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:77)
            at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:80)
            at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:111)
            at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:76)
            at $Proxy108.getAttendeeSchedule(Unknown Source)
            at com.mycompany.client.transaction.MyScheduleMain.run(MyScheduleMain.java:48)
            at com.mycompany.client.control.VelocityTransMgr.handleRequest(VelocityTransMgr.java:108)
            at org.apache.velocity.servlet.VelocityServlet.doRequest(VelocityServlet.java:372)
            at org.apache.velocity.servlet.VelocityServlet.doGet(VelocityServlet.java:333)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:260)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:527)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
            at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
            at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2396)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
            at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:170)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:469)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
            at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
            at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcessor.java:1040)
            at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor.java:1151)
            at java.lang.Thread.run(Thread.java:536)

            • 3. Re: transaction deadlock with multiple clients

              Since this works for a single client, you have
              an ordering problem.

              One request locks A then tries to lock B
              The other locks B then tries to lock A

              A deadlock.

              Possible solutions:
              1) Arrange your code so entities are locked in
              a specific order - may not be possible with
              complicated applications.
              2) You can specify read-only on certain methods
              to avoid locking where applicable.
              3) Monitor for ApplicationDeadLockException and
              retry - a recent change added in 3.2 will do this for
              you when the bean starting the transaction spots
              the rollback due to a deadlock.

              Regards,
              Adrian

              • 4. Re: transaction deadlock with multiple clients

                Adrian,

                Thanks for your reply.

                I would like to do option (2). In fact I don't want to wrap any of my read methods with a transaction. They don't need one. But How do I do this?

                I tried "Never" on session methods and "Never" on entity methods and that yielded an illegal state exception saying that I was referencing an entity and a collection but not in the same transaction. Huh? I don't get it.

                I also tried "NotSupported" on both session bean methods and "Entity" bean methods. Same exception.

                Finally I tried "Supports" on both and got same exception.

                How do I turn off transaction support for my finders and getter methods that are only doing reads?

                Thanks again for your help and support. I know what I want to do, just don't know HOW to do it.

                I am using JBoss 3.0.4 with JVM 1.4.1_01 (latest) and DB2.

                regards,
                joe

                • 5. Re: transaction deadlock with multiple clients

                  I also tried trans-attribute Never for all methods of my Entity and Sessions beans, thinking that this would keep any bean methods from using transactions. But JBoss seems to complain that I can't use a CMR collection in a transaction other than the one it was obtained in. Is JBoss starting transaction for me even if I use "Never" as trans-attribute?

                  Why do I get a "A CMR collection may only be used within the transction in which it was created" illegal state exception when I don't think I am even in a transaction and ALL I am doing is read-only methods? Very puzzled!


                  Thanks,
                  joe








                  Regards,
                  joe

                  • 6. Re: transaction deadlock with multiple clients

                    Hi Joe,

                    CMR collections require transactions, it is in the spec.

                    You can make the whole bean read-only


                    <enterprise-beans>

                    <ejb-name>MyEntity</ejb-name>
                    <read-only>True</read-only>

                    </enterprise-beans>


                    If you want to do read-only methods, do something like
                    this:


                    <enterprise-beans>

                    <ejb-name>MyEntity</ejb-name>
                    <method-attributes>

                    <method-name>get*</method-name>
                    <read-only>true</read-only>


                    </enterprise-beans>


                    If you use a non read-only method, the lock will be promoted to a full lock.

                    You might also want to investigate:


                    <enterprise-beans>

                    <ejb-name>MyEntity</ejb-name>
                    <configuration-name>Instance Per Transaction CMP 2.x EntityBean</configuration-name>

                    </enterprise-beans>


                    This creates two instances of the bean with
                    no locking.

                    To answer your puzzled point.
                    Even without a transaction, the default locking
                    policy creates a "notional transaction" to stop
                    concurrent access to an entity.

                    Regards,
                    Adrian

                    • 7. Re: transaction deadlock with multiple clients

                      Adrian,

                      Many thanks!!

                      I will investigate making my bean methods R/O and per instance attribute and see what kind of results I get.

                      Regards,
                      Joe

                      • 8. Re: transaction deadlock with multiple clients
                        hvoss

                        The <method-*> tags are only valid when checking jboss.xml against the jboss_3_1.dtd Document Type Def included e.g. in the JBoss-3.2RC1 distribution.

                        Does it nontheless take any effect in JBoss-3.0.x to specify these tags?