ハマったのでメモ。
はじめに
アプリケーションサーバのようにクラスローダに親子がある環境では、親でロードされたクラスが優先されてしまい、各アプリケーションに配置したクラスが実行時に利用できないといった事が起こる。
起こりえる問題
例えば、 Weblogic 10.3.3 では、 Weblogic 自身が apache-commons-lang の ver 2.1 をロードしている。
この Weblogic に、 apache-commons-lang の ver 2.6 を使用した以下のような実装を持つ Web アプリを配備したとする。
logger.info("parameter : " + StringUtils.join(paramList, ","));
WEB-INF/lib
にしっかりと jar を配置していても、この Web アプリは実行時に StringUtils.join(paramList, ",")
の部分で NoSuchMethodError
が発生してしまう。
これは、 Weblogic が既にロードしていた ver 2.1 の StringUtils に join(Collection, String)
が存在しないのが原因(当該メソッドは ver 2.3 から実装されている)。
対処方法
このエラーを防ぐには、各 Web アプリでロードされたクラスを優先するように設定する必要がある。
Weblogic では、 WEB-INF
フォルダの直下に weblogic.xml
という XML ファイルを配置し、 prefer-web-inf-classes
に true
を指定すればいい。
<?xml version="1.0" encoding="UTF-8" ?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
...
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
...
</weblogic-web-app>
prefer-web-inf-classes
に true
を指定すると、 WEB-INF
以下のクラスが優先して使用されるようになり、前述の問題が発生しなくなる。
特定のパッケージだけを優先する方法もあるっぽい。