Overview
Here's a little Handler I made that routes java.util.logging messsages to Log4J. These are all available here:
This very nicely solves the Facelets 'loadImplicit' error issue as well as giving you the flexibility to enable more detailed logging for the JSF reference implementation.
The java.util.logging Handler Class
JuliToLog4jHandler.java
package org.yajul.log; import org.apache.log4j.Priority; import org.apache.log4j.Logger; import java.text.MessageFormat; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; /** * A JULI (java.util.logging) handler that redirects java.util.logging messages to Log4J * http://wiki.apache.org/myfaces/Trinidad_and_Common_Logging * <br> * User: josh * Date: Jun 4, 2008 * Time: 3:31:21 PM */ public class JuliToLog4jHandler extends Handler { public void publish(LogRecord record) { org.apache.log4j.Logger log4j = getTargetLogger(record.getLoggerName()); Priority priority = toLog4j(record.getLevel()); log4j.log(priority, toLog4jMessage(record), record.getThrown()); } static Logger getTargetLogger(String loggerName) { return Logger.getLogger(loggerName); } public static Logger getTargetLogger(Class clazz) { return getTargetLogger(clazz.getName()); } private String toLog4jMessage(LogRecord record) { String message = record.getMessage(); // Format message try { Object parameters[] = record.getParameters(); if (parameters != null && parameters.length != 0) { // Check for the first few parameters ? if (message.indexOf("{0}") >= 0 || message.indexOf("{1}") >= 0 || message.indexOf("{2}") >= 0 || message.indexOf("{3}") >= 0) { message = MessageFormat.format(message, parameters); } } } catch (Exception ex) { // ignore Exception } return message; } private org.apache.log4j.Level toLog4j(Level level) {//converts levels if (Level.SEVERE == level) { return org.apache.log4j.Level.ERROR; } else if (Level.WARNING == level) { return org.apache.log4j.Level.WARN; } else if (Level.INFO == level) { return org.apache.log4j.Level.INFO; } else if (Level.OFF == level) { return org.apache.log4j.Level.OFF; } return org.apache.log4j.Level.OFF; } @Override public void flush() { // nothing to do } @Override public void close() { // nothing to do } }
JMX MBean Wrapper
Lifecycle.java
/** * Standard JMX MBean lifecycle methods. * <br>User: Joshua Davis * Date: Aug 29, 2007 * Time: 5:58:12 AM */ public interface Lifecycle { /** * Called when an MBean is started * * @throws Exception if something went wrong. */ void start() throws Exception; /** * Called when an MBean is stopped */ void stop(); }
JuliToLog4jServiceMBean.java
package org.yajul.log; import org.yajul.jmx.Lifecycle; /** * JMX Interface for the Juli->Log4J MBean. * <br> * User: josh * Date: Jun 5, 2008 * Time: 8:44:16 AM */ public interface JuliToLog4JServiceMBean extends Lifecycle { /** * @return The logging level of the java.util.logging->Log4J 'Handler' as a string */ String getHandlerLevel(); /** * Sets the logging level of the java.util.logging->Log4J 'Handler' to the specified value. * @param level the logging level for the adapter, e.g. "INFO" */ void setHandlerLevel(String level); }
JuliToLog4jService.java
package org.yajul.log; import java.util.logging.Logger; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.List; import java.util.ArrayList; /** * JMX MBean that plugs in the JULI->Log4j handler on start and unplugs it on stop. * Here is an example of a JBoss JMX MBean declaration: * <!-- Redirect java.util.logging to Log4J. --> * <mbean code="org.yajul.log.JuliToLog4JService" * name="org.yajul:service=JuliToLog4J"> * <attribute name="HandlerLevel">DEBUG</attribute> * <depends>jboss.system:type=Log4jService,service=Logging</depends> * </mbean> * Note that because of a small glitch in the JMX specification, the attribute name * is 'HandlerLevel', and not 'handlerLevel' as you might expect. * See http://madplanet.com/jboss-docu-wiki/Wiki.jsp?page=40.JMX.MBean * <br> * User: josh * Date: Jun 4, 2008 * Time: 3:41:44 PM */ public class JuliToLog4JService implements JuliToLog4JServiceMBean { private Handler activeHandler; private List<Handler> oldHandlers = new ArrayList<Handler>(); private Level handlerLevel = Level.ALL; private Level rootLevel = Level.INFO; public void start() throws Exception { try { JuliToLog4jHandler.getTargetLogger(JuliToLog4JService.class).info( "start(): Redirecting java.util.logging to Log4J..."); Logger rootLogger = LogManager.getLogManager().getLogger(""); // remove old handlers for (Handler handler : rootLogger.getHandlers()) { oldHandlers.add(handler); rootLogger.removeHandler(handler); } // add our own activeHandler = new JuliToLog4jHandler(); activeHandler.setLevel(handlerLevel); rootLogger.addHandler(activeHandler); rootLogger.setLevel(rootLevel); // done, let's check it right away!!! Logger.getLogger(JuliToLog4JService.class.getName()).info("started: sending JDK log messages to Log4J"); } catch (Exception exc) { JuliToLog4jHandler.getTargetLogger(JuliToLog4JService.class).error("start() failed", exc); } } public void stop() { Logger rootLogger = LogManager.getLogManager().getLogger(""); rootLogger.removeHandler(activeHandler); // Put all the old handlers back. for (Handler oldHandler : oldHandlers) { rootLogger.addHandler(oldHandler); } Logger.getLogger(JuliToLog4jHandler.class.getName()).info("stopped"); } public String getHandlerLevel() { return handlerLevel.getName(); } public void setHandlerLevel(String level) { final String parseThis = level.toUpperCase(); if ("DEBUG".equalsIgnoreCase(parseThis)) handlerLevel = Level.FINE; else handlerLevel = Level.parse(parseThis); } }
Adding it to JBoss AS
Once you have the classes in the classpath, just add the following to conf/jboss-service.xml right after the Log4JService declaration:
<!-- Redirect java.util.logging to Log4J. -->
<mbean code="org.yajul.log.JuliToLog4JService"
name="org.yajul:service=JuliToLog4J">
<attribute name="HandlerLevel">DEBUG</attribute>
<depends>jboss.system:type=Log4jService,service=Logging</depends>
</mbean>
NOTE: This is not needed in JBoss 5.x, it already has this feature.

Add Comment