Issue Details (XML | Word | Printable)

Key: GLASSFISH-19050
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: marina vatkina
Reporter: rgirsten
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
glassfish

Glassfish swallows RuntimeException thrown in SynchronizationListener.beforeCompletion

Created: 04/Sep/12 01:48 PM   Updated: 07/Sep/12 10:08 PM   Resolved: 07/Sep/12 10:08 PM
Component/s: jts
Affects Version/s: 3.1.2, 4.0_b53
Fix Version/s: 4.0_b54

Time Tracking:
Not Specified

File Attachments: 1. GZip Archive demo-proxy-auth-generic.tar.gz (25 kB) 04/Sep/12 01:48 PM - rgirsten

Environment:

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


Tags:
Participants: marina vatkina and rgirsten


 Description  « Hide

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.



marina vatkina added a comment - 05/Sep/12 12:33 AM

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.


rgirsten added a comment - 05/Sep/12 09:13 AM

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.


marina vatkina added a comment - 07/Sep/12 04:59 AM - edited

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


marina vatkina added a comment - 07/Sep/12 05:04 AM

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


rgirsten added a comment - 07/Sep/12 09:31 AM

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.


marina vatkina added a comment - 07/Sep/12 09:40 PM

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


marina vatkina added a comment - 07/Sep/12 09:48 PM

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


marina vatkina added a comment - 07/Sep/12 09:52 PM

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


marina vatkina added a comment - 07/Sep/12 10:08 PM

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;