Fabrizio Giudici is a Senior Java Architect with a long Java experience in the industrial field. He runs Tidalwave, his own consultancy company, and has contributed to Java success stories in a number of fields, including Formula One. Fabrizio often appears as a speaker at international Java conferences such as JavaOne and Devoxx and is member of JUG Milano and the NetBeans Dream Team. Fabrizio is a DZone MVB and is not an employee of DZone and has posted 67 posts at DZone. You can read more from them at their website. View Full User Profile

Which Logging Facility for Swing Applications?

04.27.2009
| 11521 views |
  • submit to reddit
Crossing fingers, after a long peak of other things to do, I should be able to resume writing articles with technical content. In the meantime, I'd like to discuss one of the first issues that people started filing against BetterBeansBinding: to use a logging facility for the library, that so far doesn't have any logging, with the exception of a handful of System.err.println() statements. One commenter suggested the use of SLF4J instead of java.util.logging and I can't say at the moment which solution is best.

Just to give some context, I'm recapping how I've used logging frameworks in my projects so far:

  • In the beginning, I used log4j.
  • Circa 2001, if I remember well, I started using commons-logging, still configured with log4j. At the time I was mostly doing server-side applications; the limited amount of projects I was doing in Swing probably didn't have logging at all.
  • In 2004, I was still using commons-logging, but being more involved in Jini made me more comfortable with java.util.logging.
  • Since 2005/2006, I've only been using java.util.logging, partly because I dramatically increased the percentage of my Swing projects, partly because most of the server-side stuff I've been doing recently shares lots of components with my desktop projects.

Since a few months, blueMarine has been using a very simple customized version of java.util.logging: the only new feature is that every method accepts a varargs-style such as in PrintWriter.printf():

import it.tidalwave.logger.Logger;

...

Logger logger = Logger.getLogger("name");
int x = ...;
String s = ...;
logger.fine(">>>> x=%d, s=%s", x, s);

Not only this is much more readable than concatenating string literals and variables with the + operator, but it's also faster when the log is disabled. In fact the implementation of the logging methods is encapsulated in a if (...) that tests for the current logging level; this means that string concatenations are only executed when the logging is needed:

package it.tidalwave.logger;

public class Logger
{
private java.util.logging.Logger delegate = ...;

public void fine (String pattern, Object ... args)
{
if (delegate.isLoggable(Level.FINE))
{
delegate.fine(String.format(pattern, args));
}
}
}

In contrast, the direct use of java.util.logging forces passing a single message concatenated with +, which always makes use of string concatenation, even though the result will be thrown away because the related logging level is disabled. That's why, in performance critical sections, people uses to encapsulate java.util.logging in application code including the test for the level as in:

if (logger.isLoggable(Level.FINE))
{
logger.fine(...);
}

But this style introduces a lot of extra verbosity in code, making it less readable.

I don't like re-inventing the wheel, so my custom logger will be eventually replaced by SLF4J, which - among other things - offers a similar pattern-oriented logging style; furthermore, its pluggable design makes it possible to send the log data to a number of different targets. I'm not doing this immediately only because I have other priorities in blueMarine.

So, from a point of view, I would not be against the use of SLF4J in BetterBeansBinding. The only thing that worries me is that this solution introduces a dependency, while BeansBinding at the moment has got *no* dependencies. Consider that one of the constraints of BBB is to be able to work as a "drop in" replacement for BeansBinding, and with SLF4J you'd need to replace an existing jar file with TWO jar files.

So, I see the following options:

  1. Use java.util.logging (single jar, but verbose code)
  2. Copy a customized logger, similar to the one in blueMarine, to BBB (single jar, readable code, but a few classes to cut and paste, and a sensation of NIH).
  3. Use SLF4J and live with the dependency (multiple jars, readable code, no cut and paste).
  4. Use SLF4J and deliver a "OneJAR" version of BBB embedding SLF4J classes (sounds as "all pros and no cons").

