0
# Spring JCL
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: org.springframework:spring-jcl
7
- **Package Type**: Maven
8
- **Language**: Java
9
- **Installation**:
10
```xml
11
<dependency>
12
<groupId>org.springframework</groupId>
13
<artifactId>spring-jcl</artifactId>
14
<version>6.2.8</version>
15
</dependency>
16
```
17
18
Gradle:
19
```gradle
20
implementation 'org.springframework:spring-jcl:6.2.8'
21
```
22
23
## Core Imports
24
25
```java
26
import org.apache.commons.logging.Log;
27
import org.apache.commons.logging.LogFactory;
28
```
29
30
For implementation classes (optional):
31
```java
32
import org.apache.commons.logging.LogFactoryService;
33
import org.apache.commons.logging.impl.NoOpLog;
34
import org.apache.commons.logging.impl.SimpleLog;
35
```
36
37
Internal classes (not typically imported directly):
38
```java
39
import org.apache.commons.logging.LogAdapter;
40
```
41
42
## Basic Usage
43
44
```java
45
import org.apache.commons.logging.Log;
46
import org.apache.commons.logging.LogFactory;
47
48
public class MyService {
49
private static final Log logger = LogFactory.getLog(MyService.class);
50
51
public void doSomething() {
52
logger.info("Starting operation");
53
54
try {
55
// Your code here
56
logger.debug("Operation in progress");
57
} catch (Exception e) {
58
logger.error("Operation failed", e);
59
throw e;
60
}
61
62
logger.info("Operation completed");
63
}
64
}
65
```
66
67
## Architecture
68
69
Spring JCL is built around several key components:
70
71
- **LogFactory**: Main entry point providing static factory methods for logger creation
72
- **Log Interface**: Commons Logging compatible interface with six logging levels (trace, debug, info, warn, error, fatal)
73
- **LogAdapter**: Internal adapter that automatically detects available logging frameworks (Log4J 2, SLF4J, java.util.logging)
74
- **Framework Implementations**: Bridge implementations for Log4J 2, SLF4J (with location awareness), and java.util.logging
75
- **Compatibility Layer**: Deprecated classes maintaining binary compatibility with Apache Commons Logging
76
77
## Capabilities
78
79
### Logger Factory
80
81
Creates logger instances with automatic framework detection and optimization.
82
83
```java { .api }
84
/**
85
* Main factory class for obtaining Log instances with automatic adapter detection
86
*/
87
public abstract class LogFactory {
88
/**
89
* Convenience method to return a named logger
90
* @param clazz containing Class from which a log name will be derived
91
* @return Log instance for the class
92
*/
93
public static Log getLog(Class<?> clazz);
94
95
/**
96
* Convenience method to return a named logger
97
* @param name logical name of the Log instance to be returned
98
* @return Log instance for the name
99
*/
100
public static Log getLog(String name);
101
}
102
```
103
104
**Deprecated Methods** (for compatibility):
105
```java { .api }
106
/**
107
* @deprecated in favor of getLog(Class)/getLog(String)
108
*/
109
@Deprecated
110
public static LogFactory getFactory();
111
112
/**
113
* @deprecated in favor of getLog(Class)
114
*/
115
@Deprecated
116
public Log getInstance(Class<?> clazz);
117
118
/**
119
* @deprecated in favor of getLog(String)
120
*/
121
@Deprecated
122
public Log getInstance(String name);
123
124
/**
125
* @deprecated no-op method for compatibility
126
*/
127
@Deprecated
128
public static void release(ClassLoader classLoader);
129
130
/**
131
* @deprecated no-op method for compatibility
132
*/
133
@Deprecated
134
public static void releaseAll();
135
136
/**
137
* @deprecated utility method for object identification
138
* Returns string representation with class name and identity hash code
139
*/
140
@Deprecated
141
public static String objectId(Object o);
142
143
// Abstract methods (for subclass implementation)
144
/**
145
* @deprecated abstract method for attribute access
146
*/
147
@Deprecated
148
public abstract Object getAttribute(String name);
149
150
/**
151
* @deprecated abstract method for attribute name retrieval
152
*/
153
@Deprecated
154
public abstract String[] getAttributeNames();
155
156
/**
157
* @deprecated abstract method for attribute removal
158
*/
159
@Deprecated
160
public abstract void removeAttribute(String name);
161
162
/**
163
* @deprecated abstract method for attribute setting
164
*/
165
@Deprecated
166
public abstract void setAttribute(String name, Object value);
167
168
/**
169
* @deprecated abstract method for factory release
170
*/
171
@Deprecated
172
public abstract void release();
173
```
174
175
### Logging Interface
176
177
Core logging interface providing six logging levels with conditional checks for performance.
178
179
```java { .api }
180
/**
181
* A simple logging interface abstracting logging APIs
182
*/
183
public interface Log {
184
// Level check methods (for performance optimization)
185
boolean isFatalEnabled();
186
boolean isErrorEnabled();
187
boolean isWarnEnabled();
188
boolean isInfoEnabled();
189
boolean isDebugEnabled();
190
boolean isTraceEnabled();
191
192
// Fatal level logging
193
void fatal(Object message);
194
void fatal(Object message, Throwable t);
195
196
// Error level logging
197
void error(Object message);
198
void error(Object message, Throwable t);
199
200
// Warn level logging
201
void warn(Object message);
202
void warn(Object message, Throwable t);
203
204
// Info level logging
205
void info(Object message);
206
void info(Object message, Throwable t);
207
208
// Debug level logging
209
void debug(Object message);
210
void debug(Object message, Throwable t);
211
212
// Trace level logging
213
void trace(Object message);
214
void trace(Object message, Throwable t);
215
}
216
```
217
218
**Usage Examples:**
219
220
```java
221
// Performance-optimized logging
222
if (logger.isDebugEnabled()) {
223
logger.debug("Processing user: " + user.getName() + " with ID: " + user.getId());
224
}
225
226
// Exception logging
227
try {
228
processData();
229
} catch (DataProcessingException e) {
230
logger.error("Failed to process data for user: " + userId, e);
231
throw e;
232
}
233
234
// Different logging levels
235
logger.trace("Entering method with params: " + params);
236
logger.debug("Intermediate calculation result: " + result);
237
logger.info("User " + username + " logged in successfully");
238
logger.warn("Deprecated API usage detected in class: " + className);
239
logger.error("Database connection failed", connectionException);
240
logger.fatal("System is shutting down due to critical error", criticalError);
241
```
242
243
### Service Implementation
244
245
Fallback service implementation for META-INF service discovery compatibility when commons-logging.jar is accidentally on classpath.
246
247
```java { .api }
248
/**
249
* @deprecated since it is only meant to be used in fallback scenario when commons-logging.jar is accidentally on classpath
250
*/
251
@Deprecated
252
public class LogFactoryService extends LogFactory {
253
/**
254
* Constructor that prints compatibility warning about commons-logging.jar conflicts
255
* Prints message: "Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts"
256
*/
257
public LogFactoryService();
258
259
/**
260
* Get logger instance for class - delegates to LogAdapter.createLog()
261
* @param clazz containing Class from which a log name will be derived
262
* @return Log instance for the class
263
*/
264
public Log getInstance(Class<?> clazz);
265
266
/**
267
* Get logger instance by name - delegates to LogAdapter.createLog()
268
* @param name logical name of the Log instance to be returned
269
* @return Log instance for the name
270
*/
271
public Log getInstance(String name);
272
273
// Attribute management methods (for compatibility) - uses ConcurrentHashMap
274
/**
275
* Set attribute value (null values remove the attribute)
276
*/
277
public void setAttribute(String name, Object value);
278
279
/**
280
* Remove attribute by name
281
*/
282
public void removeAttribute(String name);
283
284
/**
285
* Get attribute value
286
* @return attribute value or null if not found
287
*/
288
public Object getAttribute(String name);
289
290
/**
291
* Get all attribute names
292
* @return array of attribute names
293
*/
294
public String[] getAttributeNames();
295
296
/**
297
* Release resources - no-op method for compatibility
298
*/
299
public void release();
300
}
301
```
302
303
### Implementation Classes
304
305
Basic logger implementations for specific use cases.
306
307
```java { .api }
308
/**
309
* Trivial implementation of Log that throws away all messages
310
*/
311
public class NoOpLog implements Log, Serializable {
312
public NoOpLog();
313
public NoOpLog(String name);
314
315
// All methods return false for level checks and are no-op for logging methods
316
}
317
318
/**
319
* @deprecated in spring-jcl (effectively equivalent to NoOpLog)
320
*/
321
@Deprecated
322
public class SimpleLog extends NoOpLog {
323
/**
324
* Constructor that prints deprecation warning
325
* Prints message: "SimpleLog is deprecated and equivalent to NoOpLog in spring-jcl. Use a standard LogFactory.getLog(Class/String) call instead."
326
* @param name logger name
327
*/
328
public SimpleLog(String name);
329
}
330
```
331
332
## Types
333
334
```java { .api }
335
/**
336
* Main logging interface with six levels: trace, debug, info, warn, error, fatal
337
*/
338
public interface Log {
339
// See Logging Interface section above for complete method signatures
340
}
341
342
/**
343
* Abstract factory class for obtaining Log instances
344
*/
345
public abstract class LogFactory {
346
// See Logger Factory section above for complete method signatures
347
}
348
349
/**
350
* Service implementation extending LogFactory for compatibility
351
* @deprecated only for fallback compatibility scenarios
352
*/
353
@Deprecated
354
public class LogFactoryService extends LogFactory {
355
// See Service Implementation section above for complete method signatures
356
}
357
358
/**
359
* No-operation logger implementation
360
*/
361
public class NoOpLog implements Log, java.io.Serializable {
362
// See Implementation Classes section above for complete method signatures
363
}
364
365
/**
366
* @deprecated Simple logger implementation (equivalent to NoOpLog)
367
*/
368
@Deprecated
369
public class SimpleLog extends NoOpLog {
370
// See Implementation Classes section above for complete method signatures
371
}
372
```
373
374
### LogAdapter (Internal)
375
376
Internal adapter class that handles automatic logging framework detection and logger creation.
377
378
```java { .api }
379
/**
380
* Internal adapter class for framework detection and logger creation
381
* This class is not part of the public API but is referenced by LogFactory
382
*/
383
final class LogAdapter {
384
/**
385
* Create Log instance using detected logging framework
386
* @param name the logger name
387
* @return Log instance using the best available logging framework
388
*/
389
public static Log createLog(String name);
390
}
391
```
392
393
**Internal Implementation Classes:**
394
395
```java { .api }
396
// Log4J 2 implementation (when Log4J 2 is available)
397
private static class Log4jLog implements Log, Serializable {
398
public Log4jLog(String name);
399
// Implements all Log interface methods with Log4J 2 ExtendedLogger
400
}
401
402
// SLF4J implementation (when SLF4J is available)
403
private static class Slf4jLog<T extends Logger> implements Log, Serializable {
404
public Slf4jLog(T logger);
405
// Implements all Log interface methods with SLF4J Logger
406
}
407
408
// SLF4J with location awareness (when LocationAwareLogger is available)
409
private static class Slf4jLocationAwareLog extends Slf4jLog<LocationAwareLogger> {
410
public Slf4jLocationAwareLog(LocationAwareLogger logger);
411
// Implements all Log interface methods with location-aware SLF4J logging
412
}
413
414
// Java Util Logging implementation (fallback)
415
private static class JavaUtilLog implements Log, Serializable {
416
public JavaUtilLog(String name);
417
// Implements all Log interface methods with java.util.logging.Logger
418
}
419
```
420
421
**Note:** These internal classes are implementation details and should not be used directly. Use `LogFactory.getLog()` methods instead.
422
423
## Framework Detection
424
425
Spring JCL automatically detects and prioritizes logging frameworks through the LogAdapter class in this order:
426
427
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
428
2. **Log4J 2 Direct** - Uses `org.apache.logging.log4j.spi.ExtendedLogger` directly when available (and no SLF4J bridge detected)
429
3. **SLF4J with Location Awareness** - Uses `org.slf4j.spi.LocationAwareLogger` when available
430
4. **SLF4J Basic** - Uses `org.slf4j.Logger` when available
431
5. **Java Util Logging** - Falls back to `java.util.logging.Logger` as default
432
433
The detection is automatic and requires no configuration. The LogAdapter uses Class.forName() to detect available logging frameworks on the classpath.
434
435
## Error Handling
436
437
Spring JCL handles logging framework detection failures gracefully:
438
439
- **ClassNotFoundException**: Framework not available during Class.forName() check, tries next option
440
- **NoClassDefFoundError**: Framework partially available during Class.forName() check, tries next option
441
- **Any Throwable during detection**: Catches all exceptions during Class.forName() and continues to next framework
442
- **Service Discovery Issues**: LogFactoryService prints warning about commons-logging.jar conflicts and continues
443
- **SimpleLog Usage**: Prints deprecation warning and continues with NoOpLog behavior
444
445
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.
446
447
## Best Practices
448
449
- **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
450
- **Performance**: Use level check methods (`isDebugEnabled()`, etc.) before expensive string operations
451
- **Class-based Loggers**: Prefer `LogFactory.getLog(Class.class)` over string names for better IDE support
452
- **Exception Logging**: Always include the exception as the second parameter for proper stack trace logging
453
- **Avoid Deprecated Methods**: Use `LogFactory.getLog()` instead of deprecated `getInstance()` methods