We experience an issue when saving a Form into Oracle database via JPA2DataSource and some database constraint is violated
(see stack trace below, we deliberately disabled required setting for the field to reproduce the issue). In this case a
transaction is rolled back, but we get no appropriate status code or errors in the DSResponse object on the client.
We have debugged the code a bit (we created a wrapper around the JPA2DataSource and used a decompiler) and it seems that there is a bug in the RPCManager.completeResponse() and RPCManager.onFailure(DataSource).
- the RPCManager.onSuccess() is called, which in turn goes through all data sources and calls onSuccess(RPCManager) method, this calls EMF.commitTransaction method in turn
- when an exception happens during the commit, the JPADataSource.onSuccess(boolean) method is called.
- if there is an exception in that method (thrown in EMF.commitTransaction) the corresponding data source is added to the list of partially committed data sources and onFailure(DataSource) method is called, which in turn calls JPADataSource.onFailure(RPCManager, boolean) method (this calls EMF.rollbackTransaction in turn).
- the RPCManager.onSuccess method throws PartialCommitException, which in turn sets a boolean flag partialCommit = true.
- and that's it (at least what I see in the decompiled code) - the flag is not used in your code anywhere, the corresponding DSResponse.status = 0, the DSResponse.errors remains null.
We have no possibility to react on this error on the client side.
So the question is whether this is bug in SmartGWT or we have missed something in the documentation.
--------------------------------------------------------------------------------------
Additional information about the issue:
1. SmartGWT: SmartClient Version: v9.0p_2013-10-30/Pro Deployment (built 2013-10-30)
2. Firefox, but it does not matter
3. Two classes BgxIDACall and BgxJPADataSource are simple classes that extend corresponding Isomorphic classes and delegate all calls to the overridden methods (convenience to put breakpoints on the methods of classes that do not have source code).
4. Server exception (and some logs)
(see stack trace below, we deliberately disabled required setting for the field to reproduce the issue). In this case a
transaction is rolled back, but we get no appropriate status code or errors in the DSResponse object on the client.
We have debugged the code a bit (we created a wrapper around the JPA2DataSource and used a decompiler) and it seems that there is a bug in the RPCManager.completeResponse() and RPCManager.onFailure(DataSource).
- the RPCManager.onSuccess() is called, which in turn goes through all data sources and calls onSuccess(RPCManager) method, this calls EMF.commitTransaction method in turn
- when an exception happens during the commit, the JPADataSource.onSuccess(boolean) method is called.
- if there is an exception in that method (thrown in EMF.commitTransaction) the corresponding data source is added to the list of partially committed data sources and onFailure(DataSource) method is called, which in turn calls JPADataSource.onFailure(RPCManager, boolean) method (this calls EMF.rollbackTransaction in turn).
- the RPCManager.onSuccess method throws PartialCommitException, which in turn sets a boolean flag partialCommit = true.
- and that's it (at least what I see in the decompiled code) - the flag is not used in your code anywhere, the corresponding DSResponse.status = 0, the DSResponse.errors remains null.
We have no possibility to react on this error on the client side.
So the question is whether this is bug in SmartGWT or we have missed something in the documentation.
--------------------------------------------------------------------------------------
Additional information about the issue:
1. SmartGWT: SmartClient Version: v9.0p_2013-10-30/Pro Deployment (built 2013-10-30)
2. Firefox, but it does not matter
3. Two classes BgxIDACall and BgxJPADataSource are simple classes that extend corresponding Isomorphic classes and delegate all calls to the overridden methods (convenience to put breakpoints on the methods of classes that do not have source code).
4. Server exception (and some logs)
Code:
[EL Fine]: sql: 2014-01-05 12:17:28.097--ServerSession(1724897630)--Connection(357727017)--Thread(Thread[btpool0-4,5,main])--SELECT PROCESS_SEQ.NEXTVAL FROM DUAL
[2014-01-05 12:17:28,114] [INFO ] [btpool0-4] [org.activiti.engine.impl.bpmn.deployer.BpmnDeployer] Processing resource bgxTestProcess.bpmn20.xml
[2014-01-05 12:17:28,649] [INFO ] [btpool0-4] [org.activiti.engine.impl.bpmn.deployer.BpmnDeployer] Processing resource bgxPricingRequestProcess.bpmn20.xml
[EL Fine]: sql: 2014-01-05 12:17:34.046--ClientSession(1971564735)--Connection(1746904296)--Thread(Thread[btpool0-4,5,main])--INSERT INTO PROCESS (PROCESS_KEY, CREA_TMS, CREA_USER_ACCT_KEY, CUST_KEY, DEAL_TYPE_KEY, REFERENCE_NO) VALUES (?, ?, ?, ?, ?, ?)
bind => [21994, 2014-01-05 12:15:18.0, 1185, 1, 1, null]
[EL Fine]: sql: 2014-01-05 12:17:34.053--ClientSession(1971564735)--Thread(Thread[btpool0-4,5,main])--SELECT 1 FROM DUAL
[EL Warning]: 2014-01-05 12:17:34.055--UnitOfWork(1610775093)--Thread(Thread[btpool0-4,5,main])--Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: Einfügen von NULL in ("ACTOWUSER"."PROCESS"."REFERENCE_NO") nicht möglich
Error Code: 1400
Call: INSERT INTO PROCESS (PROCESS_KEY, CREA_TMS, CREA_USER_ACCT_KEY, CUST_KEY, DEAL_TYPE_KEY, REFERENCE_NO) VALUES (?, ?, ?, ?, ?, ?)
bind => [21994, 2014-01-05 12:15:18.0, 1185, 1, 1, null]
Query: InsertObjectQuery(com.smg.bgx.persistence.toolbox.PricingProcess@45d640c5)
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:900)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:377)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:125)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4196)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerSynchronization.afterCommit(ExtendedEntityManagerCreator.java:479)
at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:133)
at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerAfterCommit(TransactionSynchronizationUtils.java:121)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCommit(AbstractPlatformTransactionManager.java:951)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:797)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
at com.isomorphic.jpa.EMFProviderSpring.commitTransaction(EMFProviderSpring.java:184)
at com.isomorphic.jpa.EMF.commitTransaction(EMF.java:210)
at com.isomorphic.jpa.JPADataSource.onSuccess(JPADataSource.java:3982)
at com.isomorphic.jpa.BgxJPADataSource2.onSuccess(BgxJPADataSource2.java:52)
at com.isomorphic.jpa.JPADataSource.onSuccess(JPADataSource.java:4003)
at com.isomorphic.jpa.BgxJPADataSource2.onSuccess(BgxJPADataSource2.java:57)
at com.isomorphic.rpc.RPCManager.onSuccess(RPCManager.java:1669)
at com.isomorphic.rpc.RPCManager.completeResponse(RPCManager.java:1165)
at com.isomorphic.rpc.RPCManager.send(RPCManager.java:620)
at de.mycompany.bgx.server.BgxIDACall.processRPCTransaction(BgxIDACall.java:33)
at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:137)
at com.isomorphic.servlet.IDACall.doPost(IDACall.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:152)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1097)
at de.mycompany.bgx.server.AuthFilter.doFilter(AuthFilter.java:69)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: Einfügen von NULL in ("ACTOWUSER"."PROCESS"."REFERENCE_NO") nicht möglich
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1046)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3694)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1354)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:890)
... 72 more