MyFaces1.1.0とcommons-loggingとWebSphere6.0


ちょっと用事があってMyFaces1.1.0とcommons-loggingを使ったアプリケーション(Tomcat4.1.31で動作確認済)をWebSphere6.0(RAD6.0試用版付属のもの)に乗っけてみたのだが、WebSphereをいじったことがなかったので思いのほか苦労した。


せっかくなのでメモを残しておく。
実施した方法は以下の2つ。どちらも適当に調べたものなので動作保証はしない。

【方法1.WebSphereの一部ライブラリ無効化】

1.以下の2つのファイルの拡張子を変更し、jarとして読み込まれないようにする。
IBM/Rational/ADTrial/6.0/runtimes/base_v6/lib/jsf-api.jar
IBM/Rational/ADTrial/6.0/runtimes/base_v6/lib/ws-jsf.jar
2.サーバーを立ち上げ、以下のURLから管理コンソールにアクセスする(ユーザIDは適当で良い)。
http://hostname:9060/ibm/console/
3.当該アプリケーション・サーバーの「クラス・ローダー・ポリシー」が「複数(MULTIPLE)」になっていることを確認する。

※この設定により、個々のクラス・ローダーが設定できるようになる。

4.当該エンタープライズ・アプリケーションの「クラス・ローダー・モード」が「親が最初(PARENT_FIRST)」、「WARクラス・ローダー・ポリシー」が「モジュール(MODULE)」になっていることを確認する。

※ここをPARENT_LASTにすると方法2のようにcommons-logging用の設定が必要になる。

5.当該Webモジュールの「クラス・ローダー・モード」が「親が最初(PARENT_FIRST)」になっていることを確認する。

※ここをPARENT_LASTにすると方法2のようにcommons-logging用の設定が必要になる。

6.当該アプリケーションをWAR化し、管理コンソールで配備する。

※以上で完了。ただし、WebSphereのライブラリを無効化しているため、ちょっと心配。一応、JSF周りのライブラリなので大丈夫だと思うが……。

【方法2.クラス・ローダー読み込み順序変更】

1.サーバーを立ち上げ、以下のURLから管理コンソールにアクセスする(ユーザIDは適当で良い)。
http://hostname:9060/ibm/console/
2.当該アプリケーション・サーバーの「クラス・ローダー・ポリシー」が「複数(MULTIPLE)」になっていることを確認する。

※この設定により、個々のクラス・ローダーが設定できるようになる。

3.当該エンタープライズ・アプリケーションの「クラス・ローダー・モード」を「親が最後(PARENT_LAST)」に変更し、「WARクラス・ローダー・ポリシー」が「モジュール(MODULE)」になっていることを確認する。

※ここでクラス・ローダーの読み込み順序を反転し、WebSphereのJSFライブラリよりも前にWARのJSFライブラリを読むようにしている。

4.当該Webモジュールの「クラス・ローダー・モード」を「親が最後(PARENT_LAST)」に変更する。

※ここでクラス・ローダーの読み込み順序を反転し、WebSphereのJSFライブラリよりも前にWARのJSFライブラリを読むようにしている。

5.サーバーの「/profiles//properties/」に「commons-logging.properties」を作成し、以下の1行を書き込む。
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl

※これはPARENT_LASTにしたために必要になる設定。WebSphereにはcommons-loggingを拡張したjarが存在しており、その中にcommons-logging.propertiesがある。ここにLogFactoryの実装としてWebSphere固有のTrLogFactoryを使うような設定があるため、これをLogFactoryImplに差し替えないとWAR側に存在しないTrLogFactoryを参照しにいってエラーが発生する。
※本来であればサーバー側に設定せずにWARの「META-INF/services」に設定すれば良い(参考4参照)はずだが、バグなのか仕様なのか、WebSphere6.0ではサーバー側への設定が必要(参考1参照)になる。

6.当該アプリケーションから「jsp-2.0.jar」と「jta.jar」を削除する(S2DAOを使ってるのでjta.jarが入ってる)。

※「jsp-2.0.jar」はJSP1.2環境で動作させる場合に必要だが、WebSphereはJSP2.0なので不要。
jta.jar」は「javax.transaction.xa.XAResource」がWebSphereの同名クラスと競合するので削除する。
PARENT_FIRSTの場合はこれらを削除しなくてもWebSphereのものが先に読み込まれるので問題ないが、PARENT_LASTの場合は消しておかなければならない。
これら以外にも衝突するものがあれば削除する必要がある。
(自分の場合、実際に衝突するかどうかはクラスを洗い出すか実際に当該クラスを呼んでみないと分からなかった)

7.前項で修正したPersonaPart1SampleをTomcatPluginのWAR生成コマンドでまるごとWAR化し、管理コンソールで配備する。

※以上で完了。方法1よりかは妥当な方法であるが、方法1の影響範囲がJSFに限られていたのに比べ、方法2の方が影響範囲が広くなるため、一概にどちらが良いかは判断できない。