Solution #4 should be compliant with the BBB and SLF4J licenses (LGPL 2.1 and MIT-like) and it's the one that I like more at the moment, but I have to check. At the moment (1.2.3-SNAPSHOT) BBB has been split in three subcomponents, so the idea of producing a "OneJAR" is already present in BBB - in addition to the capability of releasing a jar for each module, a configuration that could be used e.g. with OSGi, NetBeans Platform and in all cases when strictly replacing the original BeansBinding is not required.

Thoughts?

 

Published at DZone with permission of Fabrizio Giudici, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mark Thornton replied on Mon, 2009/04/27 - 3:01am

the direct use of java.util.logging forces passing a single message concatenated with +

Surely not. I've never used jul like that. It is a little irritating packaging the arguments in an Object array, fortunately this is quite a cheap operation.

 

Valentin Buergel replied on Mon, 2009/04/27 - 3:13am

I used more or less the same libraries in the past (including SLF4J) before I switched to a customized logger with varargs as you did. Based on my experience I very much prefer solution 2). As the internal of the customized logger can be changed in the future, you will be able to connect the internals of that logger to a logging framework like SLF4J if this will be necessary.

Regards, Valle

Mladen Girazovski replied on Mon, 2009/04/27 - 3:50am

Thoughts? 

 No offense intended, but i think that the whole "logging scene" is ridiculous.

  •  log4j
  • commons.logging (with all it's "funny" classloading issues)
  • java.util.logging
  • sl4j
  • ....

After all, how many logging frameworks do we need?

How many times did you changethe logging implementation of an application without being forced by some bugs etc?

 I have not come accross any reason not to use log4j, the oldest logging framework with the most features.But to each his own.

 

Fabrizio Giudici replied on Mon, 2009/04/27 - 4:16am in response to: Mark Thornton

You're referring to the logp() method, I believe: yes, the problem is that Object array, since it doesn't accept varargs. So I meant "... forces passing..." unless, again, you have a bloated caller code.

Brant Boehmann replied on Mon, 2009/04/27 - 7:16am

I realize that it won't help you in the immediate term, but perhaps you should vote for the RFE that I submitted a couple years back to add varargs method to the java.util.Logger class. If this were already there, then your problem would be solved.

Fabrizio Giudici replied on Mon, 2009/04/27 - 8:27am in response to: Brant Boehmann

Definitely. varargs is such a simple change for jul, but it would be useful, so it's a shame it isn't there yet.

John J. Franey replied on Mon, 2009/04/27 - 9:25am

 

I'm not sure if your primary issue is with the framework or the programming api.

If you are speaking about the api: slf4j is my choice.  I find it to be suited for all log messages. There is no need for the log level test before calling the slf4j log method.  In aspects important to me, slf4j api offers the same features as log4j's api or jul's api.

 

if you are speaking about the framewwork: slf4j is my choice, even though it is not a framework.

slf4j defers the decision of which framework to runtime.  This is to the developer's benefit, not the gui user's.  Your users of your gui won't care, so maybe in distribution, a small, lowcost logging framework is adequate.  However, during development,  more full featured framework would be prefered like the revered log4j or your fav jul.  commons-logging api supports this, too, but commons-logging's dynamic discovery is not as solid as slf4j's static binding.

sfl4j api can be bound to a variety of frameworks: log4j, jul, logback, simplelog.  Your runtime requirements is the primary factor in the decision, not the programming api.

 

 

slf4j also has a clean answer to the problem of third-party libraries using a framework specific api that is not the framework your application uses.  For example, log4j api is used in the third-party library.  What are your options there?  1) Choose the log4j framework for your own application.  How tyrannic.  2) Write a log4j adapter that converts log4j requests to your framework's requests.  3) commons-logging, if it supports the framework you want.  4) implement the log4j api in terms of your preferred framework, lots of work (and this is what slf4j provides).

 

I am not sure whether I like logback or log4j better.  But I don't think that responds to your question.

 

 

Regards,

John

 

Mike P(Okidoky) replied on Mon, 2009/04/27 - 11:38am

What I'm missing is log entries for anything that an application accidentally does outside of the AWT event thread. You're not allowed to interact with Swing outside the AWT thread, yet this is one of the most common cause of bugs and instabilities in the more complicated Swing applications.

Also, how about using the assert mechanism to let you bypass some of the log statements.

assert log("you did something you shouldn't");

log always return true. Only logged when running the JVM with the -ea option.

 

Witold Szczerba replied on Mon, 2009/04/27 - 4:03pm

I would suggest to use option #1. Simple solution, no external libraries required. This is not supposed to be rocket science, just simple logging to replace things like:
if(LOG) {
System.err.println(.....)
}
which one has to recompile in order to actually see the message. I am not sure if adding extra dependency for 3rd party libraries would be justifiable in this case. Keep it simple.

Regards,
Witold Szczerba

Jeanette Winzenburg replied on Tue, 2009/04/28 - 9:49am

 

Murmeltiertag :-)

 In other words: we have had the exact same debate over at Swnglabs some years ago and the ,winner waaas ... stick with built-in logging, option #1, for the reasons outlined by Witold. Obviously, my preference as well.

Cheers

Jeanette

 

 

Mark Thornton replied on Tue, 2009/04/28 - 2:28pm in response to: Fabrizio Giudici

For both log and logp methods it comes down to a small amount of noise that would be unnecessary if varargs had been used: new Object[] {...}. About 15 characters and I could probably configure my IDE to generate it for me, but haven't been sufficiently irked to try that route.

 

Evan Summers replied on Wed, 2009/04/29 - 7:08am

i too use custom logger modelled after utilLogging - with varargs support - primarily for that very reason - but also to get stacktrace to deduce class name, method name and line number in the code altho "very expensive" but doesn't matter for interactive Swing app testing

Jean-Francois P... replied on Wed, 2009/04/29 - 9:27am

I think the first main decision (about BBB logging) to take would rather be:

"Should there be logging or not in a library that is implementing a JSR?"

I would probably say NO, because no JSR implementation should -to my viewpoint- impose any external dependency and it should not even impose jul (which is not external) because I don't think jul is logging library of choice of all Java developers.

Now if BBB is disconnected from JSR-295, then the choice is yours (ours?)!

My selection would probably go towards SLF4J which has a good API and can statically bind to any common logging library (log4j, jul...)

I would probably avoid commons-logging at all costs (even if classloader problems are less likely in GUIs than in JEE containers; but this shall change quickly with the rise of OSGi in GUI applications).

Just my 2 cents.

Tom Eugelink replied on Mon, 2009/05/04 - 2:35am

What I'm reading here is "I would like to use SLF4J but I can't because of the limited library management in Java". If Java would per default resolve, say, Ivy dependency information stored in the META-INF folder of a jar using a trusted repository at java.com, then this would not be a problem. Naturally this still may result in JAR hell, so a better component / plugin support would also be a good idea (JDK7?). But given that this is one step too far, I'd go for option 1.

Martin Wildam replied on Mon, 2009/05/04 - 3:38am

I did not really try any of those - I only looked at documentation and code samples for some logging frameworks - and finally decided to make my own logging module as none of the existing fit my needs.

I found it strange: So many existing things and nothing is satisfying. - Strange, but applies for many other realms also for me...

Carla Brian replied on Sun, 2012/04/15 - 2:22am

Thanks for this information. This has been useful in my coding. Keep posting. - Instant Tax Solutions Reviews

Mateo Gomez replied on Thu, 2012/07/26 - 2:59am

these information are very useful and i have learned so much here 

 
chicken burrito recipe

 

Matt Coleman replied on Fri, 2012/07/27 - 4:40am

logging facility swing is indeed a good thing to have

 graphic design buffalo

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.