or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/maven-org-springframework--spring-jcl

Spring's optimized Commons Logging bridge with automatic detection of Log4J 2, SLF4J, and java.util.logging

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.springframework/spring-jcl@6.2.x

To install, run

npx @tessl/cli install tessl/maven-org-springframework--spring-jcl@6.2.0

index.mddocs/

Spring JCL

Spring JCL (Java Commons Logging) is Spring's variant of the Apache Commons Logging API that provides a minimized and optimized logging bridge specifically designed for Spring Framework's internal logging needs. It offers special support for Log4J 2, SLF4J, and java.util.logging with automatic detection of available logging frameworks in the classpath.

Package Information

  • Package Name: org.springframework:spring-jcl

  • Package Type: Maven

  • Language: Java

  • Installation:

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jcl</artifactId>
      <version>6.2.8</version>
    </dependency>

    Gradle:

    implementation 'org.springframework:spring-jcl:6.2.8'

Core Imports

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

For implementation classes (optional):

import org.apache.commons.logging.LogFactoryService;
import org.apache.commons.logging.impl.NoOpLog;
import org.apache.commons.logging.impl.SimpleLog;

Internal classes (not typically imported directly):

import org.apache.commons.logging.LogAdapter;

Basic Usage

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MyService {
    private static final Log logger = LogFactory.getLog(MyService.class);
    
    public void doSomething() {
        logger.info("Starting operation");
        
        try {
            // Your code here
            logger.debug("Operation in progress");
        } catch (Exception e) {
            logger.error("Operation failed", e);
            throw e;
        }
        
        logger.info("Operation completed");
    }
}

Architecture

Spring JCL is built around several key components:

  • LogFactory: Main entry point providing static factory methods for logger creation
  • Log Interface: Commons Logging compatible interface with six logging levels (trace, debug, info, warn, error, fatal)
  • LogAdapter: Internal adapter that automatically detects available logging frameworks (Log4J 2, SLF4J, java.util.logging)
  • Framework Implementations: Bridge implementations for Log4J 2, SLF4J (with location awareness), and java.util.logging
  • Compatibility Layer: Deprecated classes maintaining binary compatibility with Apache Commons Logging

Capabilities

Logger Factory

Creates logger instances with automatic framework detection and optimization.

/**
 * Main factory class for obtaining Log instances with automatic adapter detection
 */
public abstract class LogFactory {
    /**
     * Convenience method to return a named logger
     * @param clazz containing Class from which a log name will be derived
     * @return Log instance for the class
     */
    public static Log getLog(Class<?> clazz);
    
    /**
     * Convenience method to return a named logger
     * @param name logical name of the Log instance to be returned
     * @return Log instance for the name
     */
    public static Log getLog(String name);
}

Deprecated Methods (for compatibility):

/**
 * @deprecated in favor of getLog(Class)/getLog(String)
 */
@Deprecated
public static LogFactory getFactory();

/**
 * @deprecated in favor of getLog(Class)
 */
@Deprecated
public Log getInstance(Class<?> clazz);

/**
 * @deprecated in favor of getLog(String)  
 */
@Deprecated
public Log getInstance(String name);

/**
 * @deprecated no-op method for compatibility
 */
@Deprecated
public static void release(ClassLoader classLoader);

/**
 * @deprecated no-op method for compatibility
 */
@Deprecated
public static void releaseAll();

/**
 * @deprecated utility method for object identification
 * Returns string representation with class name and identity hash code
 */
@Deprecated
public static String objectId(Object o);

// Abstract methods (for subclass implementation)
/**
 * @deprecated abstract method for attribute access
 */
@Deprecated
public abstract Object getAttribute(String name);

/**
 * @deprecated abstract method for attribute name retrieval
 */
@Deprecated
public abstract String[] getAttributeNames();

/**
 * @deprecated abstract method for attribute removal
 */
@Deprecated
public abstract void removeAttribute(String name);

/**
 * @deprecated abstract method for attribute setting
 */
@Deprecated
public abstract void setAttribute(String name, Object value);

/**
 * @deprecated abstract method for factory release
 */
@Deprecated
public abstract void release();

Logging Interface

Core logging interface providing six logging levels with conditional checks for performance.

/**
 * A simple logging interface abstracting logging APIs
 */
public interface Log {
    // Level check methods (for performance optimization)
    boolean isFatalEnabled();
    boolean isErrorEnabled();
    boolean isWarnEnabled();
    boolean isInfoEnabled();
    boolean isDebugEnabled();
    boolean isTraceEnabled();
    
    // Fatal level logging
    void fatal(Object message);
    void fatal(Object message, Throwable t);
    
    // Error level logging
    void error(Object message);
    void error(Object message, Throwable t);
    
    // Warn level logging
    void warn(Object message);
    void warn(Object message, Throwable t);
    
    // Info level logging
    void info(Object message);
    void info(Object message, Throwable t);
    
    // Debug level logging
    void debug(Object message);
    void debug(Object message, Throwable t);
    
    // Trace level logging
    void trace(Object message);
    void trace(Object message, Throwable t);
}

Usage Examples:

// Performance-optimized logging
if (logger.isDebugEnabled()) {
    logger.debug("Processing user: " + user.getName() + " with ID: " + user.getId());
}

// Exception logging
try {
    processData();
} catch (DataProcessingException e) {
    logger.error("Failed to process data for user: " + userId, e);
    throw e;
}

// Different logging levels
logger.trace("Entering method with params: " + params);
logger.debug("Intermediate calculation result: " + result);
logger.info("User " + username + " logged in successfully");
logger.warn("Deprecated API usage detected in class: " + className);
logger.error("Database connection failed", connectionException);
logger.fatal("System is shutting down due to critical error", criticalError);

Service Implementation

Fallback service implementation for META-INF service discovery compatibility when commons-logging.jar is accidentally on classpath.

/**
 * @deprecated since it is only meant to be used in fallback scenario when commons-logging.jar is accidentally on classpath
 */
@Deprecated
public class LogFactoryService extends LogFactory {
    /**
     * Constructor that prints compatibility warning about commons-logging.jar conflicts
     * Prints message: "Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts"
     */
    public LogFactoryService();
    
    /**
     * Get logger instance for class - delegates to LogAdapter.createLog()
     * @param clazz containing Class from which a log name will be derived
     * @return Log instance for the class
     */
    public Log getInstance(Class<?> clazz);
    
    /**
     * Get logger instance by name - delegates to LogAdapter.createLog()
     * @param name logical name of the Log instance to be returned
     * @return Log instance for the name
     */
    public Log getInstance(String name);
    
    // Attribute management methods (for compatibility) - uses ConcurrentHashMap
    /**
     * Set attribute value (null values remove the attribute)
     */
    public void setAttribute(String name, Object value);
    
    /**
     * Remove attribute by name
     */
    public void removeAttribute(String name);
    
    /**
     * Get attribute value
     * @return attribute value or null if not found
     */
    public Object getAttribute(String name);
    
    /**
     * Get all attribute names
     * @return array of attribute names
     */
    public String[] getAttributeNames();
    
    /**
     * Release resources - no-op method for compatibility
     */
    public void release();
}

Implementation Classes

Basic logger implementations for specific use cases.

/**
 * Trivial implementation of Log that throws away all messages
 */
public class NoOpLog implements Log, Serializable {
    public NoOpLog();
    public NoOpLog(String name);
    
    // All methods return false for level checks and are no-op for logging methods
}

/**
 * @deprecated in spring-jcl (effectively equivalent to NoOpLog)
 */
@Deprecated
public class SimpleLog extends NoOpLog {
    /**
     * Constructor that prints deprecation warning
     * Prints message: "SimpleLog is deprecated and equivalent to NoOpLog in spring-jcl. Use a standard LogFactory.getLog(Class/String) call instead."
     * @param name logger name
     */
    public SimpleLog(String name);
}

Types

/**
 * Main logging interface with six levels: trace, debug, info, warn, error, fatal
 */
public interface Log {
    // See Logging Interface section above for complete method signatures
}

/**
 * Abstract factory class for obtaining Log instances
 */
public abstract class LogFactory {
    // See Logger Factory section above for complete method signatures
}

/**
 * Service implementation extending LogFactory for compatibility
 * @deprecated only for fallback compatibility scenarios
 */
@Deprecated
public class LogFactoryService extends LogFactory {
    // See Service Implementation section above for complete method signatures
}

/**
 * No-operation logger implementation
 */
public class NoOpLog implements Log, java.io.Serializable {
    // See Implementation Classes section above for complete method signatures
}

/**
 * @deprecated Simple logger implementation (equivalent to NoOpLog)
 */
@Deprecated 
public class SimpleLog extends NoOpLog {
    // See Implementation Classes section above for complete method signatures
}

LogAdapter (Internal)

Internal adapter class that handles automatic logging framework detection and logger creation.

/**
 * Internal adapter class for framework detection and logger creation
 * This class is not part of the public API but is referenced by LogFactory
 */
final class LogAdapter {
    /**
     * Create Log instance using detected logging framework
     * @param name the logger name
     * @return Log instance using the best available logging framework
     */
    public static Log createLog(String name);
}

Internal Implementation Classes:

// Log4J 2 implementation (when Log4J 2 is available)
private static class Log4jLog implements Log, Serializable {
    public Log4jLog(String name);
    // Implements all Log interface methods with Log4J 2 ExtendedLogger
}

// SLF4J implementation (when SLF4J is available) 
private static class Slf4jLog<T extends Logger> implements Log, Serializable {
    public Slf4jLog(T logger);
    // Implements all Log interface methods with SLF4J Logger
}

// SLF4J with location awareness (when LocationAwareLogger is available)
private static class Slf4jLocationAwareLog extends Slf4jLog<LocationAwareLogger> {
    public Slf4jLocationAwareLog(LocationAwareLogger logger);
    // Implements all Log interface methods with location-aware SLF4J logging
}

// Java Util Logging implementation (fallback)
private static class JavaUtilLog implements Log, Serializable {
    public JavaUtilLog(String name);
    // Implements all Log interface methods with java.util.logging.Logger
}

Note: These internal classes are implementation details and should not be used directly. Use LogFactory.getLog() methods instead.

Framework Detection

Spring JCL automatically detects and prioritizes logging frameworks through the LogAdapter class in this order:

  1. Log4J 2 with SLF4J Bridge Detection - If both org.apache.logging.log4j.spi.ExtendedLogger and org.apache.logging.slf4j.SLF4JProvider are detected along with org.slf4j.spi.LocationAwareLogger, it uses SLF4J with location awareness to avoid the log4j-to-slf4j bridge conflict
  2. Log4J 2 Direct - Uses org.apache.logging.log4j.spi.ExtendedLogger directly when available (and no SLF4J bridge detected)
  3. SLF4J with Location Awareness - Uses org.slf4j.spi.LocationAwareLogger when available
  4. SLF4J Basic - Uses org.slf4j.Logger when available
  5. Java Util Logging - Falls back to java.util.logging.Logger as default

The detection is automatic and requires no configuration. The LogAdapter uses Class.forName() to detect available logging frameworks on the classpath.

Error Handling

Spring JCL handles logging framework detection failures gracefully:

  • ClassNotFoundException: Framework not available during Class.forName() check, tries next option
  • NoClassDefFoundError: Framework partially available during Class.forName() check, tries next option
  • Any Throwable during detection: Catches all exceptions during Class.forName() and continues to next framework
  • Service Discovery Issues: LogFactoryService prints warning about commons-logging.jar conflicts and continues
  • SimpleLog Usage: Prints deprecation warning and continues with NoOpLog behavior

No exceptions are thrown during logger creation - the system always provides a working logger instance, falling back to java.util.logging if all other frameworks fail.

Best Practices

  • Framework Usage: Spring JCL is designed for Spring Framework internal logging. For application code, prefer direct use of Log4J 2, SLF4J, or java.util.logging
  • Performance: Use level check methods (isDebugEnabled(), etc.) before expensive string operations
  • Class-based Loggers: Prefer LogFactory.getLog(Class.class) over string names for better IDE support
  • Exception Logging: Always include the exception as the second parameter for proper stack trace logging
  • Avoid Deprecated Methods: Use LogFactory.getLog() instead of deprecated getInstance() methods