S2JDBC + S2JUnit4でハマる

S2JDBCのエンティティのテストケースをS2JUnit4で書いてみたら、大いにハマった。

org.seasar.framework.beans.IllegalPropertyRuntimeException: [ESSR0059]クラス(org.seasar.framework.jpa.impl.PersistenceUnitManagerImpl)のプロパティ(entityManagerProvider)の設定に失敗しました。理由はorg.seasar.framework.container.IllegalAutoBindingPropertyRuntimeException: [ESSR0080]クラス(org.seasar.framework.jpa.impl.EntityManagerProviderImpl)のプロパティ(dataSourceFactory)の自動設定に失敗しました
	at org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:297)
	at org.seasar.framework.container.assembler.AbstractBindingTypeDef.bindAuto(AbstractBindingTypeDef.java:164)
	at org.seasar.framework.container.assembler.BindingTypeMustDef.doBind(BindingTypeMustDef.java:45)
	at org.seasar.framework.container.assembler.AbstractBindingTypeDef.bind(AbstractBindingTypeDef.java:91)
	at org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:50)
        (以下、たくさん続く…)

Seasar2ソースコードを漁ってみたところ、自動設定に失敗しているdataSourceFactoryのコンポーネント定義は、jdbc-extension.diconに存在することがわかった。これは通常jdbc.diconからincludeされているはずなのだが、Doltengが吐き出したjdbc.diconにはこれがincludeされていない。

jdbc-extension.diconはDAOサポートに必要とされているらしいのだが、今回のようにS2JDBCを使うことを選択した場合は不要という判断なのかもしれない。しかし、S2JUnit4はDBアクセス関係のユーティリティで利用しているのだろう、とか憶測でモノを言ってみる。

とにかく、jdbc-extension.diconをincludeさせてみた。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
	"http://www.seasar.org/dtd/components24.dtd">
<components namespace="jdbc">
    <include path="jta.dicon"/>
    <include path="jdbc-extension.dicon"/>

    <component name="xaDataSource"
        class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
...

これで先ほどの例外はthrowされなくなった。

…なんかあっさりと書いているが、この件で一週間は悩んでいた。依存関係の解消にはいつも手間取る。

追記

id:taedium氏からおそろしいスピードでコメントをいただいたので、試してみた。曰く、「S2JDBCを使うのであれば、javaee5.diconではなくapp.diconをincludeしたほうがよい」なるほど−。

s2junit4を、こう書けばいいのか。

    <component class="org.seasar.framework.unit.impl.ConfigFileIncluderImpl">
        <initMethod name="addConfigFile">
            <arg>"app.dicon"</arg>
        </initMethod>
        <initMethod name="addConfigFile">
            <arg>context.testClassShortName + ".dicon"</arg>
        </initMethod>
    ...

もっとも、諸事情あってRootDiconをapp.diconにしているテストケースがあるので、こういう対応もした*1

@RunWith(Seasar2.class)
@RootDicon("app.dicon")
public class ...

    ctx.setAutoInclude(false);
    // ctx.include("javaee5.dicon");
    ctx.include("dbtest.dicon"); // 自前のdicon

これで、jdbc.diconからjdbc-extension.diconのincludeを取り除いても、ちゃんと動くようになった。

これだけ速攻で回答できるってことは、きっとありがちなケースなんだろうなぁ(汗)ともあれ、ありがとうございました。Seasar2始めてから日記も拝見しています。

*1:他のテスト用にs2junit4.diconでもapp.diconをincludeさせているので、autoIncludeさせると参照が循環してしまう