SLF4J を使う
Hibernate のバージョンを 3.3 に上げたら、ロギングフレームワークが SLF4J に変わっていた。そのまま実行しようとすると以下のエラーが出た。
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J ではどのログ実装を使うかという指定を StaticLoggerBinder というクラスで静的に行うようだ。たとえば Log4J を使うなら Log4J 用の StaticLoggerBinder クラスを配置する。それぞれのログ実装毎に異なる StaticLoggerBinder クラスが用意されている。
これは commons-logging と比べると設定の柔軟性には欠けるのだけど、より安全であり問題が発生しにくいということらしい。実際そこまでの柔軟性は必要ないのでこれでなんら不都合はない。Hibernate を始め多くのプロジェクトが SLF4J に移行しているようだ。
そこで StaticLoggerBinder 実装を組み入れることにする。本当はこのタイミングでログ実装も LOGBack に変えてしまうのがいいのかもしれないけども、まだ同一プロジェクト内で commons-logging + Log4J を使っているところも多いので、とりあえず Log4J のまま使うことにした。Maven リポジトリを検索して、以下の dependency を追加する。
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.6</version> </dependency>
これで行けるだろうと思ったら、今度は以下のエラーが出た。
java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
これは slf4j-api とのバージョンのミスマッチが問題のようだ。hibernate 3.3 の依存ライブラリとして読み込まれた slf4j-api は 1.4.2 だったので、slf4j-log4j12 も 1.4.2 を使うようにした。
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.4.2</version> </dependency>
これで問題無くアプリケーションが実行できるようになった。