使用EJB3.1进行logback [英] logback with EJB3.1
问题描述
我使用logback / slf4j来处理我的应用程序中的日志记录。在我开始使用EJB之前,一切都很完美。一旦我将无状态EJB添加到我的应用中,记录器就开始忽略我的logback.xml并停止使用我的appender。我切换到编程记录器配置,看看有什么不对,现在当我尝试在EJB中使用我的记录器时,出现以下错误:
org.slf4j.impl.JDK14LoggerFactory不能转换为ch.qos.logback.classic.LoggerContext
< 来源于行:
$ p $ LoggerContext lc =(LoggerContext)LoggerFactory.getILoggerFactory();
是否有任何必要的特殊配置让logback与EJB一起工作?如果有问题,我将在glassfish v3上进行部署。 解决方案
这看起来非常接近这个线程,我怀疑类似的类加载问题。由于logback加载 logback.xml
(更准确地说,它检索 ClassLoader
这样做的方式),它会可能在拾取其配置文件时失败并回退到默认的 BasicConfiguration
。
不知道如何打包代码,但建议的解决方法是在EAR库中包含 logback.xml
。如果您未使用EAR包装,请尝试确定用于查看放置 logback.xml
文件的类加载器。
最后,这可能是logback中的一个问题。虽然没有检查他们的问题跟踪器。
更新:如果您使用战争包装,请尝试配置GlassFish以便首先使用子类加载器在委托之前。在 sun-web.xml中
:
< sun-web -app>
< class-loader delegate =false/>
< / sun-web-app>
$ b
更新:我在我身边进行了一些测试,并且...我无法重现您的问题。我为Java EE 6 webapp创建了一个具有以下结构的项目:
$树示例
示例
| - pom.xml
` - src
` - main
| - java
| ` - com
| ` - stackoverflow
| ` - q2418355
| | - SimpleEJB.java
| ` - SimpleServlet.java
| - 资源
| ` - logback.xml
` - webapp
| - META-INF
| ` - MANIFEST.MF
| - WEB-INF
| ` - lib
` - index.jsp
我的pom.xml如下所示:
<?xml version =1.0encoding =UTF-8?>
< project xsi:schemaLocation =http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
xmlns =http://maven.apache.org/POM/4.0.0xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance>
< modelVersion> 4.0.0< / modelVersion>
< groupId> com.stackoverflow.q2418355< / groupId>
< artifactId>样本< / artifactId>
< version> 1.0-SNAPSHOT< / version>
<包装>战争< / packaging>
< name>示例Maven Webapp< / name>
< url> http://maven.apache.org< / url>
<依赖关系>
< dependency>
< groupId> javax< / groupId>
< artifactId> javaee-api< / artifactId>
< version> 6.0< / version>
< scope>提供< / scope>
< /依赖关系>
< dependency>
< groupId> junit< / groupId>
< artifactId> junit< / artifactId>
< version> 4.7< / version>
< scope> test< / scope>
< /依赖关系>
< dependency>
< groupId> ch.qos.logback< / groupId>
< artifactId> logback-classic< / artifactId>
< version> 0.9.18< / version>
< /依赖关系>
< dependency>
< groupId> org.slf4j< / groupId>
< artifactId> slf4j-api< / artifactId>
< version> 1.5.11< / version>
< /依赖关系>
< /依赖关系>
< build>
< plugins>
< plugin>
< groupId> org.apache.maven.plugins< / groupId>
< artifactId> maven-compiler-plugin< / artifactId>
< version> 2.0.2< / version>
<配置>
< source> 1.6< / source>
< target> 1.6< / target>
< / configuration>
< / plugin>
< plugin>
< groupId> org.apache.maven.plugins< / groupId>
< artifactId> maven-war-plugin< / artifactId>
< version> 2.1-beta-1< / version>
<配置>
< failOnMissingWebXml> false< / failOnMissingWebXml>
< / configuration>
< / plugin>
< / plugins>
< finalName>样本< / finalName>
< / build>
< / project>
SimpleEJB.java
的代码是:
package com.stackoverflow.q2418355;
import javax.ejb.Stateless;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
@Stateless
public class SimpleEJB {
private static Logger logger = LoggerFactory.getLogger(SimpleEJB.class);
public String sayHello(String name){
logger.debug(>> sayHello());
logger.debug(<<< sayHello());
返回Hello+名字+!!!;
SimpleServlet的代码。 java
是:
package com.stackoverflow.q2418355;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = {/ SimpleServlet})
公共类SimpleServlet扩展HttpServlet {
@EJB
SimpleEJB bean;
private static Logger logger = LoggerFactory.getLogger(SimpleServlet.class);
$ b @Override
public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException {
logger.debug(>> doGet());
PrintWriter out = response.getWriter();
out.println(< html>< body>);
out.println(< h2> Serving at:+ request.getContextPath()+< / h2>);
out.println(< h2> Invoking EJB:+ bean.sayHello(Duke)+< / h2>);
out.println(< / body>< / html>);
logger.debug(<< doGet());
index的代码。 jsp
是:
< html>
< body>
< h2> Hello World!< / h2>
通过点击< a href =SimpleServlet>在这里< / a>来调用Servlet。
< / body>
< / html>
我的 logback.xml
看起来像:
<配置>
< appender name =STDOUTclass =ch.qos.logback.core.ConsoleAppender>
< layout class =ch.qos.logback.classic.PatternLayout>
<模式>%d {HH:mm:ss.SSS} [%线程]%-5级别记录器{36} - %msg%n< / Pattern>
< / layout>
< / appender>
< appender name =FILEclass =ch.qos.logback.core.FileAppender>
< File> /tmp/logs/testFile.log< / File>
<追加>真< /追加>
< layout class =ch.qos.logback.classic.PatternLayout>
< Pattern>% - 4relative [%thread]%-5level%logger {35} - %msg%n< / Pattern>
< / layout>
< / appender>
< logger name =com.stackoverflow.q2418355level =TRACE/>
< appender-ref ref =STDOUT/>
< appender-ref ref =FILE/>
< / root>
< / configuration>
我的 logback.xml
当调用servlet时,我得到了以下跟踪(从我的日志文件中获取):
10913 [http-thread-pool-8080 - (1)] DEBUG com.stackoverflow.q2418355.SimpleServlet - >> doGet()
10928 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleEJB - >> sayHello()
10928 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleEJB - << sayHello()
10932 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleServlet - << doGet()
我也尝试将EJB打包在自己的JAR中,并部署在 WEB-INF / lib
并得到相同的结果,它只是起作用。你能发现任何明显的差异吗?也许上传一个简化版本的应用程序(很可能需要为bug报告BTW)。
我在Eclipse 3.5下运行GlassFish v3(使用GlassFish v3插件)。
I am using logback/slf4j to handle logging in my application. Everything was working perfectly until I started using EJBs. Once I added a stateless EJB to my app, the logger started ignoring my logback.xml and stopped using my appenders. I switched to a programmatic logger configuration to see what was wrong and now I am getting the following error when I try to use my logger within the EJB:
org.slf4j.impl.JDK14LoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
stemming from the line:
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
Is there any special configuration necessary to get logback to work with EJBs? If it matters I am deploying on glassfish v3.
This looks very close to the problem described in this thread and I suspect a similar class loading issue. Because of the way logback loads logback.xml
(more precisely the way it retrieves a ClassLoader
to do so), it may fail at picking up its configuration file and fall back on a default BasicConfiguration
.
Not sure how you package your code but the suggested workaround is to include the logback.xml
in a EAR lib. If you aren't using an EAR packaging, try to identify the class loader used to see where to put the logback.xml
file.
At the end, this might be a problem in logback. Didn't check their issue tracker though.
Update: If you use a war packaging, try to configure GlassFish to use firstly the child classloaders before to delegate. In the sun-web.xml
:
<sun-web-app>
<class-loader delegate="false"/>
</sun-web-app>
Update: I did a little test on my side and... I cannot reproduce your problem. I've created a project for a Java EE 6 webapp which has the following structure:
$ tree sample sample |-- pom.xml `-- src `-- main |-- java | `-- com | `-- stackoverflow | `-- q2418355 | |-- SimpleEJB.java | `-- SimpleServlet.java |-- resources | `-- logback.xml `-- webapp |-- META-INF | `-- MANIFEST.MF |-- WEB-INF | `-- lib `-- index.jsp
My pom.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stackoverflow.q2418355</groupId>
<artifactId>sample</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>sample Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.18</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<finalName>sample</finalName>
</build>
</project>
The code for SimpleEJB.java
is:
package com.stackoverflow.q2418355;
import javax.ejb.Stateless;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Stateless
public class SimpleEJB {
private static Logger logger = LoggerFactory.getLogger(SimpleEJB.class);
public String sayHello(String name) {
logger.debug(">> sayHello()");
logger.debug("<< sayHello()");
return "Hello " + name + "!!!";
}
}
The code for SimpleServlet.java
is:
package com.stackoverflow.q2418355;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = { "/SimpleServlet" })
public class SimpleServlet extends HttpServlet {
@EJB
SimpleEJB bean;
private static Logger logger = LoggerFactory.getLogger(SimpleServlet.class);
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.debug(">> doGet()");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h2>Serving at: " + request.getContextPath() + "</h2>");
out.println("<h2>Invoking EJB: " + bean.sayHello("Duke") + "</h2>");
out.println("</body></html>");
logger.debug("<< doGet()");
}
}
The code for index.jsp
is:
<html>
<body>
<h2>Hello World!</h2>
Invoke the Servlet by clicking <a href="SimpleServlet">here</a>.
</body>
</html>
And my logback.xml
looks like:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<File>/tmp/logs/testFile.log</File>
<Append>true</Append>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
</layout>
</appender>
<logger name="com.stackoverflow.q2418355" level="TRACE"/>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
My logback.xml
gets propertly loaded and I get the following trace (taken from my log file) when invoking the servlet:
10913 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleServlet - >> doGet()
10928 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleEJB - >> sayHello()
10928 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleEJB - << sayHello()
10932 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.SimpleServlet - << doGet()
I did also try with the EJB packaged in its own JAR and deployed in WEB-INF/lib
and get the same result, it just works. Can you spot any obvious difference? Maybe upload a simplified version of your app (will very likely be required for the bug report BTW).
I am running GlassFish v3 under Eclipse 3.5 (with the GlassFish v3 plugin).
这篇关于使用EJB3.1进行logback的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!