Suppress deprecation warning on JDK 9 (for LogRecord.setMillis)
Includes revised Log methods in log level order, with consistent delegation of fatal->error for log level checks in SLF4J and JUL, a JavaUtilDelegate for defensive access to java.logging on JDK 9, support for LogRecord message objects, as well as revised log setup recommendations.
Issue: SPR-15453
Issue: SPR-14512
@ -41,9 +41,9 @@ Examples of how you, as an application developer, can benefit from the Spring pl
@@ -41,9 +41,9 @@ Examples of how you, as an application developer, can benefit from the Spring pl
* Make a Java method execute in a database transaction without having to deal with
transaction APIs.
* Make a local Java method a remote procedure without having to deal with remote APIs.
* Make a local Java method a management operation without having to deal with JMX APIs.
* Make a local Java method a message handler without having to deal with JMS APIs.
* Make a local Java method an HTTP endpoint without having to deal with the Servlet API.
* Make a local Java method a message handler without having to deal with the JMS API.
* Make a local Java method a management operation without having to deal with the JMX API.
formats]). For Maven users, the minimal dependencies needed are:
formats]). For Maven users, the minimal dependency needed is:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
@ -772,17 +663,13 @@ formats]). For Maven users, the minimal dependencies needed are:
@@ -772,17 +663,13 @@ formats]). For Maven users, the minimal dependencies needed are:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>2.7</version>
<version>2.8.2</version>
</dependency>
</dependencies>
----
If you also wish to use SLF4J, the following dependencies are also needed:
If you also wish to enable SLF4J to delegate to Log4j, e.g. for other libraries
which use SLF4J by default, the following dependency is also needed:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
@ -791,7 +678,7 @@ If you also wish to use SLF4J, the following dependencies are also needed:
@@ -791,7 +678,7 @@ If you also wish to use SLF4J, the following dependencies are also needed:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version>
<version>2.8.2</version>
</dependency>
</dependencies>
----
@ -817,25 +704,68 @@ Here is an example `log4j2.xml` for logging to the console:
@@ -817,25 +704,68 @@ Here is an example `log4j2.xml` for logging to the console:
</Configuration>
----
[[overview-native-jcl]]
====== Runtime Containers with Native JCL
Many people run their Spring applications in a container that itself provides an
implementation of JCL. IBM Websphere Application Server (WAS) is the archetype. This
often causes problems, and unfortunately there is no silver bullet solution; simply
excluding `commons-logging` from your application is not enough in most situations.
To be clear about this: the problems reported are usually not with JCL per se, or even
with `commons-logging`: rather they are to do with binding `commons-logging` to another
framework (often Log4j). This can fail because `commons-logging` changed the way they do
the runtime discovery in between the older versions (1.0) found in some containers and
the modern versions that most people use now (1.1). Spring does not use any unusual
parts of the JCL API, so nothing breaks there, but as soon as Spring or your application
tries to do any logging you can find that the bindings to Log4j are not working.
[[overview-logging-slf4j]]
===== Using SLF4J with Logback
In such cases with WAS the easiest thing to do is to invert the class loader hierarchy
(IBM calls it "parent last") so that the application controls the JCL dependency, not
the container. That option isn't always open, but there are plenty of other suggestions
in the public domain for alternative approaches, and your mileage may vary depending on
the exact version and feature set of the container.
The Simple Logging Facade for Java (http://www.slf4j.org[SLF4J]) is a popular API
used by other libraries commonly used with Spring. It is typically used with
https://logback.qos.ch/[Logback] which is a native implementation of the SLF4J API
and therefore autodetected by Spring when added to the application classpath:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
----
Alternatively, you may also configure SLF4J to delegate to Log4j (see above) or to
JUL, in particular for other libraries which use SLF4J by default. Note that it is
not important for all libraries to go through the same logging facade; it only
matters that they eventually delegate to the same log provider. So while Spring may
go to Log4j directly, other libraries may go through the SLF4J binding for Log4j,
or analogously for JUL.
[[overview-logging-jul]]
===== Using JUL (java.util.logging)
Spring will delegate to `java.util.logging` by default, provided that no Log4j or
SLF4J API is detected in the classpath. So there is no special dependency to set up:
just use Spring with no external dependency for log output to `java.util.logging`,
either in a standalone application (with a custom or default JUL setup at the JDK
level) or with an application server's log system (and its system-wide JUL setup).
Note that the `java.logging` module is NOT present by default on JDK 9, since it is
not included in `java.base`. This works fine when using Spring with Log4j or SLF4J
since the JUL API is not referenced in such a scenario. However, when choosing to
use JUL as a default log provider, remember to activate the `java.logging` module.
[[overview-logging-websphere]]
===== Commons Logging on WebSphere
Spring applications may run on a container that itself provides an implementation of
JCL, e.g. IBM's WebSphere Application Server (WAS). This does not cause issues per se
but leads to two different scenarios that need to be understood:
In a "parent first" ClassLoader delegation model (the default on WAS), applications
will always pick up the server-provided version of Commons Logging, delegating to the
WAS logging subsystem (which is actually based on JUL). An application-provided variant
of JCL, whether Spring 5's or the JCL-over-SLF4J bridge, will effectively be ignored,
along with any locally included log provider.
With a "parent last" delegation model (the default in a regular Servlet container but
an explicit configuration option on WAS), an application-provided Commons Logging
variant will be picked up, enabling you to set up a locally included log provider,
e.g. Log4j or Logback, within your application. In case of no local log provider,
Spring (like regular Commons Logging) will delegate to JUL by default, effectively
logging to WebSphere's logging subsystem like in the "parent first" scenario.
All in all, we recommend deploying Spring applications in the "parent last" model
since it naturally allows for local providers as well as the server's log subsystem.