Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagation REQUIRES_NEW fails on JBoss Application Server 4.2.1 when keeping a JDBC Connection handle [SPR-4122] #8801

Closed
spring-issuemaster opened this issue Nov 18, 2007 · 19 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Nov 18, 2007

Kavipriya Gnanasambandam opened SPR-4122* and commented

My issue is same as that of the issue #8755. I tried upgrading to the latest Spring 2.5 jar final but still i am getting the same issue.

I am obtaining the error message as

In this scenario also we have the call from the REQUIRED to the REQUIRES_NEWWe obtained the following error.

07:18:14 DEBUG [] [Admin] util.spring.TweJtaTransactionManager - Suspending current transaction, creating new transaction with name [com.taxware.priya.util.sequence.interfaces.ICustomDBSequenceOrganizer.getSequenceNextVal]
07:18:14 ERROR [] [Admin] util.sequence.CustomDBSequenceGenerator - Exception in getSequenceNextVal(). keyName = TJ_ACCOUNTING_METHOD_SEQ, dataSourceName= TweDSRef Message: Trying to change transaction TransactionImple < ac, BasicAction: a0359a9:6ba:4740d127:27a status: ActionStatus.RUNNING > in enlist!
java.lang.IllegalStateException: Trying to change transaction TransactionImple < ac, BasicAction: a0359a9:6ba:4740d127:27a status: ActionStatus.RUNNING > in enlist!
at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:525)
at org.jboss.resource.connectionmanager.TxConnectionManager.transactionStarted(TxConnectionManager.java:328)
at org.jboss.resource.connectionmanager.CachedConnectionManager.userTransactionStarted(CachedConnectionManager.java:360)


Affects: 2.0.2

Attachments:

Issue Links:

  • #8797 PROPAGATION_REQUIRES_NEW fails on JBoss 4.2.1 when using Hibernate connection release mode "on_close"
  • #8786 Transaction Manager issue "NO Active JTA Transaction". Sprying trying to synchronise a transaction marked for rollback.
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 18, 2007

Kavipriya Gnanasambandam commented

Setting the below property solved the issue.

<property name="transactionSynchronization">
<bean id="org.springframework.transaction.jta.JtaTransactionManager.SYNCHRONIZATION_NEVER" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
</property>

But this property has an impact in a different scenario.

Do we have any work around for this issue?

Thanks.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 18, 2007

Juergen Hoeller commented

So you're getting this exception even with the following two settings on LocalSessionFactoryBean / in the Hibernate properties?

<property name="useTransactionAwareDataSource" value="true"/>

<prop key="hibernate.connection.release_mode">after_statement</prop>

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

Yes after setting these two properties also i am getting the same issue. I tried using Spring 2.5 final in which the setting of the above two mentioned properties is not needed. But still i am getting the issue.
Only if i set the property as SYNCHRONISATION_NEVER i am not getting the issue.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

I am also getting the exception as

java.lang.IllegalStateException: Cannot deactivate transaction synchronization - not active
at org.springframework.transaction.support.TransactionSynchronizationManager.clearSynchronization(TransactionSynchronizationManager.java:270)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:902)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:704)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:624)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:307)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at com.taxware.twe.common.storage.StorageNotificationInterceptor.invoke(StorageNotificationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
at $Proxy80.setupAccountingMethod(Unknown Source)

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

I could figure out the issue to an extent.

The issue is in my normal flow that is when in the SYNCHRONISATION is left as such by default. JTA is trying to synchronise before the commit process but it is saying that the transaction is not active so it is not able to deactivate the transaction synchronisation. Please find the error log below

11:23:18 DEBUG [] [Admin] util.spring.JtaTransactionManager - Triggering beforeCommit synchronization
11:23:18 DEBUG [] [Admin] util.spring.JtaTransactionManager - Triggering beforeCompletion synchronization
11:23:18 ERROR [] [Admin] twe.bd.OrganizationBd - Cannot deactivate transaction synchronization - not active
java.lang.IllegalStateException: Cannot deactivate transaction synchronization - not active
at org.springframework.transaction.support.TransactionSynchronizationManager.clearSynchronization(TransactionSynchronizationManager.java:270)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:902)

But when i give the parameter SYNCHRONIZATION_NEVER then in that case JTA will not try to synchronise the transaction so my flow goes normally without any issue. The value is commited in the DB.

