2

In my project I use slf4j,

The project includes one library that uses org.apache.logging.log4j:log4j-api:2.14.0

Therefore, the library gets its logger via org.apache.logging.log4j.LogManager.getLogger(abc.class)

I include log4j-to-slf4j-2.x in my project. However, looking at the contents of log4j-to-slf4j-2.x shows no implementation for that class.

Naturally my project dies at runtime saying with NoClassDefFound org/apache/logging/log4j/LogManager

What am I missing?

THIS IS NOT A DUPLICATE OF Is there an adapter for log4j2 to work over slf4j? because I have a specific problem that requires a different solution than the one presented in the linked question. This question needs to be addressed separately. Please stop with the nonsense closing if you don't understand what is going on!

David Hofmann
  • 5,683
  • 12
  • 50
  • 78
  • @Kayaman nailed the problem and solution and that should be an answer, not a comment, but because of people closing questions they don't understand we have a less than perfect Q&A platform. – David Hofmann Jun 30 '21 at 20:28

2 Answers2

5

The log4j-to-slf4j library is meant for situations where you (or a library) are using Log4J to call logger.error() etc., but actually have an SLF4J implementation such as Logback that actually handles the logging (so you've configured appenders and so on in logback.xml for example).

You need to keep using the Log4J library, which is where LogManager class exists, but log4j-to-slf4j becomes an additional layer which will route the logging through to SLF4J and its implementation (e.g. Logback).

enter image description here

Some notes and caveats:

Use of this adapter may cause some loss of performance as the Log4j 2 Messages must be formatted before they can be passed to SLF4J. With Log4j 2 as the implementation these would normally be formatted only when they are accessed by a Filter or Appender.

So you would use log4j-to-slf4j in a situation like code using Log4J (such as a library) needs to be integrated into a bigger codebase using SLF4J for logging, or a similar situation where one codebase uses "raw" logging (directly accesses LogManager) and the other uses SLF4J, and you can't modify the code easily.

Use of the SLF4J adapter (log4j-to-slf4j-2.x.jar) together with the SLF4J bridge (log4j-slf4j-impl-2.x.jar) should never be attempted as it will cause events to endlessly be routed between SLF4J and Log4j 2.

So as Log4J is an SLF4J implementation, it's possible to create a situation where program will log with Log4J, bridge over to SLF4J, which will bridge over to SLF4J implementation (Log4J)...which will again bridge over to SLF4J and so on, ad infinitum.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
-2

You will have to use the LoggerFactory interface to get the logger

private static Logger logger = LoggerFactory.getLogger(SLF4JExample.class);

This way it will work in every case either with log4j or slf4j

41 72 6c
  • 1,600
  • 5
  • 19
  • 30
anish sharma
  • 568
  • 3
  • 5
  • The point of the bridging libraries is that you don't have to modify the code, so saying to change the code is not useful. – Andreas Jun 30 '21 at 17:42
  • 1
    Bridging works on basis of use of common interfaces, you used a concrete implementation which is not the right way – anish sharma Jun 30 '21 at 17:55
  • Thanks @anishsharma for the insight. But `LoggerFactory` is not a class inside `log4j-api:2.14.0` either – David Hofmann Jun 30 '21 at 18:21
  • 1
    @DavidHofmann `org.slf4j.LoggerFactory` is [SLF4J](http://www.slf4j.org/). `org.apache.logging.log4j.LogManager` is [Log4j 2](https://logging.apache.org/log4j/2.x/). `org.apache.log4j.LogManager` is [Log4j 1](https://logging.apache.org/log4j/1.2/). `org.apache.commons.logging.LogFactory` is [Apache Commons Logging](https://commons.apache.org/proper/commons-logging/). – Andreas Jun 30 '21 at 18:49
  • use can use log4j-over-slf4j-2.0.0-alpha1 as a maven depedency it has LogManager so this will work for you – anish sharma Jun 30 '21 at 18:54
  • @anishsharma You misunderstood which *bridging* libraries I was talking about. I wasn't taking about a logging *facade* like SLF4J or Commons Logging, I was talking about the bridging libraries that *redirect* calls of one API to another, e.g. SLF4J → Log4j 1, SLF4J → Log4j 2, SLF4J → Logback, Common Logging → SLF4J, Log4j 1 → SLF4J, Log4j 2 → SLF4J, ... There are bridges available for just about any combination of logging APIs. – Andreas Jun 30 '21 at 18:55
  • log4j-over-slf4j.jar will in turn delegate all log4j API calls to their SLF4J equivalents – anish sharma Jun 30 '21 at 18:57