Atomikos Forum |
|
Hello,
Testcase is i am having an outer service calling an inner Service. Container is Spring and both called methods are advised to run in the same transaction. In the testcase i set in the inner service rollbackOnly. Back on the outer service i want to do some searching using the already STATUS_MARKED_ROLLBACK transaction. Which gives the following exception. I know that i cant undo the rollbackonly, and every data i change from then would not persist. But it might still be useful to work on the datasources, if just to search for some data to put into my service response. Why is that behaviour not permitted? Atomikos Version: 3.7.0 22:27:07,404 ERROR Run:138 - org.hibernate.exception.GenericJDBCException: could not execute query javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1215) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:255) at at.itsv.playground.deployable.jta.Service.searchUsersOnDataSourceOne(Service.java:148) at at.itsv.playground.deployable.jta.Service.doInsert(Service.java:132) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at at.itsv.playground.deployable.jta.advice.LocalRollbackOnlyHelperAdvice.invoke(LocalRollbackOnlyHelperAdvice.java:17) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy16.doInsert(Unknown Source) at at.itsv.playground.container.Run.main(Run.java:136) Caused by: org.hibernate.exception.GenericJDBCException: could not execute query at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.loader.Loader.doList(Loader.java:2536) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276) at org.hibernate.loader.Loader.list(Loader.java:2271) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452) at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363) at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:246) ... 18 more Caused by: com.atomikos.jdbc.AtomikosSQLException: Transaction is marked for rollback only or has timed out at com.atomikos.jdbc.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:44) at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:214) at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:138) at $Proxy9.prepareStatement(Unknown Source) at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534) at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:452) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1700) at org.hibernate.loader.Loader.doQuery(Loader.java:801) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) at org.hibernate.loader.Loader.doList(Loader.java:2533) ... 26 more Caused by: com.atomikos.datasource.xa.session.InvalidSessionHandleStateException: Transaction is marked for rollback only or has timed out at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:59) at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:85) at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:176) at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:204) ... 35 more
Hi,
Disallowing this is the simplest and easiest thing that works. I see two good reasons for this behavior: 1. Our code/design is simpler 2. Anything you read would by definition be uncommitted data that you return to the client (which is dangerous IMHO) Your thoughts?
Hello Guy,
Had a quick look at jta spec, its predecessor corba and other transaction products. Quoting "https://issues.jboss.org/browse/JBTM-664"#3rd comment "A transaction is still logically active if in the rollback-only state. That status does not signify that the transaction has begun to terminate. If you assume that STATUS_MARKED_ROLLBACK makes the transaction inactive then by that logic it should be illegal to call setRollbackOnly multiple times (it should throw IllegalStateException subsequently). In fact that isn't the case and as long as the transaction has not terminated, or begun to terminate, it's correct to allow that to be called multiple times. A transaction is considered inactive once it begins the two-phase commit protocol (commit is called) or is rolled back." Quoting "http://documentation.progress.com/output/Iona/orbix/gen3/33/html/orbixots33_pguide/CosTransactions_cl.html"#Current::rollback_only() Calling Current::rollback() rolls back the transaction immediately, preventing unnecessary work from being done between the time the transaction is marked for rollback and the time the transaction is actually rolled back. The as-is situation in atomikos is that STATUS_MARKED_ROLLBACK and STATUS_ROLLBACK are now equal in effect regarding to the business service code. 1) Feels like what was not intended in the jta-spec(yes, it is said that this spec is fuzzy), as there are two different status. 2) has serious business service coding implications. I am forced to guard my code against that situation and that exception. Your argument #1, this a question of spec and - if not clearly stated - by common understanding. Understood e.g. like working with jboss and glassfish - are you in need to guard against that situation? Your argument #2, yes, but such a fact must be known to technical staff, should be decided by business experts and must be possible to opt either way for the service implementation. BTW, The same situation with quite a different effect is happening in spring :) Here spring people thought they will do the developer any good throwing an UnexpectedRollbackException if the outest service code does not acknowledge a rollback. Forcing implementors to call setRollbackOnly on their own wrapper around trasaction management. Hm, was really unexpected, not only to me... |