configuration problem Tomcat + Hibernate + Spring + BTM

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

configuration problem Tomcat + Hibernate + Spring + BTM

Boris Granveaud
Hi,

I've been struggling for the last few days to convert my webapp which works fine with Spring HibernateTransactionManager to BTM. The idea is that I would like to test JBoss Cache and it needs a JTA transaction manager. For the moment, I've configured no 2nd level caching.

I've got something that works but the performance are very bad. From what I understand in the logs, I think that the problem is that BTM opens and closes one transaction for each SQL statement.

My configuration is: Hibernate 3.3.2, BTM 1.3.2, Spring 2.5.

I tried to use a LrcXADataSource because I've got only one datasource, so AFAIK it should be more efficient.

My Spring config file:

 
  <bean id="hibernateDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
    <property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource"/>
    <property name="uniqueName" value="hibernateDataSource"/>
    <property name="allowLocalTransactions" value="true"/>
    <property name="driverProperties">
     ...
    </property>
  </bean>

 
  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" depends-on="txManager">
    <property name="useTransactionAwareDataSource" value="true"/>
    <property name="dataSource" ref="hibernateDataSource"/>
    <property name="packagesToScan" value="com.crmcompanygroup.crmsante.model"/>

    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
        <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup</prop>
        <prop key="hibernate.current_session_context_class">jta</prop>
        <prop key="hibernate.jndi.class">bitronix.tm.jndi.BitronixInitialContextFactory</prop>
       
        <prop key="hibernate.connection.release_mode">after_statement</prop>
        <prop key="hibernate.cache.use_query_cache">false</prop>
        <prop key="hibernate.cache.use_second_level_cache">false</prop>
       
        <prop key="hibernate.connection.isolation">2</prop>
      </props>
    </property>
  </bean>

 
  <bean id="btmConfig" factory-method="getConfiguration" class="bitronix.tm.TransactionManagerServices">
    <property name="serverId" value="spring-btm"/>
  </bean>

 
  <bean id="btmTransactionManager" factory-method="getTransactionManager"
        class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig" destroy-method="shutdown"/>

 
  <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="btmTransactionManager"/>
    <property name="userTransaction" ref="btmTransactionManager"/>
  </bean>

I'm not sure about the allowLocalTransactions=true but it doesn't work without that. Same for useTransactionAwareDataSource=true, is this important??

When I perform one request to my webapp which should be handled in one enclosing transaction, I see several times this logs, so it seems that several transactions are opened/closed:

