J2EE準拠は実装の準拠ではない

希望通りのデプロイを選択できるようになったので、これでやっと使えると思ったのだが、デプロイ時に例外を吐いて上手くデプロイができない。

>deploy.bat --user xxxx --password xxxx deploy --inPlace c:\webapp
Using GERONIMO_BASE:   C:\geronimo-1.1.1
Using GERONIMO_HOME:   C:\geronimo-1.1.1
Using GERONIMO_TMPDIR: C:\geronimo-1.1.1\var\temp
Using JRE_HOME:        C:\javasoft\j2se1.6

org.apache.geronimo.kernel.config.LifecycleException: start of default/weapp/1.0/war failed
        at org.apache.geronimo.kernel.config.SimpleConfigurationManager.startConfiguration(SimpleConfigurationManager.java:544)
        at org.apache.geronimo.kernel.config.SimpleConfigurationManager.startConfiguration(SimpleConfigurationManager.java:508)
        at org.apache.geronimo.kernel.config.SimpleConfigurationManager$$FastClassByCGLIB$$ce77a924.invoke()
        at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53)
        at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38)
        at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:122)
        at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:852)
        at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:239)
        at org.apache.geronimo.kernel.KernelGBean.invoke(KernelGBean.java:338)
        at org.apache.geronimo.kernel.KernelGBean$$FastClassByCGLIB$$1cccefc9.invoke()
:
:
以下略
:
        ... 36 more

原因をいろいろ調べたが、ぜんっぜん解らない。スタックトレースから察するに設定関係であろうという当たりは付くのだが、それ以上はさっぱりだ。

仕方が無いので最後の手段でweb.xmlを一行ずつ追加して行き、どの行を追加した段階でデプロイが失敗するかを調べることにした。原始的な方法ではあるが、最も確実な方法でもある。
web.xmlが怪しいと踏んだのは、このファイルを解釈するプログラミング(パースのロジック、内部への格納ロジック等)はアプリケーションサーバによりまちまちであり、厳密に統一されたファイルが書けないことが過去の経験から明らかになっているからである。(DTDの検証すら行わないサーバもある)
これがビンゴだった。Apache Geronimo 1.1.1はweb.xmlのコンテキスト初期化パラメタのパラメタ名が重複するような記述だとデプロイヤが例外を吐き処理を継続できないようだ。例えば以下のようなweb.xmlがあったとする。

    <context-param>
        <param-name>PagingThreshold</param-name>
        <param-value>25</param-value>
    </context-param>
    <context-param>
        <param-name>PagingThreshold</param-name>
        <param-value>25</param-value>
    </context-param>

このように書いた時点でデプロイシーケンスが中断されて、上述したスタックトレースとなる訳だ。普通に考えると、パース時にエラーにするか、せめて「キーが重複している」位の警告を出して、重複しているパラメタは読み飛ばせば良いとも思うのだが、その辺が柔軟では無いようだ。この、エラーとなったweb.xmlは他のアプリケーションサーバでは問題なくデプロイ、実行できていたのでまさかパラメタに重複があるなぞ思いもしなかったのだ。(まあ、元を正せば問題のあるweb.xmlで動いていたアプリケーションサーバのロジックに問題があるとも言える)

以上のようにJavaアプリケーションサーバは実装自体はベンダやOSSに任されている訳で、J2EE準拠だからといって設定ファイルのパース、バリデーションのロジックや内部オブジェクトの格納方法まで同じである保障は全く無い、というかこの辺はアプリケーションサーバ毎に固有な処理である、と考えたほうが利口である。