JSF 2 + Log4j Integration Example
In this tutorial, we will show you how to integrate the log4j framework with the JSF 2.x web application. JSF is using java.util.logging
, you need extra works to redirect the logging from JSF’s java.util.logging
to log4j
, with a serious penalty of performance, make sure use this trick only during local development or debugging environment.
Review the project environment :
- SLF4j 1.7.7
- Log4j 1.2.17
- JSF 2.2.7
- Maven 3
- Tomcat 6
- Eclipse Kepler 4.3
Steps to integrate JSF and log4j, in short.
- Turn on the JSF logging on
logging.properties
, since this project is running inside the Eclipse environment, the Eclipse’sJRE/lib/logging.properties
will be used. - Create a
log4j.properties
and put it on the class path. - Create a Servlet’s listener, install the
slf4j bridge handler
to redirect the logging from java.util.logging to log4j.
Refer to this SLF4j Bridging legacy APIs
1. Project Directory
Review the final project structure.
2. Project Dependencies
You need slf4j-log4j12 and jul-to-slf4j.
<properties>
<jdk.version>1.7</jdk.version>
<jsf.version>2.2.7</jsf.version>
<slf4j.version>1.7.7</slf4j.version>
</properties>
<dependencies>
<!-- from java.util.logging to log4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- it help to get slf4j and log4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- JSF -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${jsf.version}</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>${jsf.version}</version>
</dependency>
<!-- you need this in web -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
4. JSF Logging
Since this project is running inside the Eclipse’s environment, the Eclipse’s JRE will be used. Open the logging.properties
, change the level to FINEST, and turn on the logging on javax.faces
and com.sun.faces
:
# Default is INFO, change it to FINNEST
#java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
#Add these two lines to enable JSF logging
javax.faces.level = FINEST
com.sun.faces.level = FINEST
Refer to the java.util.logging levels.
If this project is deployed on Tomcat directly, update this
${Tomcat}\conf\logging.properties
5. Log4j Logging
Create a log4j properties file, and put it into the resources
folder, refer to step#1.
# Root logger option
log4j.rootLogger=WARN, console, file
#enable JSF logging
log4j.logger.javax.faces=DEBUG
log4j.logger.com.sun.faces=DEBUG
# Redirect log messages to console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Redirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=${catalina.home}/logs/jsfapp.log
log4j.appender.file.MaxFileSize=5KB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
6. ServletContextListener
Create a Servlet listener to install the bridge handler, in order to redirect the JSF’s logging from java.util.properties
to log4j
.
package com.mkyong.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent arg) {
System.out.println("contextInitialized....");
//remove the jsf root logger, avoid duplicated logging
//try comment out this and see the different on the console
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
@Override
public void contextDestroyed(ServletContextEvent arg) {
System.out.println("contextDestroyed....");
}
}
Include the listener class, and other standard JSF settings.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>JavaServerFacesAndLog4j</display-name>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<!-- Install slf4j bridge handler -->
<listener>
<listener-class>
com.mkyong.listener.MyListener
</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
7. Application Logging
A simple example to show you how to do log4j’s logging.
package com.mkyong.controller;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.apache.log4j.Logger;
@ManagedBean
@SessionScoped
public class PageController implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(PageController.class);
public String process() {
// logs debug
if (logger.isDebugEnabled()) {
logger.debug("PageController.process()");
}
// logs exception
logger.error("This is Error message", new Exception("Testing"));
return "success";
}
}
A simple JSF view resource.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<h1>JSF 2.0 + Log4j</h1>
<h:form>
<h:commandButton action="#{pageController.process}" value="Click Me" />
</h:form>
</h:body>
</html>
8. Demo
Run the JSF web application, and access the default page, and clicks on the button.
URL : http://localhost:8080/JavaServerFacesAndLog4j/
8.1 Both JSF and application logging will be displayed in the console.
Figure : Eclipse console
8.2 Both JSF and application logging will be logged in ${tomcat}\logs\jsfapp.log
.
Figure : D:\apache-tomcat-6.0.37\logs\jsfapp.log
No appenders could be found for logger (javax.enterprise.resource.webcontainer.jsf.config).
thanks for your post But i am using jsf2.0 without maven how to do in this case