glassfish
  1. glassfish
  2. GLASSFISH-16784

Unable to complete container-managed transaction with app scoped resources

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1
    • Fix Version/s: 3.1.1_b10
    • Component/s: jdbc
    • Labels:
      None
    • Environment:

      MacOS

      Description

      The EJB container cannot complete a transaction after a method annotated with @Asynchronous was invoked. It claims that the JDBC managed connection is not valid:

      Caused by: javax.ejb.EJBException: Unable to complete container-managed transaction.
      at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5126)
      at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4880)
      at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2039)
      at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1990)
      at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
      at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
      at $Proxy168.getSamples(Unknown Source)
      at com.mycroftmind.samples.win.asynctest._EJB31_GeneratedAsyncTestBeanIntf__Bean_.getSamples(Unknown Source)
      at com.mycroftmind.samples.win.asynctest.frontend.AsyncTestFormBean.refresh(AsyncTestFormBean.java:39)
      at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:737)
      at javax.el.BeanELResolver.invoke(BeanELResolver.java:467)
      at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:254)
      at com.sun.el.parser.AstValue.invoke(AstValue.java:228)
      at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
      at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
      at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56)
      at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
      at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
      ... 33 more
      Caused by: javax.transaction.SystemException
      at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:520)
      at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:867)
      at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5115)
      ... 53 more
      Caused by: javax.transaction.xa.XAException: com.sun.appserv.connectors.internal.api.PoolingException: javax.resource.ResourceException: This Managed Connection is not valid as the physical connection is not usable
      at com.sun.enterprise.resource.ConnectorXAResource.handleResourceException(ConnectorXAResource.java:115)
      at com.sun.enterprise.resource.ConnectorXAResource.resetAssociation(ConnectorXAResource.java:287)
      at com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource.java:128)
      at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:503)
      ... 55 more

      The database used is Derby. The complete exception stack trace can be found among the attachments, as well as a sample web application illustrating this issue. The configuration of JDBC connection pool is among the attachments as well. However, the error does not occur at all times.

      The scenario description is the following (however, it may take some time to reproduce the issue):

      • the test application is deployed
      • in the web form of the test application:
        • click Run method button - the method executes asynchronously, it waits for one minute and then persists a sample JPA entity
        • click Get results button - in roughly 1 of 10 cases the exception is thrown; if the exception does not appear, wait for some time before clicking the Get results button.

      The exception is often thrown after some (not regular) time period. It seems that it is the most likely to happen when the first action after deployment is hitting the Run method button (i.e. not getting the results from database before calling the asynchronous method).

      In real application, when the user started some asynchronous process and after some time (e.g. 5 minutes) the user wants to retrieve the results from the database. It looks like a JDBC connection has timed-out. We have run into this only when using @Asynchronous methods with the default TransactionAttribute (REQUIRED which should behave as REQUIRES_NEW with asynchronous methods) settings.

      The EJB used in the test looks as follows:

      @Singleton
      @LocalBean
      public class AsyncTestBean {

      private static final long DELAY = 60000;

      @EJB
      private AsyncTestCRUDBean crudBean;

      @Asynchronous
      @Lock(LockType.READ)
      public Future<String> testMethod() {
      System.out.println("Asynchronous method started.");

      final SampleEntity sampleEntity = new SampleEntity();
      try {
      Thread.sleep(DELAY);
      } catch (InterruptedException ex) {
      ex.printStackTrace();
      }

      this.crudBean.persist(sampleEntity);

      System.out.println("Asynchronous method done.");
      return new AsyncResult<String>("test");
      }

      @Lock(LockType.READ)
      public List<SampleEntity> getSamples() {
      return this.crudBean.getSamples();
      }
      }

      Are there any limitations when using transactional access to JPA entities in @Asynchronous methods?

      1. exception_in_async_method.txt
        16 kB
        marek.winkler
      2. exception_with_REQUIRES_NEW.txt
        90 kB
        marek.winkler
      3. issue-full-log.txt
        49 kB
        marek.winkler
      4. issue-glassfish-resources.xml
        2 kB
        marek.winkler

        Activity

        Hide
        Shalini added a comment -

        This has nothing to do with setting the wrap-jdbc-objects=true. The only difference between using DerbyPool and async-test-pool is that async-test-pool is an app scoped resources pool.

        After a lot of investigation, it has been figured out that the GlassfishNamingManagerImpl.lookupFromNamespace method does not preseve the passed "env" for connector-runtime usage. The code snippet below

        if (o instanceof NamingObjectProxy)

        { NamingObjectProxy namingProxy = (NamingObjectProxy) o; o = namingProxy.create(initialContext); }

        omits the passed env argument.

        Setting the max-pool-size/steady-pool-size to 1, wrap-jdbc-objects to true/false, idle-timeout to 30 seconds, when the app (using app scoped resources) is deployed, some of the steps to observe are when ConnectorRuntime.lookupPMResource is done, the resourceInfo passed is java:app/async-test/jdbc/async-test__pm, the ConnectorObjectFactory tries to derive a jndi name based on the "env".

        The "env" is erroneous in case of app scoped resources and that is the reason why using jdbc/__default as the jdbc resource was passing.

        Transferring the issue to Jagadish.

        Show
        Shalini added a comment - This has nothing to do with setting the wrap-jdbc-objects=true. The only difference between using DerbyPool and async-test-pool is that async-test-pool is an app scoped resources pool. After a lot of investigation, it has been figured out that the GlassfishNamingManagerImpl.lookupFromNamespace method does not preseve the passed "env" for connector-runtime usage. The code snippet below if (o instanceof NamingObjectProxy) { NamingObjectProxy namingProxy = (NamingObjectProxy) o; o = namingProxy.create(initialContext); } omits the passed env argument. Setting the max-pool-size/steady-pool-size to 1, wrap-jdbc-objects to true/false, idle-timeout to 30 seconds, when the app (using app scoped resources) is deployed, some of the steps to observe are when ConnectorRuntime.lookupPMResource is done, the resourceInfo passed is java:app/async-test/jdbc/async-test__pm, the ConnectorObjectFactory tries to derive a jndi name based on the "env". The "env" is erroneous in case of app scoped resources and that is the reason why using jdbc/__default as the jdbc resource was passing. Transferring the issue to Jagadish.
        Hide
        Shalini added a comment -

        Changing the summary to reflect that the issue is with app scoped resources.

        Show
        Shalini added a comment - Changing the summary to reflect that the issue is with app scoped resources.
        Hide
        Jagadish added a comment -

        Fix is to make sure Environment is preserved for lookup via namespaces (app/module) also which will provide similar behavior as that of lookup via "(new InitialContext(environment)).lookup()"

        Fix reviewed by Cheng.

        Show
        Jagadish added a comment - Fix is to make sure Environment is preserved for lookup via namespaces (app/module) also which will provide similar behavior as that of lookup via "(new InitialContext(environment)).lookup()" Fix reviewed by Cheng.
        Hide
        scatari added a comment -

        Approved for 3.1.1. The checkin for this fix will miss b09, so target it for b10.

        Show
        scatari added a comment - Approved for 3.1.1. The checkin for this fix will miss b09, so target it for b10.
        Hide
        Jagadish added a comment -

        FIX INFORMATION :

        svn log -v -r 47642
        branches/3.1.1/common/glassfish-naming/src/main/java/com/sun/enterprise/naming/impl/GlassfishNamingManagerImpl.java

        svn log -v -r 47639
        trunk/v3/common/glassfish-naming/src/main/java/com/sun/enterprise/naming/impl/GlassfishNamingManagerImpl.java

        Show
        Jagadish added a comment - FIX INFORMATION : svn log -v -r 47642 branches/3.1.1/common/glassfish-naming/src/main/java/com/sun/enterprise/naming/impl/GlassfishNamingManagerImpl.java svn log -v -r 47639 trunk/v3/common/glassfish-naming/src/main/java/com/sun/enterprise/naming/impl/GlassfishNamingManagerImpl.java

          People

          • Assignee:
            Jagadish
            Reporter:
            marek.winkler
          • Votes:
            3 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: