Finally, logging that makes some sense…
In Groovy 1.8 they added a very nifty new way to do logging. But first, let’s revisit how we used to do logging.
<code>
private static final Logger log = Logger.getLogger(CrudService.class);
if(log.isDebugEnabled()) {
String debugMsg = “INCOMING:: Create: “ + resource.getClass() + “::” + resource.getId();
log.debug(debugMsg);
}
</code>The main problem with the above piece of code is the inane amount of verbosity used to do something that should be really really really simple. No wonder people resort to doing System.out.*
1. private static blah blah blah is way too long and cryptic for your newbe programmer.
2. checking if(log.isDebugEnabled()) should be handled by the log method more intelligently. Btw, this if statement is typically used for performance. String concats are expensive. Even this day in age, saving a few CPU cycles is nice.
A few months ago, I set out to tackle this problem in my apps using Spring. The solution I came up with was actually somewhat decent and resorted to using injection.
<code>
@Logger private Log log;
</code>
Using a bean initializer class, we can inject the proper logging mechanism into the class based on the class. The essential code from this class is below.
<code>
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
// make the field accessible if defined private
ReflectionUtils.makeAccessible(field);
if(field.getAnnotation(Logger.class) != null) {
Log log = LogFactory.getLog(bean.getClass());
field.set(bean, log);
}
}
});
return bean;
</code>
However, it still isn’t as nice as it should be… I mean, I was typing out @Logger, Log, log in every class. I should be able to type ‘Log’ and the class should know what to do. I don’t see the sense in repeating 3 pretty obvious keywords in each class to let it know what I want to do.
Groovy has finally made this better for all of us. At the top of your class simply add…
<code>
@Log
</code>
Just one annotation. Which is how it should be.
Above I said, ‘makes some sense.’ With an emphasis on ‘some’. I’m not quite sure why there are four separate annotions for different logging frameworks. Well, I do know why… Groovy eventually compiles into Java and the Java must know something about what it needs to do and we aren’t using Spring or any fancy AOP or AspectJ things, so… I guess for now it’s a small concession to make to have cleaner code.
References:
http://docs.codehaus.org/display/GROOVY/Groovy+1.8+release+notes#Groovy1.8releasenotes-@Log