WAS 5.1, DB2 8.2, CMT, Hibernate 3.1.2 and borrowed JDBC connection => problem.
I'm coding a stateless CMT EJB method on WAS 5.1 in "transaction required" mode.
This method has to :
- do some Hibernate stuff
- then do some JDBC stuff using session.connection() and then closing it explicitely (as mentionned in Hibernate docs)
Connection release mode is "after_statement", transaction factory is CMT.
This method works perfectly with Hibernate 3.1
Since I switched to Hibernate 3.1.2, this code works too, but I can see these warnings in the logs :
J2CA0075W: An active transaction should be present while processing method allocateMCWrapper.
J2CA0075W: An active transaction should be present while processing method initializeForUOW
It might be a problem with a connection opened by a thread that is not managed by Websphere, and that is not J2EE standard.
Detailed explanation here :
http://www-1.ibm.com/support/docview.ws ... wg21109248
When I do the same JDBC stuff first and then the same Hibernate stuff : no warning
When I replace Hibernate 3.1.2 by Hibernate 3.1.0 : no warning
When I replace Hibernate 3.1.2 by Hibernate 3.1.1 : Exception because JDBC connection supplied to JDBC code is closed
Could you please help me to know what mistake I made in my code or my config ?
Or is it a 3.1.2 bug ? "borrowed connection" management changed a lot between these versions (connection dynamic proxy...)
Here is simple code that reproduces the problem :
Code:
/**
* My CMT EJB method.
* @throws Exception
*/
public void testMixHJNoFwk() throws Exception {
try {
hibernateStuff( 98 );
jdbcStuff();
} catch( Exception ex ) {
ex.printStackTrace();
throw ex;
}
}
private void jdbcStuff() throws SQLException {
System.out.println( "DELETE JDBC" );
Session sess = fact.getCurrentSession();
Connection bc = sess.connection();
bc.setAutoCommit( false );
PreparedStatement st = bc.prepareStatement( "DELETE FROM TESTOBJ WHERE NOM=?");
st.setString( 1, "nom" );
st.executeUpdate();
st.close();
bc.close();
}
private void hibernateStuff( int id ) {
Session sess = fact.getCurrentSession();
TestObject to = new TestObject();
to.setId( id );
to.setDate( new Date() );
to.setNom( "nom" );
sess.save( to );
// I need to flush, because Hibernate generared queries
// must be executed before JDBC stuff, not on session close
// that happens after JDBC stuff (end of transaction).
sess.flush();
}
Hibernate.cfg.xml :
Code:
<session-factory>
<!-- properties -->
<property name="connection.datasource">java:comp/env/jdbc/ds</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<!-- JDBC Settings -->
<property name="hibernate.connection.autocommit">false</property>
<!-- Transaction API -->
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</property>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.WebSphereTransactionManagerLookup</property>
<property name="jta.UserTransaction">java:comp/UserTransaction</property>
<property name="hibernate.session_factory_name">java:hibernate/SessionFactory</property>
<property name="hibernate.transaction.flush_before_completion">true</property>
<property name="hibernate.transaction.auto_close_session">true</property>
<property name="hibernate.connection.release_mode">after_statement</property>
<!-- mapping files (ProjetPolicy) -->
<mapping resource="hibtest/model/TestObject.hbm.xml" />
</session-factory>
Mapping :
Code:
<hibernate-mapping>
<class name="hibtest.model.TestObject" table="TESTOBJ" lazy="false">
<id name="id" column="PK" type="int">
<generator class="assigned" />
</id>
<property name="date" type="timestamp" column="DT" />
<property name="nom" type="string" column="NOM" />
</class>
</hibernate-mapping>