任务jettyRunWar与slf4j和log4j导致错误。如何使用log4j进行日志记录?

时间:2016-08-16 03:47:55

标签: gradle log4j jetty slf4j

我正在开发一个新项目并尝试首次使用Gradle。该应用程序是一个Web应用程序,因此我在war的顶部配置了jettygradle.build个插件:

apply plugin: 'war'
apply plugin: 'jetty'

在我的代码中,我编程到Apache Commons Logging API进行日志记录。我的一个依赖项(OpenSAML)使用SLF4J API进行日志记录。对于实际的日志记录配置,我最熟悉log4j 1.2,因此我想用它来实际执行日志记录。

要配置这些依赖项,我在gradle.build文件中有以下内容:

// Logging API
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'
compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.21'

// Logging at runtime
runtime group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.21'
runtime group: 'log4j', name: 'log4j', version: '1.2.17'

当我使用命令gradle jettyRunWar运行我的应用程序并且servlet执行尝试记录某些内容时,我收到以下错误:

java.lang.ExceptionInInitializerError
    at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:72)
    at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:45)
    at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
    at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
    at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
    at sso.HomePageServlet.<clinit>(HomePageServlet.java:23)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at java.lang.Class.newInstance(Class.java:442)
    at org.mortbay.jetty.servlet.Holder.newInstance(Holder.java:153)
    at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:428)
    at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:440)
    at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
    at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
    at org.slf4j.impl.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:54)
    ... 33 more

错误显然是log4j-over-slf4j.jar也在类路径中。我的申请没有列出这个。使用gradle dependencies --configuration runtime也不会列出此.jar文件。此.jar存在的唯一位置是gradle\lib目录。启动Jetty时,Gradle是否可能包含自己的类路径?

有没有办法阻止这种情况?

概述here的解决方案似乎不起作用。

gradle -v显示:

------------------------------------------------------------
Gradle 2.14.1
------------------------------------------------------------

Build time:   2016-07-18 06:38:37 UTC
Revision:     d9e2113d9fb05a5caabba61798bdb8dfdca83719

Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_45 (Oracle Corporation 25.45-b02)
OS:           Windows 7 6.1 amd64

2 个答案:

答案 0 :(得分:4)

在发布我的问题后,我看到Gradle 3.0已被释放。在发行说明中,它表示已弃用jetty插件,并且应使用Gretty

升级到Gradle 3.0并切换到使用Gretty解决了问题。

jetty插件在您的网络应用中包含Gradle的类路径这一事实&#39;运行时路径是jetty插件工作方式的问题,看起来它不会被修复。

答案 1 :(得分:0)

我知道这已经几年了,版本太晚了,但是为了完全关闭,我确认内部gradle日志正在干扰。我的日志包括以下内容:

SLF4J: Found binding in [jar:file:/**/.gradle/**/gradle-2.14.1/lib/gradle-logging-2.14.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/**/build/tmp/jettyRunWar/webapp/WEB-INF/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]

gradle-logging-2.14.1.jar 包含有问题的 org.apache.log4j.Log4jLoggerFactory 类。

变通

由于我们要处理的是遗留的整体式多项目构建,因此我们还没有准备好提高gradle版本的安全性(一个人就好了)。当依赖项 slf4j-log4j12 从版本 1.7.2 更新到 1.7.25 时,我们遇到了这个问题(我们做得还不够好)单独)。对于我们来说,解决方案是在添加检查之前将其降低到版本 1.7.13