WAS + Commons Logging + Log4J問題まとめ

2年くらい前のプロジェクトで起きた問題がまた浮上してきそうなので、メモ。

事象

WebSphere Application Server V5 or 6上で、
org.apache.commons.logging.LogFactory.getLog(Class)を使うと、org.apache.commons.logging.LogConfigurationExceptionが発生する(らしい)

直接の原因

LogFactoryの実装として、com.ibm.ws.commons.logging.TrLogLogFactoryが選択されるが、TrLogLogFactoryはLogFactoryを継承していない。

原因

ws-commons-logging.jar内のcommons-logging.propertiesの以下の記述が原因。


org.apache.commons.logging.LogFactory=com.ibm.ws.commons.logging.TrLogFactory
WAS本体を読み込むWebSphere EXTクラスローダーの方が、アプリケーション・クラスローダーやその下のWARクラスローダーより先に読み込まれるため、上記の設定の方がWar内のcommons-logging.propertiesより優先される。

対策1:クラスローダーの解決順を変える

  • WARクラスローダーのデリゲーション・モード(Delegation Mode)をPARENT FIRSTからPARENT LASTに変更する
    • 自クラスローダーのローカル・クラスパスを最初に探すようになる。

これでアプリケーション内の設定が優先されてるはず。

対策2:システムプロパティでLog4jFactoryを指定

org.apache.commons.logging.LogFactoryシステム・プロパティーで、org.apache.commons.logging.impl.Log4jFactoryを指定する。

IBMの資料(http://www-06.ibm.com/jp/domino01/mkt/websphere.nsf/499721c3388537bd49256b1a001aab28/49256dcd0019653049256f8f00584831/$FILE/Logger.pdf p.3)でも非推奨になっているので、やらない方が良い。
システムプロパティについては、hellohiro.comを参照

対策3:WARのMETA-INF/services/org.apache.commons.logging.LogFactoryで指定

META-INF/servicesに、org.apache.commons.logging.LogFactoryという適当なファイルを作って、1行目でorg.apache.commons.logging.impl.Log4jFactoryを指定する。

対策4:ws-commons-logging.jar内のcommons-logging.propertiesを修正

対策1 or 3で十分。やらない方がいい。

追記

WebSphere+commons-logging+log4jは使い物にならないによると、上記以外に、出力ログパターンによって処理性能が著しく低下するという現象があるらしい。
こっちの対策は見つかってなさげ。

そもそも調べようと思った理由

S2LoggerはCommons Loggingを使ってるみたいなので、要件が変わったときに面倒かなぁと思って。