My goal is to have a standalone solution for building JUnit tests for local and distributed transactions using JPA over Hibernate over MySQL.
So far, I have been able to use an XADataSource to access a XAResource and manage the distributed transaction following the 2 phase commit protocol. However, I have to issue SQL statements directly.
I have been trying to do the same but using JPA 2.0 persistence. I'm using simple-jndi to have an in-memory JNDI implementation.
However I keep getting NullPointerException whenever Hibernate tries to access the TransactionManager.
Any ideas? What is missing from my configuration?
Here's what I would like to do:
// Create the XA datasource instance directly
MysqlXADataSource mysqlDS = new MysqlXADataSource();
mysqlDS.setServerName("localhost");
mysqlDS.setDatabaseName("test");
mysqlDS.setUser("root");
mysqlDS.setPassword("rootroot");
// setup local JNDI
final XADataSource xaDataSource = (XADataSource) mysqlDS;
InitialContext ctx = new InitialContext( );
ctx.bind("java:/ExampleDS", xaDataSource);
{
System.out.println("Lookup...");
Object o = ctx.lookup("java:/ExampleDS");
System.out.println("Test lookup: " + o);
}
// XID - transaction ID
// global transaction identifier
// - -- --
byte[] gtrid = new byte[] { 0x44, 0x11, 0x55, 0x66 };
// branch qualifier
// - ----
byte[] bqual = new byte[] { 0x00, 0x22, 0x00 };
// combination of gtrid and bqual must be unique
Xid xid1 = new com.mysql.jdbc.jdbc2.optional.MysqlXid(gtrid, bqual, 0);
// byte[] gtrid, byte[] bqual, int formatId
// before transaction
{
XADataSource xaDS = (XADataSource) ctx.lookup("java:/ExampleDS");
XAConnection xaconn = xaDS.getXAConnection();
Connection conn = xaconn.getConnection();
XAResource xares = xaconn.getXAResource();
/* the transaction begins */
System.out.println("Start transaction");
xares.start(xid1, TMNOFLAGS);
}
// JPA code
EntityManagerFactory emf;
emf = Persistence.createEntityManagerFactory("MyPersistenceUnit"); // defined in persistence.xml
EntityManager em = emf.createEntityManager();
// System.out.println("begin");
// em.getTransaction().begin();
System.out.println("new ContactBook");
ContactBook contactBook = new ContactBook("Alice");
System.out.println("addContacts");
contactBook.addContact("Alice", 100100100);
contactBook.addContact("Bob", 200200200);
contactBook.addContact("Charlie", 300300300);
System.out.println("persist");
em.persist(contactBook);
//em.flush();
// System.out.println("commit");
// em.getTransaction().commit();
// after transaction
{
XADataSource xaDS = (XADataSource) ctx.lookup("java:/ExampleDS");
System.out.println("xaDS " + xaDS);
XAConnection xaconn = xaDS.getXAConnection();
Connection conn = xaconn.getConnection();
XAResource xares = xaconn.getXAResource();
System.out.println("End transaction");
xares.end(xid1, TMSUCCESS);
// prepare, commit
System.out.print("Prepare... ");
int rc1 = xares.prepare(xid1);
System.out.println(xaString(rc1));
if (rc1 == XA_OK) {
System.out.println("Commit");
xares.commit(xid1, /*onePhase*/ false);
} else if(rc1 == XA_RDONLY) {
System.out.println("Commit no necessary - operations were read only");
} else {
throw new IllegalStateException("Unexpected case!");
}
}
Here is persistence.xml:
<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="ContactBookPersistenceUnit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/ExampleDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="current_session_context_class" value="jta"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
<property name="hibernate.connection.release_mode" value="auto"/>
</properties>
</persistence-unit>
No comments:
Post a Comment