11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.tm.resource.jdbc.PoolingDataSource - acquiring connection from a PoolingDataSource containing an XAPool of resource hibernateDataSource with 20 connection(s) (20 still available)
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG bitronix.tm.resource.common.XAPool - trying to recycle a NOT_ACCESSIBLE connection of an XAPool of resource hibernateDataSource with 20 connection(s) (20 still available)
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG bitronix.tm.resource.common.XAPool - no current transaction, no connection can be in state NOT_ACCESSIBLE when there is no global transaction context
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG bitronix.tm.resource.common.XAPool - getting a IN_POOL connection from an XAPool of resource hibernateDataSource with 20 connection(s) (20 still available)
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG bitronix.tm.resource.common.XAPool - waiting for IN_POOL connections count to be > 0, currently is 20
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG bitronix.tm.resource.common.XAPool - found IN_POOL connection a JdbcPooledConnection from datasource hibernateDataSource in state IN_POOL wrapping a LrcXAConnection from an XAPool of resource hibernateDataSource with 20 connection(s) (20 still available)
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - getting connection handle from a JdbcPooledConnection from datasource hibernateDataSource in state IN_POOL wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.AbstractXAStatefulHolder - notifying 2 stateChangeEventListener(s) about state changing from IN_POOL to ACCESSIBLE in a JdbcPooledConnection from datasource hibernateDataSource in state IN_POOL wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.AbstractXAStatefulHolder - state changing from IN_POOL to ACCESSIBLE in a JdbcPooledConnection from datasource hibernateDataSource in state IN_POOL wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.AbstractXAStatefulHolder - notifying 2 stateChangeEventListener(s) about state changed from IN_POOL to ACCESSIBLE in a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - connection a LrcXAConnection was in state STATE_IN_POOL, testing it
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - no query to test connection of a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection, skipping test
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - got connection handle from a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.tm.resource.jdbc.PoolingDataSource - acquired connection from a PoolingDataSource containing an XAPool of resource hibernateDataSource with 20 connection(s) (19 still available)
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - enlisting a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection into null
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - in local transaction context, skipping enlistment
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcConnectionHandle - closing a JdbcConnectionHandle of a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection on a LrcConnectionHandle of a LrcXAResource in state NO_TX
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - releasing to pool a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - delisting a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection from null
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - resource is not in enlisting global transaction context: a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - requeuing a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection from null
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - resource is not in enlisting global transaction context: a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - looking in in-flight transactions for XAResourceHolderState of a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - resource not enlisted in any transaction: a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.TransactionContextHelper - resource not in enlisting global transaction context, immediately releasing to pool a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.AbstractXAStatefulHolder - notifying 2 stateChangeEventListener(s) about state changing from ACCESSIBLE to IN_POOL in a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - closing 1 uncached statement(s)
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - clearing warnings of a LrcConnectionHandle of a LrcXAResource in state NO_TX
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.AbstractXAStatefulHolder - state changing from ACCESSIBLE to IN_POOL in a JdbcPooledConnection from datasource hibernateDataSource in state ACCESSIBLE wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.c.AbstractXAStatefulHolder - notifying 2 stateChangeEventListener(s) about state changed from ACCESSIBLE to IN_POOL in a JdbcPooledConnection from datasource hibernateDataSource in state IN_POOL wrapping a LrcXAConnection
11 sept. 2009 14:02:34.373 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - requeued JDBC connection of a PoolingDataSource containing an XAPool of resource hibernateDataSource with 20 connection(s) (20 still available)
11 sept. 2009 14:02:34.389 [http-8080-Processor23] DEBUG bitronix.tm.resource.common.XAPool - a connection's state changed to IN_POOL, notifying a thread eventually waiting for a connection
11 sept. 2009 14:02:34.389 [http-8080-Processor23] DEBUG b.t.r.jdbc.JdbcPooledConnection - released to pool a JdbcPooledConnection from datasource hibernateDataSource in state IN_POOL wrapping a LrcXAConnection

Any idea of what's wrong?

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: configuration problem Tomcat + Hibernate + Spring + BTM

Ludovic Orban
Administrator
Hi,

I see different issues with your config which seem to give you some kind of autocommit behavior.

First, useTransactionAwareDataSource should always be left to false or Spring will interfere with the connection pooling mechanism.

Second, using LrcXADataSource or not makes no performance difference at all when you're using a single resource.

Third, the fact that you have to set allowLocalTransactions to true indicates that you're incorrectly using the transaction manager. I would advise you to always leave it to false as this feature is a safety net which prevents you from using your connections outside transactions.

As a matter of fact, you're not indicating to the TM that it needs to start and commit/rollback transactions. There are basically two ways to do that:

1) get a reference to the javax.transaction.UserTransaction object (that would be the btmTransactionManager Spring bean in your case) and use the JTA API: explicitly call UserTransaction.begin() in your code to start a transaction and UserTransaction.commit() or UserTransaction.rollback() to end it.

2) use Spring's AOP capabilities and configure declarative TX management, there's an example of how to do that here: http://docs.codehaus.org/display/BTM/Spring+Framework13#SpringFramework13-Step6%3AConfiguredeclarativetransactionmanagement

This is something that must be done: transaction logic actually is business logic so no library nor framework can tell for you when they need to be started and ended.

Please try this out and let me know if it helped.
Reply | Threaded
Open this post in threaded view
|

Re: configuration problem Tomcat + Hibernate + Spring + BTM

Simon-2745

With spring+btm you can also use a TransactionTemplate to control the
transaction which helps you focus only on your application code:

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/transaction/support/TransactionTemplate.html