So the issue is when we try to deactivate transaction synchronisation. Because of the exception there the normal flow is interrupted.

If i am not wrong i raised a similar synchronisation issue where spring is trying to synchronise a transaction that is not active and you have fixed the same. But i am not sure whether there are some more synchronisation issues.

Can you please help me out in this.

Thanks.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

Some more clues in this issue is the call is through the JDBC and not through hibernate.
As the call is via JDBC we are trying to use the same connection were we have the issue.

If we are getting new connections each and every time then this issue is not coming.
But getting new connections each time in a while loop is a performance impact.
And there are many JDBC calls in our code it will be a very huge change if we are planning to change it in such a way that it takes new connection every time.

As hibernate has a property as after_statement do we have any other setting in JDBC to indicate that every time a new connection has to be created so that we can overcome this issue for time being.

Thanks.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Juergen Hoeller commented

Ah... you're keeping a JDBC Connection handle yourself there! This is simply not supported by JBoss. (FWIW, it is supported by WebLogic and WebSphere.) Spring can do nothing about that... I'm afraid you have no other choice than to close and reopen those Connections within each transaction boundary. This should be reasonably efficient, though, since the Connections are pooled anyway.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

For e.g
I get a connection before the while loop. That is only one connection object is created that is used across.When the spring is trying to synchronise the transaction. Spring fails stating that the Cannot deactivate transaction synchronization - not active. Can't the spring deactivate the synchronisation when the same connection is used across?

 con = SQLConnection.getConnection(dsRef);
while (createItr.hasNext())
{
 }

If i create the same connection object inside the while loop then the synchronisation passes without any issue.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

This is our scenario. We have two beans

1)Bean A and Bean B.
2)The transaction attribute of Bean A is requires and the Transaction Attribute of Bean B is Requires New.
3) Bean A calls Bean B.
4)When Bean A calls Bean B the current transaction of Bean A is suspended and new transaction is created. Then TransactionSyncronizationManager clears the transaction synchronization. While trying to clear the transaction synchronisation the issue happens.

11:23:18 ERROR [] [Admin] twe.bd.OrganizationBd - Cannot deactivate transaction synchronization - not active

The Bean B is called via the JDBC route. We faced the similar issue in Spring with hibernate were the work around you suggested was after_statement property but the same work around wont work with JDBC calls. So will spring fix the issue for the JDBC route also.

And in the mean time do we have any work around for this issue.

Thanks.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

The same issue has been raised in the Spring forum

http://forum.springframework.org/showthread.php?t=18781&page=2.

And the Spring Senior team member has replied stating that the work around is to set the property SYNCHRONIZATION_NEVER. That is we need to instruct the Spring not to hold on to a connection but rather obtain a connection from the DataSource for each use.

But this work around has impact in some other areas.

Can you please let me know whether is this the only work around available. Or is Spring planning to provide some fix for the same.

Thanks.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Juergen Hoeller commented

While there may be some things that Spring can do better here, the fundamental underlying issue is that JBoss does not support holding a JDBC Connection open across transaction boundaries. So I'm afraid you'll have to obtain the Connection freshly within each transaction boundary, which is the equivalent of what Hibernate's connection release mode "after_statement" does.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 19, 2007

Kavipriya Gnanasambandam commented

In Spring 2.5 final you have fixed the issue by aggresively closing the connection that hibernate is holding at a point of time. Cant the same work around be applied for the JDBC connection. I am not sure whether it is possible. But can't Spring aggresively close the connections. We are supporting Weblogic,Websphere and JBoss Appserver. we cant create new connections each time for the issue of JBoss Appserver. I am still wondering whether will it be able for Spring to provide some work around.

JBoss is not going to provide any work around because they might say that it is an expected behaviour. But as per spec it is the responsibility of the appserver to close the connection aggresively.

Is there anything that can be done from the Spring side to solve this issue.

Thanks for your immediate response and replies.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 25, 2007

Juergen Hoeller commented

I've added a "reobtainTransactionalConnections" flag to Spring's TransactionAwareDataSourceProxy. This means that the actual target Connection will get returned on suspend and reobtained on resume, even if your application keeps hold on to the Connection handle -- provided that you define a TransactionAwareDataSourceProxy with reobtainTransactionalConnections="true" and obtain your application's Connections through it.

