Difference between Logger.getLogger(className) and LogFactory.getLog(className )? - java

I know its a package difference
1) org.apache.log4j.Logger logger = Logger.getLogger(clazz);
2) org.apache.commons.logging.Log log = LogFactory.getLog(clazz);
The first one uses loggers via log4j and the second one uses commons.logging. We have a huge project where in some classes loggers are configured using log4j and in some cases its commons.logging.
I did find a log4j property file though.Is there a similar property file for commons.logging ? Where do I configure for commons-logging ?. I am unable to see the logs generated by commons-logging.
Any help is appreciated.

Yes, commons-logging is a facade API that was suppose to abstract you from underlying logging framework (in practice there was a choice between log4j and java.util.logging) so that you could switch from one to another without touching the code - just by switching libraries available on the CLASSPATH.
Unfortunately due to some design mistakes it had issues with complex class-loading environments, like application servers. Currently it is effectively superseded by slf4j.
In your case I would recommend sticking with one API - either Log4J or commons-logging, even though commons-logging will (most likely) delegate to log4J. You can also migrate to using SLF4J and install bridging APIs, but this is slightly more advanced.

Related

SLF4j and Logback in Application which can be embeddable

I am using SLF4j and Logback in my application. Now I have the requirement that my application should be embedabble in other applications. This means, that the application can be used as a library in other applications. Everything works as expected except the Logger part. I just can't figure out how to completely disable Logback (this is because the user should bring its own logger implementation). I tried also to find information if it is possible to run Logback in something like a "delegation mode" to allow other SLF4j implementations to hook in, but I did not find anything.
Another approach would be to write a custom Classloader which gets rid of logback when the application starts, but this is very complicated (afaik it is not possible without hacks to remove loaded classes from classloader while the application is running).
Does anyone see a possibility to do this without splitting my application in different modules?
At compile time, you should only have slf4j-api in your classpath.
At runtime, you can choose to add logback in your runtime classpath, and slf4j will use it.
If the other application uses e.g. log4j, they need to add slf4j-log4j instead of logback, as well as slf4j-api and your module.
If they use java.util.logging, they need to add slf4j-jdk14 instead of logback.
In both cases, you might want to tell them which logging categories you use, so they can add it in their log4j or java.util.logging configuration.

Logback native VS Logback via SLF4J

I have gone through the following article regarding the logging frameworks available for Java:
http://michaelandrews.typepad.com/the_technical_times/2011/04/java-logging-reconsidered.html
The author has mentioned using SLF4J with Logback. How is that different from using Logback directly. Wouldn't it be better if one uses Logback directly rather than going for SLF4J, since Logback is built on top of SLF4J.
SLF4J is adding zero overhead to Logback since it is simply the interface that is implemented by Logback without any additional layer.
You should use SLF4J simply because...
It enables you to switch away from Logback if you ever need to
It does not cost you anything, even the imports are smaller ;)
Other people will love you for using SLF4J and hate you for using a specific logging framework directly if you ever release your code into the wild.
The only place where you'd access Logback directly would be while (re)configuring your logging manually in an application. The need for this arises occasionally but even in that case, working with Logback would be restricted to a single class or even method.
As a rule of thumb: libraries should always use a logging abstraction while applications define the logging they are using, optionally accessing it directly.
SLF4J adds almost no overhead and Logback has a native bindings to it.
If you know by 100% that you will not need to switch to other logging framework in the future, go with logback native. But SLF4J allows you some abstraction and you can switch logging backends in a blink.
Logback is not build on top of SLF4J. SLF4J is an abstraction framework for logging. It doesn't do any logging itself. It just provides unified interface for logging.

Baffled by Java Logging Systems with Spring and Hibernate

