使用嵌入式Jetty和Tapestry进行日志记录

时间:2013-09-16 09:34:31

标签: log4j jetty slf4j tapestry embedded-jetty

我有一个使用Tapestry框架的war web应用程序。它使用slf4j + log4j并且运行良好。

我还有一个带有嵌入式jetty 8的简单服务器应用程序,我用它来部署战争。

我也想在服务器中使用slf4j + log4j。

因此我将slf4j和log4j依赖项添加到我的服务器pom.xml:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

我明白了:

SLF4J: Class path contains multiple SLF4J bindings.<br/>
SLF4J: Found binding in [jar:file:/tmp/jetty-0.0.0.0-8080-web-app-0.0.1.war-_-any-/webapp WEB-INF/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/martin/monitoring-gui/trunk/release/target/release-0.0.1-webgui-distribution/release-0.0.1/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

足够公平,Tapestry依赖项自动包含slf4j-log4j12log4j。所以我将以下内容添加到我的webapp pom.xml tapestry-core部分:

<exclusions>  
    <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
    </exclusion>

    <exclusion>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
    </exclusion>
</exclusions>

现在,实际的绑定和记录器应该只出现在服务器应用程序中。 但是,在服务器启动时,我得到:

Exception in thread "main" java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for resolved class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type taticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory; used in the signature
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:299)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:269)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:281)
at org.apache.tapestry5.TapestryFilter.<init>(TapestryFilter.java:56)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.eclipse.jetty.servlet.ServletContextHandler$Context.createFilter(ServletContextHandler.java:1051)
at org.eclipse.jetty.servlet.FilterHolder.doStart(FilterHolder.java:104)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:763)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:265)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1242)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:717)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:494)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95)
at org.eclipse.jetty.server.Server.doStart(Server.java:282)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
...

一直到我的码头Server.start()调用;

我错过了什么?

3 个答案:

答案 0 :(得分:1)

您有依赖性问题。我不是一直使用排除,而是看到依赖树并重新排序pom.xml中的标记。这里的规则表明依赖的第一次出现获胜。因此,当您希望另一个省略继承的依赖项时,只需将依赖项标记移动到您希望省略继承的依赖项之前。

这使得pom更具可读性,并且还控制使用树中依赖项的版本。在极少数情况下,我必须使用标签。

答案 1 :(得分:0)

问题是你的类路径上有两个版本的slf4j-log4j12。从它的外观来看,你正在设法排除旧版本而不是旧版本。 Slf4j抱怨说它期待的版本比它找到的版本更新。

在我看来,1.6.1版本通过您的嵌入式jetty服务器进入您的类路径。您是否也通过maven设置了码头依赖性?如果是这样,请将exclude添加到您的jetty依赖项中。无论哪种方式,您都需要检查类路径并以某种方式解决冲突的版本

答案 2 :(得分:0)

好的,感谢joostschouten和user2424794的帮助。我已经开始工作了。

mvn dependency:tree显示,其他网络应用的依赖关系:qpid-client为战争导入了另一个slf4j-api。 因此,另一项排除是必要的:

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-client</artifactId>
    <version>0.22</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

为了记录,tapestry-core依赖:

<dependency>
    <groupId>org.apache.tapestry</groupId>
    <artifactId>tapestry-core</artifactId>
    <version>${tapestry-release-version}</version>
    <exclusions>  
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

剩下的唯一问题是战争不会在没有slf4j-api的情况下编译,因此我将其添加为编译的战争依赖,而不是链接 - maven的provided范围:

<dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.7.5</version>
     <scope>provided</scope>
</dependency>

当然,slf4j-apislf4j-log4j12log4j被添加为服务器的依赖项,并将其“提供”给war应用程序。

现在一切都编译,运行和记录就好了。