The standard way to use SLF4J is that it's the main logging framework that you use. (You call methods defined within the slf4j-api
.) It, in turn, uses a "binding" such as slf4j-log4j12
which tells it how to talk to the "real" logging framework. And then you also need to have the real logging framework on your classpath, such as "log4j" version 1.2.
Some newer logging libraries, such as Logback, are both the "binding" and the "real" framework, so if you want to use that as your logging framework, you only need logback-classic
along with slf4j-api
, so it's two libraries rather than three.
The confusing "over" and "to" libraries exist as a way to deal with the reality that you probably depend on libraries that want to log in a different way than the way you've selected for your application, but it's nice to have everything directed into one framework. So, if you're using SLF4J and Logback, but you're depending on a library which logs using Log4j 1.2, you want to include the log4j-over-slf4j
library, which will "intercept" any Log4j calls within any libraries in your application and translate them to be logged by SLF4J instead. Conversely, if you're logging with Log4j 1.2 directly (without SLF4J) and need to call a library that's using SLF4J, you're going to want to include the slf4j-log4j12
library to intercept those calls and translate them to Log4j for you. There are a variety of these kinds of libraries, each to intercept and translate from one particular logging framework to another.
But your question was "So, which combination and version should I choose?", which is rather broad, as we're not sure what it is that you're trying to do. Selecting a logging framework is like any other technology framework decision, based on a lot of things like developer familiarity, what the systems you need to integrate with are using, and if there are any existing code or standards which one wants to stay consistent with. So, I'm going to try to avoid getting into that selection process too much, and answer your question about how to set up Maven to use SLF4J as your logging framework, backed by Log4j version 2:
- Add a dependency for the current version of slf4j-api
Add a dependency for Log4j 2 and its SLF4J binding (From https://logging.apache.org/log4j/2.x/maven-artifacts.html):
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
- Use
<dependencyManagement>
sections in your POM to ensure that all your dependencies use the same version of your logging framework. (For instance, many libraries will include slf4j-api
as a dependency, but they may each use a different version.) Generally logging frameworks keep good compatibility between versions, so you generally want to override all the supplied dependency versions with the (usually newer) one that you're using.
- If you have any libraries that are using other logging framework, use the appropriate interceptor bridge to redirect its logging, either one from Log4j 2 that will redirect it straight to Log4Jj 2, or one from SLF4J which will redirect to SLF4J, which will then be further directed to Log4j. (While it may seem to do redirect twice, it could make things easier if you were to keep SLF4J but change to another "real" logging framework at some point. Maybe.) For instance, if you have a library that uses commons-logging, you want to include
jcl-over-slf4j
instead.
- Also, use the maven-enforcer-plugin's
bannedDependencies
rules to ensure that you're excluding any logging frameworks that you're not using that the libraries you're depending on are trying to bring into your project. That is, for that example I gave of a library you depend on that uses commons-logging
, you need to <exclude>
commons-logging
from that library dependency, and add it to your bannedDependencies
list to ensure that you don't accidentally get it again from some other library. Otherwise, you'll have both the "real" commons-logging as well as your fake bridge (that emulates the interface and translates to your real logging framework) on the classpath, and will run into trouble.
I hope that overview helps. Note I haven't actually tried running Log4j 2 in anything yet, and just got those dependencies from their documentation. Definitely test that everything's working the way you expect.