or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/maven-org-slf4j--slf4j-jdk14

SLF4J binding implementation that bridges SLF4J API with Java Util Logging (JUL) framework

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.slf4j/slf4j-jdk14@2.0.x

To install, run

npx @tessl/cli install tessl/maven-org-slf4j--slf4j-jdk14@2.0.0

index.mddocs/

SLF4J JDK14 Provider

SLF4J JDK14 Provider is a binding implementation that bridges the SLF4J (Simple Logging Facade for Java) API with Java Util Logging (JUL), the built-in logging framework in the JDK. This lightweight adapter enables SLF4J-based applications to output logs through the standard java.util.logging framework without requiring additional logging dependencies.

Package Information

  • Package Name: org.slf4j:slf4j-jdk14
  • Package Type: maven
  • Language: Java
  • Installation: Add to Maven dependencies or use as a service provider jar

Maven Dependency:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>2.0.17</version>
</dependency>

Core Imports

import org.slf4j.jul.JULServiceProvider;
import org.slf4j.jul.JDK14LoggerFactory;
import org.slf4j.jul.JDK14LoggerAdapter;

Basic Usage

The slf4j-jdk14 provider is automatically discovered via Java's ServiceLoader mechanism when present on the classpath. No explicit configuration is required for basic usage:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Example {
    private static final Logger logger = LoggerFactory.getLogger(Example.class);
    
    public void demonstrateLogging() {
        logger.trace("Trace level message");
        logger.debug("Debug level message");
        logger.info("Info level message");
        logger.warn("Warning level message");
        logger.error("Error level message", new RuntimeException("Example error"));
    }
}

Architecture

The provider consists of three main components:

  • JULServiceProvider: Service provider implementation for automatic discovery
  • JDK14LoggerFactory: Factory for creating and caching logger instances
  • JDK14LoggerAdapter: Adapter that wraps java.util.logging.Logger instances

Level Mapping: SLF4J levels are mapped to JUL levels:

  • TRACE → Level.FINEST
  • DEBUG → Level.FINE
  • INFO → Level.INFO
  • WARN → Level.WARNING
  • ERROR → Level.SEVERE

Capabilities

Service Provider Implementation

The main service provider that enables automatic SLF4J integration.

public class JULServiceProvider implements SLF4JServiceProvider {
    // API version this implementation is compiled against
    public static String REQUESTED_API_VERSION = "2.0.99";
    
    public JULServiceProvider();
    public ILoggerFactory getLoggerFactory();
    public IMarkerFactory getMarkerFactory();
    public MDCAdapter getMDCAdapter();
    public String getRequestedApiVersion();
    public void initialize();
}

Usage: This class is automatically instantiated by SLF4J's ServiceLoader mechanism. Manual instantiation is not typically needed.

Logger Factory

Factory implementation that creates and manages logger instances.

public class JDK14LoggerFactory implements ILoggerFactory {
    public JDK14LoggerFactory();
    public Logger getLogger(String name);
}

Usage:

JDK14LoggerFactory factory = new JDK14LoggerFactory();
Logger logger = factory.getLogger("com.example.MyClass");

Logger Adapter

Logger adapter that bridges SLF4J Logger interface to java.util.logging.Logger.

public final class JDK14LoggerAdapter extends LegacyAbstractLogger 
    implements LocationAwareLogger {
    
    // Constants for stack trace analysis
    static final int MAX_SEARCH_DEPTH = 12;
    static String SELF = JDK14LoggerAdapter.class.getName();
    static String[] BARRIER_CLASSES;
    
    // Constructor
    JDK14LoggerAdapter(java.util.logging.Logger logger);
    
    // Level check methods
    public boolean isTraceEnabled();
    public boolean isDebugEnabled();
    public boolean isInfoEnabled();
    public boolean isWarnEnabled();
    public boolean isErrorEnabled();
    
    // Logging methods (inherited from parent classes)
    // All standard SLF4J Logger interface methods available
    
    // LocationAwareLogger method
    public void log(Marker marker, String callerFQCN, int slf4jLevelInt, 
                   String message, Object[] arguments, Throwable throwable);
    
    // LoggingEvent support
    public void log(LoggingEvent event);
    
    // Level conversion utilities
    private static Level slf4jLevelToJULLevel(org.slf4j.event.Level slf4jLevel);
    private static Level slf4jLevelIntToJULLevel(int levelInt);
    
    // Event processing
    private LogRecord eventToRecord(LoggingEvent event, Level julLevel);
}

Usage: Logger instances are typically obtained through SLF4J's LoggerFactory, not directly instantiated:

Logger logger = LoggerFactory.getLogger(MyClass.class);

// Level checks
if (logger.isDebugEnabled()) {
    logger.debug("Debug message with parameter: {}", value);
}

// Direct logging
logger.info("Application started");
logger.warn("Configuration missing, using defaults");
logger.error("Failed to process request", exception);

// LoggingEvent support (typically used by SLF4J internally)
LoggingEvent event = new LoggingEvent(Level.INFO, logger);
event.setMessage("Event-based logging");
logger.log(event);

Level Check Operations

All logger adapters provide level checking methods for performance optimization.

// Check if specific logging levels are enabled
boolean isTraceEnabled();
boolean isDebugEnabled();
boolean isInfoEnabled();
boolean isWarnEnabled();
boolean isErrorEnabled();

Usage:

// Avoid expensive string operations when level is disabled
if (logger.isDebugEnabled()) {
    logger.debug("Processing item: {}", expensiveToString(item));
}

Level Conversion

The provider includes utility methods for converting SLF4J levels to JUL levels.

// Internal level conversion methods
private static Level slf4jLevelToJULLevel(org.slf4j.event.Level slf4jLevel);
private static Level slf4jLevelIntToJULLevel(int levelInt);

Level Mapping:

  • TRACELevel.FINEST
  • DEBUGLevel.FINE
  • INFOLevel.INFO
  • WARNLevel.WARNING
  • ERRORLevel.SEVERE

Stack Trace Analysis

The adapter preserves caller information through stack trace analysis with configurable depth limits.

// Stack trace analysis constants
static final int MAX_SEARCH_DEPTH = 12;
static String SELF = "org.slf4j.jul.JDK14LoggerAdapter";
static String[] BARRIER_CLASSES; // Contains known SLF4J framework classes

Caller Detection: The adapter analyzes up to 12 stack frames to identify the actual calling class and method, filtering out known SLF4J framework classes to provide accurate source location information in log records.

LoggingEvent Processing

The adapter supports SLF4J's LoggingEvent API for structured logging scenarios.

// LoggingEvent processing
public void log(LoggingEvent event);
private LogRecord eventToRecord(LoggingEvent event, Level julLevel);

LoggingEvent Usage:

// Create and configure a logging event
LoggingEvent event = new LoggingEvent();
event.setLevel(Level.INFO);
event.setLoggerName("com.example.MyClass");
event.setMessage("Processing completed for user: {}");
event.setArgumentArray(new Object[]{"john.doe"});
event.setTimeStamp(System.currentTimeMillis());

// Log through the adapter
logger.log(event);

Event to Record Conversion: The eventToRecord method converts SLF4J LoggingEvent objects to JUL LogRecord objects, handling:

  • Message formatting with parameters
  • Timestamp preservation
  • Logger name mapping
  • Exception handling
  • Source location information

Service Provider Configuration

The provider is automatically discovered through Java's ServiceLoader mechanism via the configuration file:

File Structure:

src/main/resources/
└── META-INF/
    └── services/
        └── org.slf4j.spi.SLF4JServiceProvider

File Content: org.slf4j.jul.JULServiceProvider

This configuration enables automatic discovery of the JUL provider when slf4j-jdk14 is present on the classpath.

Module System Integration

For Java 9+ module system:

module org.slf4j.jul {
    requires org.slf4j;
    requires java.logging;
    
    exports org.slf4j.jul;
    opens org.slf4j.jul to org.slf4j;
    
    provides org.slf4j.spi.SLF4JServiceProvider 
        with org.slf4j.jul.JULServiceProvider;
}

Types

Core SLF4J Types

These types are provided by the SLF4J API dependency:

// From org.slf4j.spi
interface SLF4JServiceProvider {
    ILoggerFactory getLoggerFactory();
    IMarkerFactory getMarkerFactory();
    MDCAdapter getMDCAdapter();
    String getRequestedApiVersion();
    void initialize();
}

