Groovy で S2JDBC を使用してみる
急に思い立ったので、Groovy スクリプト上で S2JDBC(S2・S2Tiger 2.4.18 RC3)を試してみることにした。
なんとなくハマリそうな気もしたのだが、Groovy 1.1 ならアノテーションを使えるし Groovy だけで S2JDBC が書けると色々活用できるかなと思い、とりあえずやってみる事に。
import javax.persistence.* import org.seasar.framework.container.SingletonS2Container import org.seasar.framework.container.factory.SingletonS2ContainerFactory import org.seasar.extension.jdbc.JdbcManager @Entity class Dept { @Id @GeneratedValue Integer id Integer deptNo String deptName String loc @Version Integer versionNo } SingletonS2ContainerFactory.init() def jdbcManager = SingletonS2Container.getComponent(JdbcManager.class) def dept = new Dept(deptNo : 5, deptName : "テスト・データ") jdbcManager.insert(dept).execute() println("id : ${dept.id}") def insDept = jdbcManager.from(Dept.class).where("id = ?", dept.id).getSingleResult() println("result : ${insDept.id}, ${insDept.deptNo}, ${insDept.deptName}")
上記のスクリプトを Groovy 1.1 RC3(JavaSE 6)で実行してみると。案の定、以下のようなエラーが発生。エンティティクラスに Java で定義したものを使って Groovy 1.0 で実行しても同様のエラーが発生。
>groovy test.groovy Caught: java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.seasar.extension.dbcp.impl.XAConnectionImpl.getXAResource()Ljavax/transaction/xa/XAResource;" the class loader (instance of org/codehaus/groovy/tools/RootLoader) of the current class, org/seasar/extension/dbcp/impl/XAConnectionImpl, and the class loader (instance of <bootloader>) for interface javax/sql/XAConnection have different Class objects for the type javax/transaction/xa/XAResource used in the signature at test.run(test.groovy:29) at test.main(test.groovy)
やっぱり駄目かなとは思ったものの、メカニズムはよくわからないが、別々の JAR ファイルに含まれている javax.transaction.xa.XAResource クラスが、それぞれ別のクラスローダーに読み込まれてるのが原因だと予想し、一方の XAResource クラスを JAR ファイルから排除するというかなり強引な方法を試してみる事にした。
実際に、以下の方法を実施した JAR ファイルを作成し geronimo-j2ee_1.4_spec-1.0.jar の代わりに使って上記のスクリプトを実行してみたところ、エラーも発生せずに見事実行に成功した。
これにより多少手間がかかるものの、Groovy 1.1 で一応は S2JDBC を実行できる事を確認した。
なお、dicon ファイルは以下のものだけを使い、app.dicon 以外は Java で S2JDBC を使った時(id:fits:20071127)のファイルをそのまま使用した。
ちなみに、app.dicon は以下のように変更。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components> <include path="s2jdbc.dicon"/> </components>