Allan Saddi's projects blog

Syndicate content RSS: Allan Saddi's projects blog - Announcements and ramblings about projects new and old.
Announcements and ramblings about projects new and old.
Updated: 9 hours 29 min ago

TomEE/OpenEJB + PostgreSQL XA DataSources

Sat, 2012-05-26 16:37
TomEE 1.0 released recently and due to that, I decided to revisit the land of EJBs once again. (Especially what is known as "EJB 3.1 Lite.") I've been a heavy Spring user both with work projects and personal projects, so EJBs have never really been on my radar. And for whatever reason, I always gravitate toward the transaction manager/database side whenever I try out a new container.

Anyway, setting up TomEE/OpenEJB with local transactions is pretty straightforward. What's problematic (and doesn't seem to be well documented at all) is setting up XA datasources.

There are two major problems:
  1. The XADataSource implementation must also implement DataSource. I looked at 3 drivers: PostgreSQL, H2, and briefly, Oracle 11g. PostgreSQL seems to be the only one whose XADataSource does not implement DataSource.

  2. DBCP-356 and DBCP-358. I'm not sure if they're bugs, but they're certainly oddities.
First the easy case, H2, which isn't plagued by either problem. What really isn't evident is that to set up an XA datasource in TomEE/OpenEJB, you must:
  1. Set JdbcDriver to the XADataSource implementation.

  2. Use Definition to set properties for that XADataSource rather than the usual (JdbcUrl, etc.) However, use Username and Password as normal.
So a minimal XA H2 datasource definition would look something like:

<Resource id="myDataSource" type="DataSource">
  JtaManaged true
  JdbcDriver org.h2.jdbcx.JdbcDataSource
  Definition url=jdbc:h2:MyDataBase
  UserName foobar
  Password hunter2
</Resource>

Fairly easy. And to set more properties in Definition, simply use semi-colons to delimit multiple properties.

Now, to use PostgreSQL with TomEE/OpenEJB you have to first create a dummy class that extends PGXADataSource and implements javax.sql.DataSource. If you're using JDK 6/JDBC4, you will most likely have to implement a few more methods as well. For now, it seems ok if the methods simply throw UnsupportedOperationExceptions or similar, since the PostgreSQL JDBC4 classes do the same.

public class MyPGXADataSource extends PGXADataSource implements DataSource {
    public boolean isWrapperFor(Class<?> arg0) throws SQLException {
       throw new UnsupportedOperationException();
    }
    public <T> T unwrap(Class<T> arg0) throws SQLException {
       throw new UnsupportedOperationException();
    }
}

To solve problem #2, you can either use the PostgreSQL 8.4 driver (which doesn't have the problematic interaction with DBCP), or patch up DBCP 1.4 with the patch I attached to DBCP-356. Once that's done, the PostgreSQL XA datasource definition is pretty simple:

<Resource id="myDataSource" type="DataSource">
  JtaManaged true
  JdbcDriver package.to.MyPGXADataSource
  Definition DatabaseName=foodb;ServerName=mydbhost
  UserName foobar
  Password hunter2
</Resource>

The only caveat is that PGXADataSource does not take a URL property, so you will have to pass the database name, server name, port, etc. as separate properties in Definition.