Issues replacing Log4j with LogBack, log4j-over-slf4j.jar shortcomings - java

So I've been porting some of our services to use Logback over log4j and I've been using the log4j-over-slf4j jar to spoof log4j for our legacy dependencies. The only issue is log4j-over-slf4j doesn't implement many of the classes of log4j so I'm seeing a decent few class not found exceptions from dependent jars. How have people got around this? Is it enough to just put the nlog4j in your classpath instead of the log4j-over-slf4j jar? I haven't tested this last idea yet but I'm planning on it tomorrow.
Reference:
http://www.slf4j.org/legacy.html
http://www.slf4j.org/nlog4j/

The only issue is log4j-over-slf4j doesn't implement many of the classes of log4j so I'm seeing a decent few class not found exceptions from dependent jars. How have people got around this?
Well, I guess you're facing "problems" explicitly mentioned in the Bridging legacy APIs link you posted:
When does it not work?
The log4j-over-slf4j module will not
work when the application calls log4j
components that are not present in the
bridge. For example, when application
code directly references log4j
appenders, filters or the
PropertyConfigurator, then
log4j-over-slf4j would be an
insufficient replacement for log4j.
However, when log4j is configured
through a configuration file, be it
log4j.properties or log4j.xml, the
log4j-over-slf4j module should just
work fine.
If the dependent JARs are under your control, you should really try to migrate the code using the SLF4J Migrator tool.
Is it enough to just put the nlog4j in your classpath instead of the log4j-over-slf4j jar?
This might solve the ClassNotFoundException but I wonder how the whole logging is going to work. And given that NLog4J is no longer actively developed, I wonder if this is a good long term solution.

Related

Was slf4j affected with vulnerability issue in log4j

I have implemented a POC and have used slf4j for logging. The zero day vulnerability issue in log4j, did that also impact slf4j logs?
Depends on the underlying implementation of SLF4J.
log4j 1.x is safe with respect to CVE-2021-44228. Thus, if your SLF4J provider/binding is slf4j-log4j12.jar, you are safe regarding CVE-2021-44228.
If you are using log4j-over-slf4j.jar in conjunction with the SLF4J API, you are safe unless the underlying implementation is log4j 2.x.
Check this - http://slf4j.org/log4shell.html
It depends. Slf4j is just an api, that can be using behind any of its implementions, being log4j just one. Check which one is using on the back, and if this is log4j and between versions 2.0.0 and 2.15.0 (2.15.0 is the one with the fix, versions 1.x are not affected) you should update it (if it is exposed to users directly or indirectly)
According to Apache, "only the log4j-core JAR file is impacted by this vulnerability. Applications using only the log4j-api JAR file without the log4j-core JAR file are not impacted by this vulnerability.
Also Apache Log4j is the only Logging Services subproject affected by this vulnerability. Other projects like Log4net and Log4cxx are not impacted by this."
So you should be safe, as long as you do not use log4j-core package.
[,1.7.26),[1.8.0-alpha0,1.8.0-beta2) has Vulnerabilities. Please follow the link https://snyk.io/vuln/maven:org.slf4j:slf4j-ext

Is there reason to avoid slf4j?

Digging into some Java logging stuff, and question about slf4j. It seems awfully convenient, always doing the logging same way in .java files, worrying only about logger name, then doing all logging configuration by having right .jar and .properties/.xml files.
What are the reasons to use or not to use slf4j by default in any project?
In this particular case, log4j will actually doing the logging (some to file, some to stdout, some to database), and it is a maven project.
I'm hoping for simple "yeah, go for it" or "no, using slf4j is asking for trouble X" from somebody with experience.
We have been logging over the SLF4J API for 1.5 years now. Before that we used log4j directly. Now we use jboss.logging, with a logback intermezzo and had to change zero lines in our code for all the framework changing.
So, go for it ;)
Definitely use slf4j. It's the standard common logging interface of today and it finally does it right regarding the plugging in of actual logging implementations. Logback as the implementation is highly recommended, it is the successor of log4j, done by the same guy who quit log4j to it from the start, but straightening out the issues that couldn't be straightened out in log4j.
Ok, I actually ended up not using slf4j, but instead using log4j directly, because slf4j just kept on using JDK14LoggerAdapter instead of Log4jLoggerAdapter or LogBack, and I got fed up trying to get it to work by tweaking dependencies...
The project in question is Jenkins plugin built with Maven2, that may have been the reason of complications. It really did not work by "just put these dependencies to .pom".
So, to answer my own question, a reason to not use slf4j is: less moving parts, less dependencies, less manuals and docs to read through, less questions to ask at SO/mailing lists.

How do I set up commons-logging to use logback?

