Atomikos TransactionsEssentials で JTA (XA with MySQL編)


前回の Atomikos TransactionsEssentials で JTA (Spring + JDBC 編) では、普通に UserTransaction を使ってみたところ、特に問題なく動作しました。


しかし、JPA を使い始めると、どうも動作がおかしい。

null source

まずは、以下のエラー。

Exception in thread "main" java.lang.IllegalArgumentException: null source
	at java.util.EventObject.<init>(EventObject.java:38)
	at javax.sql.StatementEvent.<init>(StatementEvent.java:39)
	at com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper.close(JDBC4PreparedStatementWrapper.java:70)
	at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534)
	at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:269)
	at org.hibernate.id.insert.AbstractReturningDelegate.releaseStatement(AbstractReturningDelegate.java:58)
	at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:36)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2163)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2643)
	at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:51)
	at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
	at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
	at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
	at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
	at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:49)
	at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131)
	at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
	at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
	at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)
	at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)
	at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)
	at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:357)
	at $Proxy9.persist(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:194)
	at $Proxy9.persist(Unknown Source)
	at sample.JpaExample1.main(JpaExample1.java:43)

おいら側のソース的には、以下のように、ただエンティティを persist しているだけです。

em1.persist(a1);

エラー吐いてるクラスは com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper ですね。


ドライバが怪しいかな、、、。

Connector/J のバージョンを 5.1.5, 5.1.4 に落としてみた。

ということで、ドライバのバージョンを、5.1.5, 5.1.4 のように落としながら試してみました。


すると、エラーが NullPointerException に変わりました。

Exception in thread "main" java.lang.NullPointerException
	at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534)
	at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:269)
	at org.hibernate.id.insert.AbstractReturningDelegate.releaseStatement(AbstractReturningDelegate.java:58)
	at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:36)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2163)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2643)
	at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:51)
	at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
	at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
	at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
	at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
	at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:49)
	at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131)
	at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
	at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
	at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)
	at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)
	at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)
	at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:357)
	at $Proxy9.persist(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:194)
	at $Proxy9.persist(Unknown Source)
	at sample.JpaExample1.main(JpaExample1.java:43)

今度は hibernate のレベルでエラーを吐いてます。


エラーの出てる箇所は、以下の ps.close(); のところです。

private void closePreparedStatement(PreparedStatement ps) throws SQLException {
    try {
        log.trace("closing statement");
        ps.close(); // ここ!!
        if ( factory.getStatistics().isStatisticsEnabled() ) {
            factory.getStatisticsImplementor().closeStatement();
        }
    }
    finally {
        if ( !releasing ) {
            // If we are in the process of releasing, no sense
            // checking for aggressive-release possibility.
            connectionManager.afterStatement();
        }
    }
}


となると、ps の実装返しているヤツが犯人か。


しかも、Connetor/J のバージョンを変えて、PreparedStatement が null になったってことは、、、。


やっぱりドライバが怪しい、、、。

Connector/J のバージョンを 5.1.3 に落としてみた。

懲りずに、バージョンを落としてみましたところ、バージョンを 5.1.3 で動きました。
ヽ( ・∀・)ノ ワーイ


以下、MySQL のログです。

650 Query  SET autocommit=0
650 Query  XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d3,0x41544f4d
650 Query  insert into A (name) values ('Kuma-chan')
650 Query  XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,x41544f4d
650 Query  XA PREPARE 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e74631,0x41544f4d
650 Query  XA COMMIT 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d1,0x41544f4d


ロールバックもしてみましたが、問題なしです。


データソースその1

1075 Query  SET autocommit=0
1075 Query  XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
1075 Query  insert into A (name) values ('Kuma-chan')
1075 Query  XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
1075 Query  XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d


データソースその2

1038 Query  SET autocommit=0
1038 Query  XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
1038 Query  insert into A (name) values ('Fellow-kun')
1038 Query  XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
1038 Query  XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d

しかし、まだまだ爆弾が眠っているような気がする。

追記

  • 5.0系のサーバに5.1系のドライバ使ってました。詳細はこのページに書いてあります。

続く