interface ILoggerFactory {
    Logger getLogger(String name);
}

interface LocationAwareLogger extends Logger {
    void log(Marker marker, String fqcn, int level, String message, 
             Object[] argArray, Throwable t);
}

// From org.slf4j
interface Logger {
    // Standard logging methods
    void trace(String msg);
    void debug(String msg);
    void info(String msg);
    void warn(String msg);
    void error(String msg);
    
    // Parameterized logging methods
    void trace(String format, Object... arguments);
    void debug(String format, Object... arguments);
    void info(String format, Object... arguments);
    void warn(String format, Object... arguments);
    void error(String format, Object... arguments);
    
    // Exception logging methods
    void trace(String msg, Throwable t);
    void debug(String msg, Throwable t);
    void info(String msg, Throwable t);
    void warn(String msg, Throwable t);
    void error(String msg, Throwable t);
    
    // Level check methods
    boolean isTraceEnabled();
    boolean isDebugEnabled();
    boolean isInfoEnabled();
    boolean isWarnEnabled();
    boolean isErrorEnabled();
}

interface Marker {
    String getName();
    void add(Marker reference);
    boolean remove(Marker reference);
    boolean contains(Marker other);
    boolean contains(String name);
}

interface IMarkerFactory {
    Marker getMarker(String name);
    boolean exists(String name);
    boolean detachMarker(String name);
}

interface MDCAdapter {
    void put(String key, String val);
    String get(String key);
    void remove(String key);
    void clear();
}

class LoggingEvent {
    Level getLevel();
    String getLoggerName();
    String getMessage();
    Object[] getArgumentArray();
    Throwable getThrowable();
    long getTimeStamp();
}

Java Util Logging Types

Key JUL types used by the implementation:

// From java.util.logging
class Logger {
    static Logger getLogger(String name);
    boolean isLoggable(Level level);
    void log(LogRecord record);
    String getName();
}

class LogRecord {
    LogRecord(Level level, String msg);
    void setLoggerName(String name);
    void setThrown(Throwable ex);
    void setSourceClassName(String sourceClassName);
    void setSourceMethodName(String sourceMethodName);
    void setMillis(long millis);
}

class Level {
    static final Level FINEST;
    static final Level FINE;
    static final Level INFO;
    static final Level WARNING;
    static final Level SEVERE;
}

Error Handling

The provider handles several error scenarios:

Common Exceptions

  • IllegalStateException: Thrown when an unrecognized SLF4J level is encountered during level mapping
  • IllegalArgumentException: Thrown when both throwable argument and throwable in argument array are provided to logging methods

Error Scenarios

  1. Unrecognized Level: When slf4jLevelToJULLevel receives an unknown SLF4J level enum value
  2. Double Throwable: When both explicit throwable parameter and throwable in arguments array are provided to LoggingEvent processing
  3. JUL Initialization Failure: Handled gracefully during factory construction by calling java.util.logging.Logger.getLogger("")
  4. Stack Trace Analysis: Limited to MAX_SEARCH_DEPTH (12) stack frames to prevent excessive performance overhead
  5. Event Processing: In eventToRecord, throws IllegalArgumentException if both event throwable and formatted message throwable are present

Configuration

JUL Configuration

Since this provider delegates to java.util.logging, configure JUL using standard mechanisms:

logging.properties:

# Root logger level
.level = INFO

# Console handler
handlers = java.util.logging.ConsoleHandler

# Console handler level and format
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# Package-specific levels
com.example.level = DEBUG

Programmatic Configuration:

import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.ConsoleHandler;

Logger julLogger = Logger.getLogger("com.example");
julLogger.setLevel(Level.FINE);
julLogger.addHandler(new ConsoleHandler());

Integration Notes

  1. Automatic Discovery: No manual configuration needed when slf4j-jdk14 is on classpath
  2. Thread Safety: Logger instances are cached in ConcurrentHashMap for thread-safe access
  3. Performance: Level checks are delegated to JUL's isLoggable() for optimal performance
  4. Caller Information: Stack trace analysis preserves caller location information in log records
  5. Root Logger Mapping: SLF4J ROOT logger is properly mapped to JUL's "" (empty string) root logger