UndeclaredThrowableException from Container Invoked Callback
cm Sep 7, 2001 9:54 PMI've looked at previous posts dealing with the UndeclaredThrowableException and found one post that seemed similiar to my situation with no response and a few other posts that dealt with an earlier version of JBoss. I am using JBoss 2.2.1 and I've noticed that if an EJBException is thrown from the ejbStore of a bean managed entity bean, then the client receives a java.lang.reflect.UndeclaredThrowableException instead of a RemoteException. It seems like the EJB Spec specifies that a RemoteException should be received by the client.
In order to define an exception handling scheme for my EJB components and understand how exceptions work with EJBs I tried the following:
A client test program calls a session bean named PartyManager that updates a bean managed entity bean named Party. Within the ejbStore method of the Party entity bean, a SQLException is thrown (because the SQL statement's syntax is incorrect). The SQLException is caught and then an EJBException is thrown. The ejbStore method looks as follows:
public void ejbStore()
{
// Create our database objects
Connection conn = null;
PreparedStatement ps = null;
try
{
// Create an UPDATE prepared statement
conn = DbUtils.getConnection();
ps = conn.prepareStatement( SQL_UPDATE_QUERY );
ps.setString( 1, this.guid );
ps.setString( 2, this.name );
// Execute the Update
if( ps.executeUpdate() != 1 )
{
throw new EJBException( "ejbStore failed updating party with primary key: " + this.id.longValue() );
}
}
catch( SQLException eSQL )
{
EJBException e = new EJBException( eSQL );
throw e;
}
finally
{
try
{
// Clean up our database objects
if( ps != null ) ps.close();
if( conn != null ) conn.close();
}
catch( SQLException eSQL )
{
eSQL.printStackTrace();
}
}
}
The server.log contains the following stacktrace:
[PartyManagerBean] java.sql.SQLException: ORA-00900: invalid SQL statement
[PartyManagerBean] at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:114)
[PartyManagerBean] at oracle.jdbc.oci8.OCIDBAccess.check_error(OCIDBAccess.java:1503)
[PartyManagerBean] at oracle.jdbc.oci8.OCIDBAccess.executeFetch(OCIDBAccess.java:1111)
[PartyManagerBean] at oracle.jdbc.oci8.OCIDBAccess.parseExecuteFetch(OCIDBAccess.java:1235)
[PartyManagerBean] at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:1313)
[PartyManagerBean] at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1232)
[PartyManagerBean] at oracle.jdbc.driver.OracleStatement.doExecuteWithBatch(OracleStatement.java:1353)
[PartyManagerBean] at oracle.jdbc.driver.OracleStatement.doExecute(OracleStatement.java:1760)
[PartyManagerBean] at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1805)
[PartyManagerBean] at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:322)
[PartyManagerBean] at org.opentools.minerva.jdbc.PreparedStatementInPool.executeUpdate(PreparedStatementInPool.java:82)
[PartyManagerBean] at com.ipnetsolutions.config.srv.party.PartyBean.ejbStore(PartyBean.java:1552)
[PartyManagerBean] at java.lang.reflect.Method.invoke(Native Method)
[PartyManagerBean] at org.jboss.ejb.plugins.BMPPersistenceManager.storeEntity(BMPPersistenceManager.java:331)
[PartyManagerBean] at org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization.beforeCompletion(EntitySynchronizationInterceptor.java:342)
[PartyManagerBean] at org.jboss.tm.TxCapsule.doBeforeCompletion(TxCapsule.java:1228)
[PartyManagerBean] at org.jboss.tm.TxCapsule.commit(TxCapsule.java:322)
[PartyManagerBean] at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:76)
[PartyManagerBean] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:318)
[PartyManagerBean] at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:99)
[PartyManagerBean] at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:190)
[PartyManagerBean] at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
[PartyManagerBean] at org.jboss.ejb.StatelessSessionContainer.invoke(StatelessSessionContainer.java:271)
[PartyManagerBean] at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invoke(JRMPContainerInvoker.java:392)
[PartyManagerBean] at java.lang.reflect.Method.invoke(Native Method)
[PartyManagerBean] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:241)
[PartyManagerBean] at sun.rmi.transport.Transport$1.run(Transport.java:142)
[PartyManagerBean] at java.security.AccessController.doPrivileged(Native Method)
[PartyManagerBean] at sun.rmi.transport.Transport.serviceCall(Transport.java:139)
[PartyManagerBean] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:443)
[PartyManagerBean] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:643)
[PartyManagerBean] at java.lang.Thread.run(Thread.java:484)
[PartyManagerBean] javax.ejb.EJBException
[PartyManagerBean] at com.ipnetsolutions.config.srv.party.PartyBean.ejbStore(PartyBean.java:1566)
[PartyManagerBean] at java.lang.reflect.Method.invoke(Native Method)
[PartyManagerBean] at org.jboss.ejb.plugins.BMPPersistenceManager.storeEntity(BMPPersistenceManager.java:331)
[PartyManagerBean] at org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization.beforeCompletion(EntitySynchronizationInterceptor.java:342)
[PartyManagerBean] at org.jboss.tm.TxCapsule.doBeforeCompletion(TxCapsule.java:1228)
[PartyManagerBean] at org.jboss.tm.TxCapsule.commit(TxCapsule.java:322)
[PartyManagerBean] at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:76)
[PartyManagerBean] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:318)
[PartyManagerBean] at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:99)
[PartyManagerBean] at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:190)
[PartyManagerBean] at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
[PartyManagerBean] at org.jboss.ejb.StatelessSessionContainer.invoke(StatelessSessionContainer.java:271)
[PartyManagerBean] at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invoke(JRMPContainerInvoker.java:392)
[PartyManagerBean] at java.lang.reflect.Method.invoke(Native Method)
[PartyManagerBean] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:241)
[PartyManagerBean] at sun.rmi.transport.Transport$1.run(Transport.java:142)
[PartyManagerBean] at java.security.AccessController.doPrivileged(Native Method)
[PartyManagerBean] at sun.rmi.transport.Transport.serviceCall(Transport.java:139)
[PartyManagerBean] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:443)
[PartyManagerBean] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:643)
[PartyManagerBean] at java.lang.Thread.run(Thread.java:484)
When the client gets the exception, the client gets a java.lang.reflect.UndeclaredThrowableException instead of a RemoteException. I think the client is getting the UndeclaredThrowableException, because the container is throwing a javax.transaction.RollbackException (which extends from Exception) as opposed to the javax.transaction.TransactionRollbackException (which extends from java.rmi.RemoteException). The client's stacktrace is as follows:
java.lang.reflect.UndeclaredThrowableException: javax.transaction.RollbackException: Unable to commit, tx=XidImpl [FormatId=257, GlobalId=shaines2//3, BranchQual=] status=STATUS_ROLLEDBACK
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:245)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:220)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:122)
at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker_Stub.invoke(Unknown Source)
at org.jboss.ejb.plugins.jrmp.interfaces.StatelessSessionProxy.invoke(StatelessSessionProxy.java:188)
at $Proxy1.update(Unknown Source)
at com.ipnetsolutions.config.itf.EJBConfigurator.updateParty(EJBConfigurator.java:2531)
at TestClient.testEJBException(TestClient.java:1517)
at TestClient.main(TestClient.java:96)
If I try a different experiment and cause an EJBException within a stateless session bean, then the client DOES receive a RemoteException. Should a RemoteException be received by the client when an EJBException is thrown from a container invoked callback? Is there a problem with JBoss?
Thanks in advance for any help.