WHen deploying my Spring / Hibernate application, I get the following warning related to logging:
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
Surprising to me was the lack of information from a Google / SO search. The only thing relevant was this SO post Problem with Commons Logging / Log4j setup in spring webapp with tomcat 6
However, this is even beyond me. Can somebody clarify the logging systems in play here, or point me to a RECENT resource on the matter (there are some ancient google search results that don't really apply). Specifically, the issues I'm wrestling with are:
The distinction among commons-logging, log4j, slf4j and JCL. My understanding is that slf4j is a wrapper, while commons-logging and log4j are actual implementations. I don't know where JCL fits in.
How to configure logging for Spring. What does in the web.xml file, do i need a log4j.properties file or a log4j.xml file? Where does it go, in WEB-INF? Does anything go in my applicationContext.xml file? (sorry but I need to start from zero here).
I am using Hibernate in my project and including via Maven. It seems that Hibernate uses slf4j-simple. I have seen warnings saying that I can't have slf4j-simple and slf4j-log4j both on the classpath. I have not included slf4j-log4j as a dependency, but Hibernate must be including it. How do i solve this problem? Can I force Hibernate to use log4j instead?
Any help would be greatly appreciated. Thanks.
edit:
Thanks for all the answers so far. I am giving these suggestions a try. What about spring web-app specifically? I've seen examples of listeners and parameters and whatnot put into the web.xml file. Is this also required?
commons-logging and SLF4J are both API wrappers around other logging implementations. SLF4J is the more modern of the two, and rather more capable. Log4j is a logging implementation, and pretty much the defacto standard. JUL (short for java.util.logging) is the (generally awful) logging implementation that comes with the JRE. Another log implementation is logback, which is slowly gaining traction, but not at all widespread yet.
log4j.properties and log4j.xml are different ways of configuring log4j, both are equally valid. Which one you use is up to you, although some application servers dictate one or the other. Read the log4j manual to find out how to configure this.
If Hibernate uses SLF4J as its API, that's the choice of the Hibernate developers. However, you can choose which logging implementation SLF4J will delegate to. Again, read the slf4j manual to find out how to select your chosen implementation.
Yes, it's all rather confusing. Given an open choice, SLF4J and Logback is the most capable combination, but you usually don't get an open choice. Different frameworks (like Hibernate and Spring) will potentially use different logging APIs, usually commons-logging or SLF4J, but you can get all those APIs to eventually log to the same underlying implementation (usually log4j).
The distinction among commons-logging, log4j, slf4j and JCL. My understanding is that slf4j is a wrapper, while commons-logging and log4j are actual implementations. I don't know where JCL fits in.
Jakarta Commons Logging (JCL) and Simple Logging Facade for Java SLF4J are both abstractions for various logging frameworks e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time. Commons Logging is known to suffers from class loader problems which is what SLF4J tries to solve (SLF4J is known to be a cleaner library).
Having that said, the fact is that Spring uses Jakarta Commons Logging API (see Logging Dependencies in Spring): Spring is compiled against JCL and Spring makes JCL Log objects available for classes that extend Spring. The is actually the only mandatory external dependency in Spring. This choice has been made because many other frameworks where also using it (e.g. Struts). The idea was to avoid having to have multiple facade libraries on the class path when building applications ("A" for Spring, "B" for Struts, etc). It is however possible to replace JCL by SLF4J if you want to (SFL4J provides bindings to logging frameworks but also a "JCL to SLF4J" bridge). See the mentioned post Logging Dependencies in Spring for all the details.
How to configure logging for Spring. What does in the web.xml file, do i need a log4j.properties file or a log4j.xml file? Where does it go, in WEB-INF? Does anything go in my applicationContext.xml file? (sorry but I need to start from zero here).
To log, you have 1. to decide which implementation you want to use (java.util.logging, log4j or logback), 2. to put the chosen one on the classpath if required (java.util.logging is in Java SE so it doesn't require extra libraries) and 3. to configure it (by putting a config file on the classpath). If you choose to use log4j, just add its jar and a log4j.properties or a more fancy (but more verbose) log4j.xml (this is just another format for the configuration) to the classpath.
I am using Hibernate in my project and including via Maven. It seems that Hibernate uses slf4j-simple. I have seen warnings saying that I can't have slf4j-simple and slf4j-log4j both on the classpath. I have not included slf4j-log4j as a dependency, but Hibernate must be including it. How do i solve this problem? Can I force Hibernate to use log4j instead?
Hibernate utilizes Simple Logging Facade for Java (SLF4J) and, indeed, you can't have several bindings (e.g. slf4j-simple.jar and slf4j-logj12.jar) on the classpath at the same time. Here, you are very likely getting slf4j-simple.jar transitively from another dependency. To solve this problem, run mvn dependency:tree to figure out from where it's coming from and exclude it if required.
And by the way, in your case, I would configure Spring to use SLF4J as Hibernate is using it. Follow the steps in the link mentioned in the first paragraph for that. And I would use logback as logging framework (which the successor of log4j), this is where things happen now.
You need a log4j.properties file in your classpath. Here is a minimal properties file I happened to have created yesterday:
log4j.logger.BillReview=INFO,BillReviewLog
log4j.appender.BillReviewLog=org.apache.log4j.RollingFileAppender
log4j.appender.BillReviewLog.File=BillReview.log
log4j.appender.BillReviewLog.Append=true
log4j.appender.BillReviewLog.MaxFileSize=5000KB
log4j.appender.BillReviewLog.MaxBackupIndex=5
log4j.appender.BillReviewLog.layout=org.apache.log4j.PatternLayout
log4j.appender.BillReviewLog.layout.ConversionPattern=%c %p %-10.10X{server} %-4.4X{user} %d{ISO8601} %m%n
Put that into a log4j.properties file, change all the references to 'BillReview' to something more like your project and that'll log to a file and stop those messages.
Your questions about which logging framework are largely personal choice. Log4j is the old standard and it works fine, Commons logging and slf4j are newer APIs and allow some more complicated use cases.
I'll let some more experienced Gurus than I answer the first bullet.
Answering your second bullet...
You can use either a log4j.properties or log4j.xml file (it doesn't matter which). Whatever you choose you should add it to your classpath (typically it should go in the same directory as your source code). If you are using Spring, a nice way to break your src directory up into logical portions is by using the following directory structure...
src/main/java -- put main source here
src/main/resources -- put resources used by you main source here
src/test/java -- put test source here (for tests)
src/test/resources -- put resources for tests here
You would therefore put your log4j.properties in the src/test/resources directory.
Answering your third bullet...
You can exclude a dependency within a dependency in you pom.xml file by doing the following...
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>${xbean.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
I had problems in the same area while running my tests. I eventually noticed that junit was bringing in slf4j-nop as a dependency, in addition to the slf4j-log4j12 that I wanted. Once I excluded slf4j-nop, it started working.

Difference in using java.util.logging and Log4j Loggers

I am developing a java application for which i have to use a logging mechanism. And now i am confused to choose either java libraries logger or to go for Log4j logger.
So i want to know when i can go for java logger
and when i can go for log4j logger.
I'd suggest you go with SLF4J instead to decouple your application from specific logging frameworks. It has adapters for various popular logging frameworks such as Jakarta Logging, JDK1.4 logging, log4j etc. making it a good abstraction for logging needs.
Logger class was not part of jdk earlier on, so several library implementations sprung up. The Log4j library has one of the most comprehensive set of logging utilities (Formatters, Appenders etc). However, for most developers this would be an overkill and the simple java.util.Logger would suffice.
I personally use a custom wrapper over my logger implementation. This enables me to define custom calls to carry out functional logging/auditing.
There are the Apache Commoms Logging project and SLF4J, either of which abstracts the underlying logging library.
In practice I tend to use Log4J over the built in logging classes. Mainly because Log4J can be configured per web-app in an application server, whereas JDK logging is configured per JVM.
The approach I would currently recommend is to use SLF4J as the logging API. You can then pick your logging framework depending on your needs as you discover them.
I did a writeup on what I consider to be best practice in getting started with SLF4J and a simple "log to System.out" which is currently placed at. http://runjva.appspot.com/logging101/index.html
Hopefully it is helpful.
I find Log4j more flexible when it comes to tweaking the logging cfg without re-compiling code in production environment.

Logging using SL4J, Jakarta Commons logging, log4j for third party libraries and my own code

I have some questions about logging, more specifically about setting it up and making sure it works.
The project I'm doing will use Wicket, Spring and Hibernate. I know that Wicket and Hibernate uses Simple Logging Facade for Java (SL4J) and that Spring is using the logging component from Apache Commons.
Will they co-exist happily?
I thought I would use log4j together with both SL4J and the logging component from Apache commons, do you think that's a good idea?
Can I set up them all to output logging data into a common file?
Or should I use separate files?
Or should I store the logging messages in the database? (I'd rather not, as I find grepping etc on text files quite convenient.)
For Spring I guess I need some kind of configuration file for the Apache Commons logging component as well where I direct it to use log4j?
When I've set these up I guess to see that everything works I set the logging level to INFO as it's fairly certain that all three of the frameworks output some information in that mode? Or is there an even better way to make sure?
And my last question. In the project I'm starting, do you recommend that I use SL4J for my own logging purposes? (I thought I would use log4j directly, but that was before I learned a little bit more about logging and a lot of respectable libraries seem to choose the path of a bridge/facade for their logging needs. And if it gets us flexibility without added cost there's no reason not to do it that way.)
I'm looking forward to hearing more from you about how you are doing your logging. It's a new area for me which I'm eager to improve myself in.
Well SLF4J is just a facade, like commons logging, which means they still need something else to work. They permit library authors to not force users into having multiple logging library and configuration. Log4j and logback are regular logging libs.
See here for more info.
SLF4J has a commons logging bridge that you can use to replace the commons logging library. I think the schema there explain the situation very well.
Now, you just need to use slf4j-logj12.jar to have commons logging and slf4j use log4j (or anything else you chose; btw, logback doesn't need an additional library to be used with slf4j) as a backing engine.
You application will thus have
jcl104-over-slf4j.jar (to bridge jakarta commons logging to slf4j)
slf4j.jar (for hibernate and others to use slf4j)
slf4j-logj12.jar (for slf4j to use log4j as a backend)
log4j.jar (for your application to use. all config will also be done here)
Here is how to redirect everything to SLF4J:
remove commons-logging.jar from your classpath. If you are using Maven and have trouble getting rid of commons-logging, see this.
put jcl-over-slf4j.jar in your classpath (it comes in the SLF4J distribution). This is a drop-in replacement that mimics JCL's classes, but calls SLF4J internally. This will take care of Spring, and any other framework that uses JCL.
Connect SLF4J to your favorite backend (Log4J, Logback...) by putting slf4j-xxx.jar in the classpath. Configure the backend to log all categories to one file, and you're done.
As for using SLF4J in your application, it is not strictly necessary. Libraries like JCL and SLF4J were originally designed for people who write libraries and do no want to lock their clients into a particular logging framework.
PS: by the way, JCL = Jakarta Commons Logging

Categories