Logback with EJB3.1

I am using logback / slf4j to handle logging in my application. Everything worked fine until I started using EJB. After I added stateless EJB to my application, the registrar began to ignore my logback.xml file and stopped using my applications. I switched to the registrar software configuration to find out what was wrong, and now I get the following error when I try to use my registrar in EJB:

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

follows from the line:

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

Is there any special configuration needed to work with EJB? If that matters, I am deploying to glassfish v3.

+5
source share
4 answers

This looks very close to the problem described in this thread , and I suspect that the problem is with a similar class loading. Due to the way logback loads logback.xml (more precisely, how it retrieves ClassLoader for this), it may fail when compiling its configuration file and return to the default BasicConfiguration .

Not sure how you pack your code, but a suggested workaround is to include logback.xml in the EAR lib. If you are not using EAR packaging, try identifying the class loader used to determine the location of the logback.xml file.

In the end, this can be a problem in logback. However, they did not check their tracker.

Update:. If you use military packaging, try setting up GlassFish to use child class loaders for delegation first. In sun-web.xml :

 <sun-web-app> <class-loader delegate="false"/> </sun-web-app> 

Strike>


Update: I checked a little on my side and ... I can not reproduce your problem. I created a project for Java EE 6 webapp that 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 this:

 <?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> 

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

Code for 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()"); } } 

Code for index.jsp :

 <html> <body> <h2>Hello World!</h2> Invoke the Servlet by clicking <a href="SimpleServlet">here</a>. </body> </html> 

And my logback.xml looks like this:

 <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 the correct load, and when I call the servlet, I get the following trace (taken from the log file):

 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 also tried with an EJB packaged in its own JAR and deployed to WEB-INF/lib and getting the same result, it just works. Can you spot any obvious difference? You may need to download a simplified version of your application (most likely it will be required for a BTW error message).

I am running GlassFish v3 under Eclipse 3.5 (with the GlassFish v3 plugin).

+9
source

The exception org.slf4j.impl.JDK14LoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext shows that SLF4J is not bound to logback-classic, but to slf4j-jdk14. In short, the registration code is not to blame, because it is not implemented or called.

It seems that GFv3 is exporting slf4j-jdk14.jar to your application and thus overrides your choice of logging in the background, logback in this case. This is one of those scenarios where an application server inadvertently imposes its rights on a user.

If GFv3 imposes SLF4J on the end user, then the problem with GFv3 should be solved by the developers of GFv3. I may be mistaken, but I think they assume that the end user will not want any other logging functions, except that it is provided by java.util.logging and simply binds slf4j-jdk14 in GFv3. Users must contact them and state that their assumption is incorrect. It is also possible that they are aware of this problem and are already providing a workaround ...

+5
source

Basically the problem is that the application server uses provides slf4j. And that your attempts to use it go to the slf4j application server binding, and not the one you want yourself.

Can't you use slf4j binding in Glassfish?

0
source

Here is a very important code:

EJB Input:

 @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; } } } 

Interceptor, where is my registration code:

 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()); } } } 

.Xml log file

 <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> 

Support for 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; } } 

I have a jsf page with

 <span id="submit-button"> <h:commandButton id="button-submit" value="Sign On" action="#{loginBacking.performLogin}" /> </span> 

finally my 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> 

Edit: I also tried changing my registrar to static, no change.

0
source

Source: https://habr.com/ru/post/925493/


All Articles