All you need to do is to define such a DataSource proxy inbetween your application code and the target DataSource. Your application code would then be talking to this proxy instead of to the target DataSource directly, simply by injecting a reference to this proxy where necessary. Note that this is only necessary if your application holds on to a Connection handle across transaction boundaries!

<bean id="myDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"/>
<property name="targetDataSource" ref="myTargetDataSource"/>
<property name="reobtainTransactionalConnections" value="true"/>
</bean>

Performance-wise, this should be fine since reobtaining the target Connection during a transaction is an efficient operation; Spring caches the current transactional Connection in the background. So this should hopefully solve your problem... Please give this a try with tonight's 2.5.1 snapshot and let me know whether it works for you!

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 28, 2007

Kavipriya Gnanasambandam commented

In our application we are not using the TransactionAwareDataSourceProxy. This is the sample of our SpringConfig file.

<beans>

<bean id="dataSource"
    class="org.springframework.jndi.JndiObjectFactoryBean"
    abstract="false" singleton="true" lazy-init="default"
    autowire="default" dependency-check="default">
    <property name="jndiName" value="DS" />

</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
    abstract="false" singleton="true" lazy-init="default"
    autowire="default" dependency-check="default">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
    <property name="mappingJarLocations">
        <list>
            <value>mapping.jar</value>
        </list>
    </property>
 <property name="useTransactionAwareDataSource" value="true"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">
                org.hibernate.dialect.SQLServerDialect
            </prop>
            <prop key="hibernate.connection.release_mode">after_statement</prop>
            <!-- prop key="current_session_context_class">thread</prop -->
            <prop key="hibernate.transaction.factory_class">
                org.hibernate.transaction.CMTTransactionFactory
            </prop>
            <prop
                key="hibernate.transaction.manager_lookup_class">
                com.taxware.twe.util.hibernate.GenericTransactionManagerLookup
            </prop>
            <prop key="hibernate.jdbc.use_streams_for_binary">true</prop>
            <prop key="hibernate.jdbc.batch_size">0</prop>
        </props>
    </property>
</bean>

In this where can i include the property reobtainTransactionalConnections?

Thanks

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 28, 2007

Juergen Hoeller commented

I suppose your JDBC-based DAOs receive a reference to the "dataSource" bean directly? You need to define a separate TransactionAwareDataSourceProxy like as follows:

<bean id="myDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<property name="targetDataSource" ref="dataSource"/>
<property name="reobtainTransactionalConnections" value="true"/>
</bean>

Your JDBC-based DAOs should then receive a reference to this "myDataSource" bean (or whatever you prefer to call it).

So this is only about the JDBC access side of your code. It won't affect Hibernate access at all.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 29, 2007

Kavipriya Gnanasambandam commented

I took the Spring 2.5.1 jar from the Nightly Snap shot and I have added the property you have provided to the Spring config file. But still i am getting the same issue. I have attached my Spring Config file and the datasource file.

Thanks

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 29, 2007

Juergen Hoeller commented

What does your JDBC access code look like? Does it talk to the "myDataSource" and "loadDataSource" beans (the proxies) accordingly? How exactly does it handle its open Connection?

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 29, 2007

Kavipriya Gnanasambandam commented

The issue is Jboss doesnot allow to suspend a transaction when there are any open connections associated to it.
The same issue that we faced in hibernate. But now this is the issue with the JDBC connection where we open a connection then we suspend the transaction and try to create a new transaction.

As we are having a connection open we are not able to suspend the transaction.

As this is JDBC connection handling we have modified the code such a way that the connections are not left open before suspending the transaction.

But is there anything that spring can do it from their side for this issue?

Thanks

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 29, 2007

Juergen Hoeller commented

I do understand the scenario. The recent change in TransactionAwareDataSourceProxy was designed exactly for that scenario. If you obtain your Connection from that special DataSource, you'll get a proxy back which will transparently return the Connection and reobtain it accordingly.

My suspicion is that your code is still talking to the original DataSource, not to the TransactionAwareDataSourceProxy. Can you please double-check that your code is set up correctly there, so that your JDBC access code actually receives a Connection proxy from the TransactionAwareDataSourceProxy? Check the Connection handle that your code receives there: Is it a raw JBoss Connection or is it a Spring Connection proxy? The raw JBoss Connection will not work with suspension, but the Spring Connection proxy should be able to handle that.

Juergen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.