Как подключить Log4j2 в Spring 4
Итак, Хьюстон Spring, у нас проблема.
В свой проект я решил подключить логирование (внезапно, да?) с использованием Log4j. Зашёл я к ним на сайт, посмотрел, что появилась новая версия Log4j – version 2, и добавил её в maven dependency. Но была проблема – логи не писались. Вообще никуда и никакие. Сначала думал, что не правильная конфигурация Log4j2, потому что консоль ругалась постоянно на:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. |
Да и какие-никакие логи (от hibernate, например) – шли, укрепляя мою уверенность в кривую конфигурацию. А что там делает SLF4J, которого у меня в POM-файлах в помине нет я как-то не успевал задуматься :)
А через какое-то время стало не до логов (ведь всегда есть дебаг под рукой) и я перестал обращать на это внимание. Но потом всё вернулось к логированию снова. Столкнулся с проблемой, что REST контроллер не хотел принимать @RequestBody объекты. Постоянно ругался ошибкой 400 Bad Request. Понятно, что проблема в отправляемых данных, но вот где именно – одним дебагом было не обойтись, а помнить все классы, в которых происходит маппинг JSON в объекты или где обрабатываются методы помеченные аннотацией @RequestMapping – довольно сложно :)
Пришлось снова возвращаться к проблеме логирования. К слову – конфигурация Log4j2 была описана предельно простая:
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <File name="file" fileName="log4j2.log" append="true"> <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> </File> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <Appender-ref ref="file"/> <Appender-ref ref="console"/> </Root> <Logger name="org.springframework.web" level="debug"> <Appender-ref ref="file"/> <Appender-ref ref="console"/> </Logger> </Loggers> </Configuration> |
Как видно – для всего Spring Web MVC установлен уровень DEBUG. Но – тишина. В Google – тишина. Потом я обратил внимание, ведь при запуске ругается на SLF4J, которого у меня в помине нет! Решил добавить мост для SLF4J в maven.
После чего стали происходить различные чудеса. Чаще всего это были ClassNotFoundException:
Failed to instantiate SLF4J LoggerFactory Reported exception: java.lang.NoClassDefFoundError: org/apache/logging/log4j/spi/AbstractLoggerAdapter |
И прочие подобные. Через какое-то время я дошёл до ошибки:
java.lang.NoClassDefFoundError: org/apache/log4j/LogManager |
И тут до меня дошло. Spring 4 использует SLF4J, который использует Log4j первой версии.
Дальше были попытки заставить использовать SLF4J вторую версию, но не получилось. В итоге, благодаря статье в блоге одного индусского программиста (печально, да? :) ) я нашёл как запретить из Spring 4 использование SLF4J. Но это было решение для Gradle, а у меня maven.
В maven можно запретить использовать зависимости, которые могут подтягивать подключаемые зависимости (взрыв мозга). Но глобального exclusion нету. Зато есть отличный обходной путь. Нужно добавить необходимые зависимости с областью видимости provided. Что не будет копировать их в папку lib:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> <scope>provided</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> <scope>provided</scope> </dependency> |
Обратите внимание, что версии я брал для своей версии Spring – 4.1.1.RELEASE.
Пересобираем, чистим папки временных файлов и данных вашего веб-сервера, чтобы там не осталось лишнего и радуемся:
2015-01-20 15:57:16,223 DEBUG [RMI TCP Connection(3)-127.0.0.1] env.MutablePropertySources (MutablePropertySources.java:111) - Adding [servletConfigInitParams] PropertySource with lowest search precedence 2015-01-20 15:57:16,223 DEBUG [RMI TCP Connection(3)-127.0.0.1] env.MutablePropertySources (MutablePropertySources.java:111) - Adding [servletConfigInitParams] PropertySource with lowest search precedence 2015-01-20 15:57:16,224 DEBUG [RMI TCP Connection(3)-127.0.0.1] env.MutablePropertySources (MutablePropertySources.java:111) - Adding [servletContextInitParams] PropertySource with lowest search precedence |
1 комментарий
[…] Вернёмся к нашим проблемам логирования при использовании новой версии библиотеки Log4j2. Ранее мы разобрались, как заставить использовать библиотеку Log4j2 в Spring 4. […]