使用EJB3.1进行logback

我正在使用logback / slf4j来处理我的应用程序中的日志记录。 在我开始使用EJB之前,一切都运行良好。 一旦我将无状态EJB添加到我的应用程序,记录器就开始忽略我的logback.xml并停止使用我的appender。 我切换到程序化记录器配置以查看错误,现在当我尝试在EJB中使用我的记录器时,我收到以下错误:

org.slf4j.impl.JDK14LoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext

来自这条线:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

是否需要任何特殊配置才能使回归与EJB一起使用? 如果重要的话,我正在使用glassfish v3进行部署。

这看起来非常接近此线程中描述的问题,我怀疑类似的类加载问题。 由于logback加载logback.xml的方式(更确切地说是它检索ClassLoader的方式),它可能无法获取其配置文件并回退到默认的BasicConfiguration

不确定如何打包代码,但建议的解决方法是将logback.xml包含在EAR库中。 如果您没有使用EAR打包,请尝试识别用于查看logback.xml文件放置位置的类加载器。

最后,这可能是回归中的问题。 但是没有检查他们的问题跟踪器。

更新:如果您使用war包装,请尝试将GlassFish配置为在委托之前首先使用子类加载器。 sun-web.xml

    


更新:我在我身边做了一点测试……我无法重现你的问题。 我已经为Java EE 6 webapp创建了一个项目,它具有以下结构:

 $ tree sample
