glassfish
  1. glassfish
  2. GLASSFISH-19050

Glassfish swallows RuntimeException thrown in SynchronizationListener.beforeCompletion

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.2, 4.0_b53
    • Fix Version/s: 4.0_b54
    • Component/s: jts
    • Labels:
      None
    • Environment:

      Glassfish 3.1.2.2, EclipseLink 2.3.2, Oracle Database Server 10.x or 11.x

      Description

      I have created an example that demonstrates how to use the EclipseLink feature for
      Oracle Database Server Proxy Authentication.
      This feature uses database authentication and authorization to secure an application.

      On Glassfish the original RuntimeException thrown in an EclipseLink exception handler is not piggybacked with the EJBException that the web client does receive from the failed session bean method call.

      [#|2012-09-04T15:08:37.237+0200|WARNING|oracle-glassfish3.1.2|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=39;_ThreadName=Thread-2;|javax.ejb.EJBException: Transaction aborted
      at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5142)
      at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4901)
      at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
      at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
      at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
      at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
      at $Proxy138.incrementAndReadValue(Unknown Source)
      at oracle.support.web.BackingBean.incrementAndReadValue(BackingBean.java:46)
      at org.apache.jsp.WEB_002dINF.jsp.write_jsp._jspService(write_jsp.java:97)
      at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
      at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411)
      at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)
      at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
      at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
      at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:809)
      at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:671)
      at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:505)
      at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:476)
      at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:355)
      at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:305)
      at oracle.support.web.ControllerServlet.doPost(ControllerServlet.java:83)
      at oracle.support.web.ControllerServlet.doGet(ControllerServlet.java:38)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
      at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
      at oracle.support.web.AuthenticationFilter.doFilter(AuthenticationFilter.java:61)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
      at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
      at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
      at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
      at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
      at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
      at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
      at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
      at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
      at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
      at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
      at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
      at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
      at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
      at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
      at java.lang.Thread.run(Thread.java:722)
      Caused by: javax.transaction.RollbackException
      at com.sun.jts.jta.TransactionManagerImpl.commit(TransactionManagerImpl.java:334)
      at com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.commitDistributedTransaction(JavaEETransactionManagerJTSDelegate.java:185)
      at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:861)
      at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5136)
      ... 54 more

      The README file of the example explains how to setup the example.
      The problem can be reproduced by logging in as user "proxyuser" and password "test" and then clicking on "write".
      The user "proxyuser" does not have privileges to write and therefore the JDBC driver will raise an exception that indicates that the privileges are not sufficient.

      On WebLogic Server the example does display the correct error message of the root cause exception on the error page.

        Activity

        Hide
        marina vatkina added a comment -

        Fixed on trunk with rev 55854.

        To make the same change in 3.1.2x line 333 in src/main/java/com/sun/jts/jta/TransactionManagerImpl.java should be changed as follows:

        • throw new RollbackException();
          + RollbackException rbe = new RollbackException();
          + Throwable cause = ex.getCause();
          + if (cause != null) { + rbe.initCause(cause); + }

          + throw rbe;

        Show
        marina vatkina added a comment - Fixed on trunk with rev 55854. To make the same change in 3.1.2x line 333 in src/main/java/com/sun/jts/jta/TransactionManagerImpl.java should be changed as follows: throw new RollbackException(); + RollbackException rbe = new RollbackException(); + Throwable cause = ex.getCause(); + if (cause != null) { + rbe.initCause(cause); + } + throw rbe;
        Hide
        marina vatkina added a comment -

        Transaction.commit was fixed by http://java.net/jira/browse/GLASSFISH-11970

        Show
        marina vatkina added a comment - Transaction.commit was fixed by http://java.net/jira/browse/GLASSFISH-11970
        Hide
        marina vatkina added a comment -

        Interestingly enough the unit test calls tx.commit() and that path attaches the cause. TM.commit() doesn't

        Show
        marina vatkina added a comment - Interestingly enough the unit test calls tx.commit() and that path attaches the cause. TM.commit() doesn't
        Hide
        marina vatkina added a comment -

        I can reproduce it with 2 XA resources, but it's not clear yet why junit test doesn't catch it

        Show
        marina vatkina added a comment - I can reproduce it with 2 XA resources, but it's not clear yet why junit test doesn't catch it
        Hide
        rgirsten added a comment -

        I have tried to simplify my example but I was not able to.
        My example uses an XA data source for the transaction that throws the RuntimeException in the eclipselink exception handler when it detects the
        SQLSyntaxErrorException: ORA-01031: insufficient privileges
        My RuntimeException does not piggyback the SQLSyntaxErrorException. But this is not the problem.
        The problem is that the RollbackException does not piggyback the root cause exception which is the RuntimeException.
        If I remove the eclipselink exception handler by putting the persistence.xml property in comments then I have the problem that the SQLSyntaxErrorException is not piggybacked by the RollbackException.
        There is very little Glassfish specific that eclipselink is doing.
        The SunAS/Glassfish support classes do provide Glassfish specific methods to lookup the TransactionManager and to unwrap JDBC connections.

        Show
        rgirsten added a comment - I have tried to simplify my example but I was not able to. My example uses an XA data source for the transaction that throws the RuntimeException in the eclipselink exception handler when it detects the SQLSyntaxErrorException: ORA-01031: insufficient privileges My RuntimeException does not piggyback the SQLSyntaxErrorException. But this is not the problem. The problem is that the RollbackException does not piggyback the root cause exception which is the RuntimeException. If I remove the eclipselink exception handler by putting the persistence.xml property in comments then I have the problem that the SQLSyntaxErrorException is not piggybacked by the RollbackException. There is very little Glassfish specific that eclipselink is doing. The SunAS/Glassfish support classes do provide Glassfish specific methods to lookup the TransactionManager and to unwrap JDBC connections.
        Hide
        marina vatkina added a comment -

        I have even a junit test case that verifies that an exception from beforeCompletion is attached to the RollbackException...

        Show
        marina vatkina added a comment - I have even a junit test case that verifies that an exception from beforeCompletion is attached to the RollbackException...
        Hide
        marina vatkina added a comment - - edited

        Can you attach a simple test case? Are you using XA or non-XA resources?

        Show
        marina vatkina added a comment - - edited Can you attach a simple test case? Are you using XA or non-XA resources?
        Hide
        rgirsten added a comment -

        The web client error page walks down the exception chain and prints the root exception error message.
        The client gets EJBException with RollbackException. The root cause exception is missing.
        I have tried to setup a simpler example which is simply violating a primary key constraint (unique key violation) in a transaction. But in this case the client will receive the complete chain of exceptions including the root cause.
        So, somewhat the behavior of Glassfish seems to be inconsistent.
        But without having the complete exception chain available, the client cannot handle or report an application exception.
        It is pretty normal for persistence frameworks to plug into JTS by using a SynchronizationListener with the beforeCompletion and afterCompletion method. Also it is normal that such persistence framework does call setRollbackOnly if the processing of the beforeCompletion and afterCompletion actions was throwing an exception.

        Show
        rgirsten added a comment - The web client error page walks down the exception chain and prints the root exception error message. The client gets EJBException with RollbackException. The root cause exception is missing. I have tried to setup a simpler example which is simply violating a primary key constraint (unique key violation) in a transaction. But in this case the client will receive the complete chain of exceptions including the root cause. So, somewhat the behavior of Glassfish seems to be inconsistent. But without having the complete exception chain available, the client cannot handle or report an application exception. It is pretty normal for persistence frameworks to plug into JTS by using a SynchronizationListener with the beforeCompletion and afterCompletion method. Also it is normal that such persistence framework does call setRollbackOnly if the processing of the beforeCompletion and afterCompletion actions was throwing an exception.
        Hide
        marina vatkina added a comment -

        Can you try the scroll through the causes? I think we fixed it in the transaction code, but the EJB container only reports the actual transaction failure (javax.transaction.RollbackException), which is fine.

        Show
        marina vatkina added a comment - Can you try the scroll through the causes? I think we fixed it in the transaction code, but the EJB container only reports the actual transaction failure (javax.transaction.RollbackException), which is fine.

          People

          • Assignee:
            marina vatkina
            Reporter:
            rgirsten
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: