HotDeployClassLoaderはJPAのTempClassLoaderとして使えるか?

Seasarメディア準備号 ひがやすお氏インタビューを読みました。

Javaは、クラスを一度クラス・ローダーに読ませると変更できません。デバッガAPIを使えば可能ですが、この路線はいろいろ考えて放棄しました。一カ月考えて、ゴールデン・ウィークに方法を思いついて、実装したのが、Seasar2.4で追加した「Hot Deploy」の機能です。この機能は2006年5月にサンフランシスコで開催したJavaOne2006で講演したときにデモンストレーションを見せています。

ここを読んでいて、まさにJPAのTempClassLoaderってこれだよなと思いました。JPA(というかTopLink)がEntityクラスをクラスローダーに読み込ませる前にエンハンスする・・・という無理な仕組みを採用しているが故に、クラス情報を取得する為に一時的なClassLoaderが必要になります。
・・・ということは、TempClassLoaderにHotDeployClassLoaderを利用すれば、より汎用的になるのでは?・・・と考えました。
今までTopLinkの実装を利用していたTempClassLoader関係を、HotDeployClassLoaderを使うようにdiconファイルを修正してみました。すると・・・今まで動かなかったローカルアプリケーションでも、Web環境と同じ設定でTopLink EsesntialsのLAZYロードが動くようになりました!(昨日書いたTopLinkの問題があるので、アノテーションをgetterにつけないと動きませんが)。
おぉ凄い・・・これならローカル環境・Web環境関係なく同一設定で利用することができるし、javaagentを使う必要もありません。もっと早く気がつけばよかった・・・
(なお、ここに至る前に、Seasar2の方で、初期化処理に対する新機能を追加していただいてます。componentsのinitializeOnCreate属性をtrueにすると、S2がコンポーネントを読み込む前に特定diconファイルだけ初期化してくれるので、S2TopLinkの初期化設定が劇的に簡単になりました。どうもありがとうございます!)
しかし一点だけ問題がありまして、JUnit上ではうまく動きませんでした。

    public static void main(String[] args) {
        SingletonS2ContainerFactory.setConfigPath("org/seasar/toplink/jpa/service/impl/TestServiceImplTest.dicon");
        SingletonS2ContainerFactory.init();
        S2Container container = SingletonS2ContainerFactory.getContainer();
        TestService service = TestService.class.cast(container.getComponent(TestService.class));
        List<Product> list = service.getProductList();
        for (Product p : list) {
            System.out.println("ID:" + p.getId());
            System.out.println("NAME:" + p.getName());
            System.out.println("VERSION:" + p.getVersion());
            System.out.println("CUSTOMER_NAME:" + p.getCustomer().getName());
        }
    }

こう書くと上手く動きます。(TopLinkトランザクションの外からも遅延ロードするので、p.getCustomer()を読んだ時点でLAZYロードしてしまうというおまけつき(汗))
しかし、JUnit環境だと・・・

    public void testGetProductListTx() {
        List<Product> list = testService.getProductList();
        for (Product p : list) {
            System.out.println("ID:" + p.getId());
            System.out.println("NAME:" + p.getName());
            System.out.println("VERSION:" + p.getVersion());
            System.out.println("CUSTOMER_NAME:" + p.getCustomer().getName());
        }
    }

JUnit(S2TestCase)でこう書くと、for文でProductを取り出した時点で、ProductのClassCastExceptionが発生してしまいました。どうやら、TestクラスのロードをJUnitが行ってる関係で発生してるみたいです。うーむ、やはりJUnitだけは簡単には対応できなさそう・・・単体テスト環境では自動的にtoplink.weaving=false設定にするような仕掛けを考えた方がいいのかも。