The Apache Log4j implementation of java.util.logging providing JUL to Log4j bridge functionality
—
The Log4jBridgeHandler provides an alternative to LogManager replacement, especially useful for webapps running on containers where the LogManager cannot or should not be used. It acts as a JUL Handler that bridges log events from JUL to Log4j.
Configure in JUL's logging.properties:
# Set the handler
handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler
# Enable level propagation (recommended)
org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true
# Optional: Add suffix to logger names
org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _JUL
# Optional: Enable debug output
org.apache.logging.log4j.jul.Log4jBridgeHandler.sysoutDebug = falseimport org.apache.logging.log4j.jul.Log4jBridgeHandler;
// Install with configuration
Log4jBridgeHandler.install(
true, // removeHandlersForRootLogger - remove existing handlers
"_JUL", // suffixToAppend - suffix for logger names (optional)
true // propagateLevels - auto-propagate Log4j levels to JUL
);// Create and configure handler
Log4jBridgeHandler handler = new Log4jBridgeHandler(
false, // debugOutput
"_JUL", // suffixToAppend
true // propagateLevels
);
// Add to root logger
java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger("");
rootLogger.addHandler(handler);Once installed, all JUL log events are automatically bridged to Log4j:
// Standard JUL logging - automatically bridged to Log4j
java.util.logging.Logger logger = java.util.logging.Logger.getLogger("com.example");
logger.severe("Critical error occurred");
logger.warning("Warning message");
logger.info("Information message");
logger.fine("Debug message");
logger.finest("Trace message");
// Parameterized messages
logger.log(java.util.logging.Level.INFO, "Processing {0} records in {1}ms",
new Object[]{count, duration});
// Exception logging
try {
riskyOperation();
} catch (Exception e) {
logger.log(java.util.logging.Level.SEVERE, "Operation failed", e);
}Add a suffix to JUL logger names to identify bridged messages:
org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _JULThis converts logger com.example.Service to com.example.Service._JUL in Log4j.
Automatically synchronize Log4j log levels with JUL:
org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = trueWhen enabled:
Enable diagnostic output for troubleshooting:
org.apache.logging.log4j.jul.Log4jBridgeHandler.sysoutDebug = truepublic class Log4jBridgeHandler extends java.util.logging.Handler implements PropertyChangeListener {
/**
* Creates handler reading configuration from JUL's LogManager.
* Reads properties: sysoutDebug, appendSuffix, propagateLevels.
*/
public Log4jBridgeHandler();
/**
* Creates handler with explicit configuration.
*
* @param debugOutput enable debug output to System.out
* @param suffixToAppend suffix for JUL logger names (null for none)
* @param propagateLevels enable automatic level propagation from Log4j to JUL
*/
public Log4jBridgeHandler(boolean debugOutput, String suffixToAppend, boolean propagateLevels);
/**
* Programmatically installs handler on JUL root logger.
*
* @param removeHandlersForRootLogger remove existing handlers from root logger
* @param suffixToAppend suffix for JUL logger names (null for none)
* @param propagateLevels enable automatic level propagation
*/
public static void install(boolean removeHandlersForRootLogger, String suffixToAppend, boolean propagateLevels);
/**
* Publishes JUL LogRecord to Log4j.
* Converts levels, handles messages, and propagates exceptions.
*
* @param record the JUL LogRecord to publish (null records are ignored)
*/
public void publish(LogRecord record);
/**
* No-op flush implementation.
*/
public void flush();
/**
* Cleanup handler resources and remove property change listeners.
*/
public void close();
}When level propagation is enabled, the handler:
// When Log4j configuration changes:
for (LoggerConfig log4jConfig : log4jConfiguration.getLoggers().values()) {
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(log4jConfig.getName());
java.util.logging.Level julLevel = LevelTranslator.toJavaLevel(log4jConfig.getLevel());
julLogger.setLevel(julLevel);
}The bridge handler uses LevelTranslator for bidirectional level conversion:
For Tomcat webapps, create WEB-INF/classes/logging.properties:
# Complete JUL configuration for this webapp only
.level = INFO
handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler
# Configure bridge handler
org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true
org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _WEBAPP
# Optional: specific logger levels
com.example.level = DEBUGThe bridge handler gracefully handles various error conditions:
The Log4jBridgeHandler is fully thread-safe:
Install with Tessl CLI
npx tessl i tessl/maven-org-apache-logging-log4j--log4j-jul