Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global transaction management - Jboss : Closing a connection for you

We have a spring application deployed on a jboss 7 server.

The application uses multiple datasources obtained from jboss through jndi.

The Transaction management is also provided by the Java EE container (we use Spring JtaTransactionManager)

The app architecture is a legacy one with DAOs extending hibernate Templates (using Spring HibernateDaoSupport).

Transaction are managed in the service layer using @Transactional annotations.

My 1st questions are:

  • when encountering the annotation, how does the transaction manager know which datasources will be involved in the transaction ?

  • when does it effectively retrieve a JDBC connection and on which datasources ? when does it effectively open a transaction ? (only DAOs got a reference to the sessionFactory bound to a specific datasource).

The driver we are using does not support distributed (XA) transactions, in most case we doesn't need multi-phase commit as only one datasource is written. Anyway when we access (read only) other datasources within the same transaction we got messages in logs :

INFO  [org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager] (http--0.0.0.0-8080-4) IJ000100: Closing a connection for you. Please close them yourself: org.jboss.jca.adapters.jdbc.jdk6.WrappedConnectionJDK6@691644c: java.lang.Throwable: STACKTRACE
at org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl.registerConnection(CachedConnectionManagerImpl.java:265)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:495)
at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:129)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) [hibernate-core-3.3.1.GA.jar:3.3.1.GA]
[...]
  • Is there a way to properly manage connection release in such a case without using XA datasources ?

  • Otherwise can those message safely be ignored or do they denote a real problem ? (log level is INFO)

[edit]

Some additional data on configuration :

exemple of datasource declaration

<!-- JNDI datasource -->
<bean id="customersDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/${shared.datasource}" />
</bean>

Associated sessionFactory

<bean id="sharedSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="customersDataSource" />
    <property name="configLocation" value="classpath:hibernate.shared.cfg.xml" />
    <property name="hibernateProperties">
        <props>
            <!-- jboss specific transaction management -->
            <prop key="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
            <prop key="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
            <prop key="hibernate.connection.release_mode">after_transaction</prop>
            <prop key="hibernate.transaction.auto_close_session">true</prop>
            [...]
        </props>
    </property>
</bean>

We are thinking about playing with hibernate.connection.release_mode but even if only one datasource is actually written within a single transaction, it's not always the same one.

like image 633
Gab Avatar asked Nov 01 '22 22:11

Gab


1 Answers

When encountering the annotation, how does the transaction manager know which datasources will be involved in the transaction ?

As long as you have:

<tx:annotation-driven/>

Spring should use a TransactionInterceptor that intercepts your service method call and wraps the request in a JTA transaction.

Spring doesn't have an actual XA transaction manager, the JtaTransactionManager is only a facade requiring a backend JTA provider (like JBoss AS transaction manager).

You still need to configure the Jboss TM, like this:

<bean id="jbossTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple">
</bean>

When does it effectively retrieve a JDBC connection and on which datasources ? when does it effectively open a transaction ? (only DAOs got a reference to the sessionFactory bound to a specific datasource).

The transaction is triggered by the JtaTransactionManager which delegates the actual transaction init request to JBoss TM.

All data sources must be XA complaint, you can't mix JTA with resource-local DataSources. Some transaction manager may use the LastResourceCommit optimization allowing you to enlist up to one non-XA DataSource.

The data source is enlisted in the current transaction the moment a database connection is wanted:

DataSource.getConnection()

From this point on this connection will participate in the current transaction, hence it will be committed or rollback based on the transaction outcome.

I don't think you should use LocalDataSourceConnectionProvider. You need to set:

<jta-data-source>java:/WareHouseDS</jta-data-source>

<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />

Hibernate needs to know where to get the JBoss AS JNDI for the registered DataSource.

like image 140
Vlad Mihalcea Avatar answered Nov 13 '22 23:11

Vlad Mihalcea