You setup the TransactionTemplate within the spring configuration to
have a reference to the bitronix TM. The template will do the
begin()/commit()/rollback() around the code which you give it as a
callback. Typical Spring TransactionTemplate code that would look
something like the code below. Although the code looks a little
unfamiliar at first it can help to keep a narrower scope to your
transactions. It can also help to prevent the introduction of methods
and interfaces who's only purpose is to declare them as being
transactional which can lead to a procedural feel to business services.

@Service("myService")
class MyService {

private TransactionTemplate transactionTemplate = null;
...

public String process( final Work work ) {

    String result = (String)transactionTemplate.execute( new
TransactionCallback() {
        Object doInTransaction( TransactionStatus tstatus ) {
             java.lang.System.out.println( work.toString() );
             // do the work that touches many resources within a
transaction. the template will rollback any work if an runtime exception
is thrown or if tstatus.setRollbackOnly() is called.
        }      
    });

    return result;

}


}

rgds
Simon

Ludovic Orban wrote:

> As a matter of fact, you're not indicating to the TM that it needs to start
> and commit/rollback transactions. There are basically two ways to do that:
>
> 1) get a reference to the javax.transaction.UserTransaction object (that
> would be the btmTransactionManager Spring bean in your case) and use the JTA
> API: explicitly call UserTransaction.begin() in your code to start a
> transaction and UserTransaction.commit() or UserTransaction.rollback() to
> end it.
>
> 2) use Spring's AOP capabilities and configure declarative TX management,
> there's an example of how to do that here:
> http://docs.codehaus.org/display/BTM/Spring+Framework13#SpringFramework13-Step6%3AConfiguredeclarativetransactionmanagement
>
>  


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: configuration problem Tomcat + Hibernate + Spring + BTM

Boris Granveaud
In reply to this post by Ludovic Orban
Hi,

Thank you for your help. I'm going to change useTransactionAwareDataSource and allowLocalTransactions as you said.

Regarding LrcXADataSource, what is the point of this data source if it doesn't optimize performance for a single source?

I'm aware that I need to specify transactions start and end. I use @Transactional annotations and they work fine with HibernateTransactionManager. But now that I switched to a JTA transaction manager, it doesn't work anymore. Something must be missing in my Spring configuration.

Ludovic Orban wrote
I see different issues with your config which seem to give you some kind of autocommit behavior.

First, useTransactionAwareDataSource should always be left to false or Spring will interfere with the connection pooling mechanism.

Second, using LrcXADataSource or not makes no performance difference at all when you're using a single resource.

Third, the fact that you have to set allowLocalTransactions to true indicates that you're incorrectly using the transaction manager. I would advise you to always leave it to false as this feature is a safety net which prevents you from using your connections outside transactions.

As a matter of fact, you're not indicating to the TM that it needs to start and commit/rollback transactions. There are basically two ways to do that:

1) get a reference to the javax.transaction.UserTransaction object (that would be the btmTransactionManager Spring bean in your case) and use the JTA API: explicitly call UserTransaction.begin() in your code to start a transaction and UserTransaction.commit() or UserTransaction.rollback() to end it.

2) use Spring's AOP capabilities and configure declarative TX management, there's an example of how to do that here: http://docs.codehaus.org/display/BTM/Spring+Framework13#SpringFramework13-Step6%3AConfiguredeclarativetransactionmanagement

This is something that must be done: transaction logic actually is business logic so no library nor framework can tell for you when they need to be started and ended.

Please try this out and let me know if it helped.
Reply | Threaded
Open this post in threaded view
|

Re: configuration problem Tomcat + Hibernate + Spring + BTM

Ludovic Orban
Administrator
LrcXADataSource is meant for databases lacking XA support or faking it or when the implementation is too buggy. This XA datasource wraps a standard JDBC Driver implementation and emulates XA with the safest possible way.

If your code is @Transactional annotated you should have such tag in your spring config:

<tx:annotation-driven transaction-manager="txManager"/>

I guess you do have it but it was missing from the config snippet you copied. If your transactional logic works with the hibernate transaction manager then it should also work with the JTA one. I'm just suspecting that your transactions are working just by chance with Hibernate as this isn't uncommon at all.