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>

これで問題無くアプリケーションが実行できるようになった。