We use slf4j + logback, and happened to have some third-party libraries which use commons-logging. How do I set it up to use logback?
The answer is to not use commons-logging.jar, since SLF4J was designed to do what commons-logging does but better. As #MahdeTo refers to, you need to use jcl-over-slf4j.jar.
Check out the documentation from the slf4j website on migrating from commons-logging.
I come across this question too, and found out jcl-over-slf4j.jar indeed can solve the problem, I couldn't understand that why commons-logging couldn't use logback automatically, since commons-logging is log interface and logback is implementation, they should integrate automatically, until I found this:
The Apache Commons Logging (JCL) provides a Log interface that is
intended to be both light-weight and an independent abstraction of
other logging toolkits. It provides the middleware/tooling developer
with a simple logging abstraction, that allows the user (application
developer) to plug in a specific logging implementation.
JCL provides thin-wrapper Log implementations for other logging tools,
including Log4J, Avalon LogKit (the Avalon Framework's logging
infrastructure), JDK 1.4, and an implementation of JDK 1.4 logging
APIs (JSR-47) for pre-1.4 systems. The interface maps closely to Log4J
and LogKit.
Obviously not all the log interface can integrate nicely with log implementation which mean, if you really want to use logback, jcl-over-slf4j.jar is your only solution now because JCL only support Log4J, Logkit, JDK 1.4.
Just add jcl-over-slf4j to the dependencies of your project (check current version at https://search.maven.org/search?q=g:org.slf4j%20AND%20a:jcl-over-slf4j&core=gav)
for those all who wants to keep the final package size smaller; checkout
mvn dependency:tree result of your project and if any dependency to commons-logging exists, exclude them as well. Since the jcl-over-slf4j.jar contains both Log and LogFactory classes with exact same package structure, these commons-logging jars will be extra on your final package.

Java: Libraries within Libraries and Classpath Issues

We are having a discussion at work and an interesting point came up:
Say you are developing a small library, call it somelib. Say that somelib needs to do some logging, but you don't want to reinvent the wheel, so you decide to use a 3rd party logging library.
Additionally, you want to make integration of somelib as painless as possible, so you distribute a single JAR file (somelib.jar), which has the other logging JAR, call it logger.jar, embedded inside of it. Much like what Maven's jar-with-dependencies assembly does.
Now comes the issue. Since your product is a library, what if your customer is using somelib and also happen to be using a different version of the same logging library on their own. Now we have a classpath problem.
This seems to me like it would be a common problem for people that write libraries, so what is the typical solution?
Do they avoid using JAR bundling methods altogether? Even if we do that, there is still an issue with a user's code expecting version X of the logging library, and somelib's code expecting version Y.
Do they somehow insert a dummy package prefix so that the logger classes in somelib won't conflict?
What about dynamic loading of the logger library? (though this still has versioning problems from 1.)
You may consider to use OSGI or wait for JDK 8 and its Jigsaw project.

SLF4J, Common Logging, console output

I have this 3rd party library that has:
slf4j-api-1.5.5.jar
slf4j-jdk14-1.5.5.jar
jcl-over-slf4j-1.5.5.jar
I want to write some tests against this library and see its log output, and I don't want to add any more logging libraries (no log4j or anything else).
I understand that SLF4J and Common Logging are both logging abstractions so I probably need to write my own simple concrete logger (or maybe not, since jcl-over-slf4j includes org.apache.commons.logging.impl.SimpleLog?). If so, what interfaces should I implement, and more importantly, how do I set up SL4J/Common Logging to use my logger in my test? I read in the SLF4J docs that I have to modify the StaticLoggerBinder class... does that really mean that I actually have to download SLF4J sources, modify the class and recompile it?
We use SLF4J. It's very useful but several of the jars have confusing names and it's not real clear starting out to know which ones are incompatible.
SLF4J is the API you use for logging in your code (e.g. log.info("blah"). However, SLF4J has no configuration aspect to it. At runtime you add exactly one jar to the classpath that binds the API to the 'real' logging subsystem. If you want to use Log4J, add slf4j-log4j.jar or the StaticBinder jar for Simple or JDK, or Logback. You configure any of these logging implementations as you normally would without SLF4J.
There are several SLF4J modules available to redirect existing logging statements written using the APIs of Log4J, Apache Commons Logging, and java.util.logging to SLF4J. This allows you to setup a single logging configuration for all these disperate implementations. (This is very useful to avoid configuring both, say, Log4J and JUL if you have libraries that bind directly to any legacy logging framework.)
The SLF4J legacy page explains these concepts in depth. Heck, there is even a module to redirect Sysout.out/err to SFL4J.
To more directly answer your question: sure you can write your own logging implementation to go under SLF4J; but the only reason to do so is because you are already locked into some homegrown craptastic logging framework.
If you want to keep it simple, use the built-in (as of jdk 1.4) logger
https://docs.oracle.com/en/java/javase/19/docs/api/java.logging/java/util/logging/Logger.html
the jdk binding jar comes with slf4j. you want to make sure the jar is deployed to your webapp WEB-INF/lib dir or just in your classpath otherwise. See (slf4j.org/faq.html#where_is_binding) and this (slf4j.org/faq.html) for more information.
the jar you want to add to your classpath is slf4j-jdk14.jar. Note that the jdk logger is already available, this jar is the link between the slf4j interfaces and the chosen logger implementation. the jdk logging binding jar comes with the slf4j distribution. this should do it for you.
Your question leds me to believe that you have not read the the SLF4J user manual. It's a very short document. If after reading the document you still have the same question, then the document fails its purpose and needs to be clarified.
Anyways, you don't need to implement your own Logger class. Just use slf4j-simple which ships with SLF4J.

Categories

Resources