instance="session"でエラー発生

instance="session" or "request"にすると、以下のエラーが発生する。

[ERROR] 2005-10-02 19:23:03 StandardContext#loadOnStartup() サーブレット /hoge がload()例外を投げました
org.seasar.framework.exception.EmptyRuntimeException: [ESSR0007]sessionはnullあるいは空であってはいけません
	at org.seasar.framework.container.deployer.SessionComponentDeployer.deploy(SessionComponentDeployer.java:28)
	at org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:75)
	at org.seasar.framework.container.impl.S2ContainerImpl.getComponent(S2ContainerImpl.java:89)
	at org.seasar.framework.container.assembler.AutoPropertyAssembler.assemble(AutoPropertyAssembler.java:44)
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.assemble(SingletonComponentDeployer.java:47)
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.deploy(SingletonComponentDeployer.java:27)
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.init(SingletonComponentDeployer.java:55)
	at org.seasar.framework.container.impl.ComponentDefImpl.init(ComponentDefImpl.java:249)
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:344)
	at org.seasar.framework.container.factory.SingletonS2ContainerFactory.init(SingletonS2ContainerFactory.java:36)
	at org.seasar.framework.container.servlet.S2ContainerServlet.init(S2ContainerServlet.java:47)
	at javax.servlet.GenericServlet.init(GenericServlet.java:211)
〜(省略)〜

当然、web.xmlで

    <filter>
        <filter-name>s2filter</filter-name>
        <filter-class>org.seasar.framework.container.filter.S2ContainerFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>s2filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>s2servlet</servlet-name>
        <servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

という設定はしてますよ、はい。その辺りは抜かりなく。

実際、別のフィルタでS2Containerのrequest,response,sessionとういコンポーネント名でgetしてみると、ちゃんとオブジェクトは入ってるんです。
つーか、Tomcat起動時に上記のエラーが発生するんですよ。これが。


で、色々試した結果、大体見えてきた。

HogeLogicImplクラスの中で、UserImpl(インタフェースUser)をDIしたい場合に、

<components>
	<component name="user" class="hoge.entity.impl.UserImpl" instance="session" />
	<component class="hoge.logic.impl.HogeLogicImpl" instance="request" ></component>
</components>

という設定をすると、起動時にエラーは発生せず、実行も可能。

<components>
	<component name="user" class="hoge.entity.impl.UserImpl" instance="session" />
	<component class="hoge.logic.impl.HogeLogicImpl" instance="singleton" ></component>
</components>

のようにDI先コンポーネントがsingletonだと、起動時にエラー発生!


エラーメッセージから解析するのはとっても難しいけど、原因がわかった今となっては、そりゃそうだ、という感じかも。

つまり、

  • ライフサイクルがsingletonなコンポーネントHogeLogicImplは、起動時にインスタンス化されてコンテナに設定される。
  • その時点で、HogeLogicImplが必要なコンポーネントがDIされる。
  • その時点では、sessionなどないのでUserImplは取得できない。
  • エラー!!

というわけだ。

ま、そりゃそうだ。


でも、エラーメッセージがわかりづらいっす。検索してもぜんぜん情報ヒットしないし。
実際、マニュアルにも明示的には書いてないですよね。ふつーに気付けよッてことかしら?これにハマったのって僕だけ?


こういう設定上の制約は、機械的にチェックできるんで、kijimunaで警告してくれるようになると大変助かります。
…と、世界の隅っこでぼそっとつぶやいておこう。