2011-07-30T15:36:00CEST
[Hibernate, JTA, JDBC, connection pool]
Christian Bauer

If all you want is Hibernate/JPA and a database connection pool, pick one that is JTA compatible. I've only just now found Bitronix and it looks great.

Put this in your pom.xml:

<repository>
    <id>jboss-repo</id>
    <url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>

<dependency>
    <groupId>org.codehaus.btm</groupId>
    <artifactId>btm</artifactId>
    <version>2.1.1</version>
</dependency>

<dependency>
    <!-- ORCL can't be bothered to update javax.persistence in Maven central but
         I hear great things about their new sailboat -->
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.0-api</artifactId>
    <version>1.0.1.Final</version>
</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>3.6.6.Final</version>
    <exclusions>
        <!-- Javassist does the job -->
        <exclusion>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Hibernate and the JTA manager will communicate through JNDI (don't get me started), so put a jndi.properties file on your classpath to enable the bundled minimal implementation:

java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory

Next configure and start the JTA manager and connection pool - see the Bitronix website if you want to do this with property files instead of code:

// Each JVM needs a stable unique identifier for TX recovery
TransactionManagerServices.getConfiguration().setServerId("myServer1234");

// Create the datasource and set the connection pool details
PoolingDataSource datasource = new PoolingDataSource();
datasource.setUniqueName("myDS");
datasource.setMinPoolSize(5);
datasource.setMaxPoolSize(25);
datasource.setPreparedStatementCacheSize(50);

// If you use Hibernate's hbm2ddl.auto mode, on startup SchemaExport executes
// connection.setAutoCommit(true) to export DDL. This is a non-XA transaction.
// Alternatively, wrap UserTransaction.begin() and commit() around your Hibernate
// startup code.
datasource.setAllowLocalTransactions(true);

// This is for H2 DBMS, which I really like for small scale use
datasource.setClassName("org.h2.jdbcx.JdbcDataSource");
datasource.getDriverProperties().put("URL", "jdbc:h2:mem:myTemporaryDB");
// H2 doesn't need a password for temporary in-memory databases
//datasource.getDriverProperties().setProperty("user", "scott");
//datasource.getDriverProperties().setProperty("password", "tiger");

// Create pool, bind datasource to JNDI
datasource.init();

Now set the datasource name for JNDI lookup in JPA's META-INF/persistence.xml and configure how Hibernate should lookup the transaction manager:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                                 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

    <persistence-unit name="myPU">
        <jta-data-source>myDS</jta-data-source>
        <properties>

            <property name="hibernate.dialect"
                      value="org.hibernate.dialect.H2Dialect"/>

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

            <property name="hibernate.hbm2ddl.auto"
                      value="create"/>

        </properties>
    </persistence-unit>

</persistence>

Finally, start JPA and write units of work with EntityManagers:

Context ctx = new InitialContext();
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPU");

UserTransaction tx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
tx.begin();

EntityManager em = emf.createEntityManager();
em.persist();
em.createQuery();

tx.commit();

That's neat. Now can we get rid of JNDI and have someone competent redesign the JTA API, please?

(I've tried Emmanuel's guide for standalone usage of JBoss TS but the dependencies are just too scary. I don't trust a transaction manager runtime that depends on a diagram drawing library or a test coverage tool. No, it's not fixed in the latest version. If the implementation code looks like the build setup...)

3 Comments
2011-07-31T07:55:39CEST
Guy
Atomikos should work too: http://www.atomikos.com/Main/TransactionsEssentials Best
2011-08-06T13:50:32CEST
Ludovic Orban
You may be interested in reading http://blog.bitronix.be/2011/02/why-we-need-jta-2-0/ . You're one of the very few people who seem to grasp the true essence of JTA as you proved in the comments you posted there: https://issues.jboss.org/browse/JBSEAM-1144. I'm desperate about that spec so if you have any idea of what could be done to improve the situation I'm more than open to listen to what you have to say. Thanks!
2011-08-06T15:38:27CEST
Christian Bauer
The quality of JTA has been a major but hidden factor why Java EE has a heavyweight reputation. I remember saying that if JTA and JNDI APIs weren't as horrible as they are, Spring would not exist. A simple checked exception in the wrong place can result in an impressive amount of framework and wrapper code over time. The problem is that meanwhile nobody is using these APIs directly anymore. The same goals (transaction demarcation and component lookup) can be achieved declaratively without externalization (no XML). Frameworks like Spring and Seam just wrap it anyway no matter how good the API is, it's great for hidden vendor lock-in. Marketing a standalone implementation of these APIs has the same issue, as I'm sure you have found out by now. Although people like me who write books/documentation love the modularity of a standalone JTA manager for tutorials, in practice almost everyone will just deploy on a fully managed Java EE container. I'll talk to some people who are more familiar with the JCP and see if we can get a discussion started.
Add comment

New Java Persistence with Hibernate Training Course available!
Creative Commons License