样品
 |  -  pom.xml
 ` -  src
     ` - 主要
         |  -  java
         |  ` -  com
         |  ` -  stackoverflow
         |  ` -  q2418355
         |  |  -  SimpleEJB.java
         |  ` -  https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/SimpleServlet.java
         |  - 资源
         |  ` -  logback.xml
         ` -  webapp
             |  -  META-INF
             |  ` -  MANIFEST.MF
             |  -  WEB-INF
             |  ` -  lib
             ` -  index.jsp

我的pom.xml看起来像:

   4.0.0 com.stackoverflow.q2418355 sample 1.0-SNAPSHOT war sample Maven Webapp http://maven.apache.org   javax javaee-api 6.0 provided   junit junit 4.7 test   ch.qos.logback logback-classic 0.9.18   org.slf4j slf4j-api 1.5.11      org.apache.maven.plugins maven-compiler-plugin 2.0.2  1.6 1.6    org.apache.maven.plugins maven-war-plugin 2.1-beta-1  false    sample   

SimpleEJB.java的代码是:

 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 + "!!!"; } } 

https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/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 = { "/https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/SimpleServlet" }) public class https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/SimpleServlet extends HttpServlet { @EJB SimpleEJB bean; private static Logger logger = LoggerFactory.getLogger(https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/SimpleServlet.class); @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { logger.debug(">> doGet()"); PrintWriter out = response.getWriter(); out.println(""); out.println("

Serving at: " + request.getContextPath() + "

"); out.println("

Invoking EJB: " + bean.sayHello("Duke") + "

"); out.println(""); logger.debug("<< doGet()"); } }

index.jsp的代码是:

   

Hello World!

Invoke the Servlet by clicking here.

我的logback.xml看起来像:

    %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n    /tmp/logs/testFile.log true  %-4relative [%thread] %-5level %logger{35} - %msg%n         

我的logback.xml被加载logback.xml ,并在调用servlet时得到以下跟踪(取自我的日志文件):

 10913 [http-thread-pool-8080-(1)] DEBUG com.stackoverflow.q2418355.https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/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.https://stackoverflow.com/questions/2418069/logback-with-ejb3-1/SimpleServlet - << doGet() 

我也尝试将EJB打包在自己的JAR中并部署在WEB-INF/lib并得到相同的结果,它只是起作用。 你能发现任何明显的差异吗? 也许上传你的应用程序的简化版本(很可能是错误报告BTW所必需的)。

我在Eclipse 3.5(使用GlassFish v3插件)下运行GlassFish v3。

org.slf4j.impl.JDK14LoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContextexception显示SLF4J未绑定到logback-classic而是绑定到slf4j-jdk14。 简而言之,回归代码不应该受到责备,因为它没有被执行也没有被调用。

看起来GFv3正在将slf4j-jdk14.jar导出到您的应用程序中,从而覆盖了您选择的日志后端,在这种情况下是logback。 这是app服务器无意中对用户施加选择的场景之一。

如果GFv3确实对最终用户施加了SLF4J绑定,那么这是一个必须由GFv3开发人员解决的GFv3问题。 我可能错了,但我认为他们假设最终用户不希望任何其他日志记录function超出java.util.logging提供的function,只需在GFv3中捆绑slf4j-jdk14。 用户需要联系他们并抱怨他们的假设不正确。 他们也有可能意识到这个问题并且已经提供了解决方法……

基本上问题是应用程序服务器使用提供slf4j并且您尝试使用它会转到应用程序服务器slf4j绑定而不是您自己想要的绑定。

你不能只在Glassfish中使用slf4j绑定吗?

这里几乎是完全相关的代码:

登录EJB:

 @Stateless @Interceptors(LoggingInterceptor.class) public class LoginEJB { @PersistenceContext(unitName = "persistence") private EntityManager em; public User getUser(String username) { try { Query query = em.createQuery("Select u from User u where u.userName = '" + username + "'"); User user = (User) query.getSingleResult(); return user; } catch (NoResultException e) { return null; } } } 

我的日志代码所在的拦截器:

 import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LoggingInterceptor { private Logger logger = LoggerFactory.getLogger(this.getClass()); @AroundInvoke public Object logMethod(InvocationContext ic) throws Exception { logger.info("[{}] Entering - {}()", ic.getTarget().toString() , ic.getMethod().getName()); try { return ic.proceed(); } finally { logger.info("[{}] Exiting - {}()", ic.getTarget().toString() , ic.getMethod().getName()); } } } 

logback.xml

    %d{HH:mm:ss.SSS} [%-5level] [%logger{36}] - %msg%n    c:\ItamLogs\log.txt  c:\ItamLogs\Archive\log-%d{yyyy-MM-dd}.txt   [%-5level] - %d{HH:mm:ss.SSS} [%logger{35}] - %msg%n           

jsf2.0支持bean。

 @ManagedBean public class LoginBacking extends AbstractBacking { @NotEmpty(message = "User Name required.") private String username; @NotEmpty(message = "Password required.") private String password; @EJB private LoginEJB loginEJB; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String performLogin() { String result = "login"; User user = loginEJB.getUser(username); if(null == user || !user.getPassword().equals(password)) { this.getFacesContext().addMessage("login-form:button-submit", new FacesMessage("The User Name or Password entered is incorrect.")); return result; } this.setCurrentUser(user); result = "success"; return result; } } 

我有一个jsf页面

    

最后我的pom

  4.0.0 com.test tester 1.0/version> Code war   maven2-repository.dev.java.net Java.net Repository for Maven http://download.java.net/maven/2/    codecaus codehaus http://repository.codehaus.org    ibiblio http://www.ibiblio.org/maven2/   jboss http://repository.jboss.com/maven2  true   false    jboss-snapshot http://snapshots.jboss.org/maven2  true   true    java.net.glassfish Repository hosting the jee6 artifacts http://download.java.net/maven/glassfish     jboss-plugins http://repository.jboss.com/maven2  true   false    jboss-snapshot-plugins http://snapshots.jboss.org/maven2  true   true      javax.faces jsf-api 2.0 provided   javax.servlet servlet-api 2.5 provided   javax.el el-api 1.0 provided   javax.validation validation-api 1.0.0.GA   org.glassfish bean-validator 3.0-JBoss-4.0.0.Beta3   org.glassfish.extras glassfish-embedded-all 3.0 test   javax javaee-api 6.0-SNAPSHOT   junit junit 4.7   javax.faces jsf-api 2.0 provided    org.hibernate hibernate-core 3.5.0-CR-2   org.hibernate hibernate-annotations 3.5.0-CR-2   org.hibernate hibernate-commons-annotations 3.2.0.Beta1   org.hibernate hibernate-entitymanager 3.5.0-CR-2   org.hibernate hibernate-c3p0 3.5.0-CR-2   postgresql postgresql 8.4-701.jdbc4    ch.qos.logback logback-core 0.9.18   ch.qos.logback logback-classic 0.9.18   org.slf4j slf4j-api 1.5.11   org.eclipse.persistence javax.persistence 2.0.0    gfv3ee6      org.apache.maven.plugins maven-compiler-plugin  1.6 1.6    org.apache.maven.plugins maven-war-plugin 2.0      org.apache.maven.plugins maven-war-plugin 2.0     

编辑:我也尝试将我的记录器更改为静态,无变化。