CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-logging-log4j--log4j-jul

The Apache Log4j implementation of java.util.logging providing JUL to Log4j bridge functionality

Pending
Overview
Eval results
Files

bridge-handler.mddocs/

Bridge Handler

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.

Installation

Declarative Configuration

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

Programmatic Installation

import 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
);

Manual Installation

// 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);

Usage

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

Configuration Options

Suffix Appending

Add a suffix to JUL logger names to identify bridged messages:

org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _JUL

This converts logger com.example.Service to com.example.Service._JUL in Log4j.

Level Propagation

Automatically synchronize Log4j log levels with JUL:

org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true

When enabled:

  • Log4j configuration changes trigger JUL level updates
  • Eliminates the need to maintain duplicate level configurations
  • Prevents JUL from filtering messages that Log4j should see

Debug Output

Enable diagnostic output for troubleshooting:

org.apache.logging.log4j.jul.Log4jBridgeHandler.sysoutDebug = true

API Reference

Log4jBridgeHandler Class

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

Level Propagation Details

When level propagation is enabled, the handler:

  1. Monitors Log4j Configuration: Listens for Log4j configuration changes
  2. Updates JUL Levels: Automatically sets JUL logger levels to match Log4j
  3. Maintains References: Keeps hard references to JUL loggers to prevent garbage collection
  4. Cleans Up Unused: Resets JUL levels for loggers not configured in Log4j

Propagation Process

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

Level Translation

The bridge handler uses LevelTranslator for bidirectional level conversion:

  • JUL SEVERE → Log4j ERROR
  • JUL WARNING → Log4j WARN
  • JUL INFO → Log4j INFO
  • JUL CONFIG → Log4j CONFIG (custom level)
  • JUL FINE → Log4j DEBUG
  • JUL FINER → Log4j TRACE
  • JUL FINEST → Log4j FINEST (custom level)

Performance Considerations

Handler Overhead

  • Message Formatting: Uses JUL's SimpleFormatter for message formatting
  • Level Conversion: Minimal overhead for level translation
  • Logger Lookup: Cached Log4j logger instances for performance

Level Filtering

  • JUL Pre-filtering: Only log events passing JUL's level filter reach the handler
  • Dual Filtering: Messages filtered by both JUL and Log4j levels
  • Optimization: Use level propagation to align filtering

Extended Logger Support

  • Enhanced Performance: Uses ExtendedLogger.logIfEnabled() when available
  • Location Information: Preserves caller location through FQCN
  • Fallback Handling: Falls back to standard Logger.log() if ExtendedLogger fails

Restrictions and Limitations

  1. Location Information: Manually provided source location in JUL methods (entering(), exiting(), logp(), etc.) is not preserved
  2. Level Configuration: Requires level configuration in both JUL and Log4j unless using level propagation
  3. Performance: Additional overhead compared to LogManager approach
  4. Handler Chain: Only processes log events that pass JUL's handler chain

Webapp Integration

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

Error Handling

The bridge handler gracefully handles various error conditions:

  • Null Records: Silently ignores null LogRecord instances
  • ExtendedLogger Failures: Falls back to standard logging if ExtendedLogger throws NoClassDefFoundError
  • Logger Name Handling: Uses fallback name for null logger names
  • Configuration Errors: Continues operation with default settings if configuration fails

Thread Safety

The Log4jBridgeHandler is fully thread-safe:

  • Synchronized Level Propagation: Level propagation setup is synchronized
  • Property Change Handling: Thread-safe property change listener registration
  • Logger References: Thread-safe management of JUL logger references

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-logging-log4j--log4j-jul

docs

bridge-handler.md

index.md

level-translation.md

logger-adapters.md

logmanager-integration.md

tile.json