[英]logback with EJB3.1
我正在使用logback / slf4j處理應用程序中的日志記錄。 在我開始使用EJB之前,一切都運行良好。 將無狀態EJB添加到我的應用程序后,記錄器開始忽略我的logback.xml,並停止使用附加程序。 我切換到編程式記錄器配置以查看出了什么問題,現在當我嘗試在EJB中使用記錄器時遇到以下錯誤:
org.slf4j.impl.JDK14LoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
源於這一行:
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
是否需要任何特殊的配置才能使Logback與EJB一起使用? 如果有問題,我將在glassfish v3上進行部署。
這看起來非常接近此線程中描述的問題,我懷疑存在類似的類加載問題。 由於logback加載logback.xml
的方式(更准確地說,是它檢索ClassLoader
的方式),因此它可能無法獲取其配置文件並使用默認的BasicConfiguration
。
不確定如何打包代碼,但是建議的解決方法是在EAR lib中包含logback.xml
。 如果您不使用EAR包裝,請嘗試識別用於查看logback.xml
文件放置位置的類加載器。
最后,這可能是登錄后的問題。 不過沒有檢查他們的問題跟蹤器。
更新:如果使用戰爭包裝,請嘗試將GlassFish配置為在委托之前先使用子類加載器。
在
sun-web.xml
:
<sun-web-app> <class-loader delegate="false"/> </sun-web-app>
更新:我做了一些測試,但是...我無法重現您的問題。 我已經為Java EE 6 Webapp創建了一個項目,該項目具有以下結構:
$ 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
我的pom.xml看起來像:
<?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>
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 + "!!!";
}
}
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" })
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()");
}
}
index.jsp
的代碼是:
<html>
<body>
<h2>Hello World!</h2>
Invoke the Servlet by clicking <a href="SimpleServlet">here</a>.
</body>
</html>
我的logback.xml
看起來像:
<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>
logback.xml
加載了我的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
並獲得相同的結果,它可以正常工作。 你能發現明顯的不同嗎? 也許上傳您的應用程序的簡化版本(錯誤報告BTW非常可能需要)。
我正在Eclipse 3.5(帶有GlassFish v3插件)下運行GlassFish v3。
org.slf4j.impl.JDK14LoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
異常,這表明SLF4J並非綁定至經典的logback,而是綁定至slf4j-jdk14。 簡而言之,不要責怪登錄代碼,因為它沒有被執行或調用。
看起來GFv3正在將slf4j-jdk14.jar導出到您的應用程序中,因此覆蓋了您選擇的日志記錄后端(在這種情況下為logback)。 這是應用服務器無意中將其選擇強加給用戶的情況之一。
如果確實GFv3將SLF4J綁定強加給最終用戶,那么這就是GFv3問題,必須由GFv3開發人員解決。 我可能是錯的,但我認為他們認為最終用戶將不希望使用java.util.logging提供的任何其他日志記錄功能,而不會在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
<configuration scan="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%-5level] [%logger{36}] - %msg%n</Pattern>
</layout>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>c:\ItamLogs\log.txt</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>c:\ItamLogs\Archive\log-%d{yyyy-MM-dd}.txt</FileNamePattern>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>[%-5level] - %d{HH:mm:ss.SSS} [%logger{35}] - %msg%n</Pattern>
</layout>
</appender>
<logger name="org.hibernate">
<level value="WARN"/>
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
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頁面
<span id="submit-button">
<h:commandButton id="button-submit" value="Sign On" action="#{loginBacking.performLogin}" />
</span>
終於我的pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>tester</artifactId>
<version>1.0/version>
<name>Code</name>
<packaging>war</packaging>
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
</repository>
<repository>
<snapshots />
<id>codecaus</id>
<name>codehaus</name>
<url>http://repository.codehaus.org</url>
</repository>
<repository>
<snapshots />
<id>ibiblio</id>
<url>http://www.ibiblio.org/maven2/</url>
</repository>
<repository>
<id>jboss</id>
<url>http://repository.jboss.com/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>jboss-snapshot</id>
<url>http://snapshots.jboss.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>java.net.glassfish</id>
<name>Repository hosting the jee6 artifacts</name>
<url>http://download.java.net/maven/glassfish</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-plugins</id>
<url>http://repository.jboss.com/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>jboss-snapshot-plugins</id>
<url>http://snapshots.jboss.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>bean-validator</artifactId>
<version>3.0-JBoss-4.0.0.Beta3</version>
</dependency>
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- JPA -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.2.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc4</version>
</dependency>
<!-- logging -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>0.9.18</version>
</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>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<properties>
<netbeans.hint.deploy.server>gfv3ee6</netbeans.hint.deploy.server>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<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.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
</plugin>
</plugins>
</build>
</project>
編輯:我也嘗試將記錄器更改為靜態,沒有更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.