Monday, December 13, 2010

Correct SLF4J logger wrapping

The problem

As much as the idea pains me, I find it necessary to wrap the well-known logger wrapping framework SLF4J. Why?

The framework author goes to lengths to support JDK1.4 in the API, a reasonable goal for a broadly used API. The result is signatures such as this:

public interface Logger {
    /* ... */

    void info(String msg);

    void info(String format, Object arg);

    void info(String format, Object arg1, Object arg2);

    void info(String format, Object[] args);

    void info(String format, Throwable t);

    /* ... */
}

That's it. You get 0-2 parameters to put into your formatted mesage. If you have more than two parameters you are out of luck. An no mixing exceptions with formatted messages. However, were SLF4J coded against JDK5 the API might become:

public interface Logger {
    /* ... */

    void info(String msg, Object... args);

    /* NB - ellipsis parameter must be last. */
    void info(Throwable t, String msg, Object... args);

    /* ... */
}

Yes, both simpler and more functional. But not a an option without maintaining two versions of the code base or losing backwards compatibility.

A solution

In the past I worked around this with some pretty wild solutions, but today I ran across Wrapping the slf4j API, posted in August.

I can fix SLF4J for JDK5 myself:

public class LoggerBase {
    private static final String FQCN = LoggerBase.class.getName();

    private final Logger logger;

    public LoggerBase(Class thisClass) {
        this.logger = getLogger(thisClass);
    }

    public LoggerBase(String loggerName) {
        this.logger = getLogger(loggerName);
    }

    /* ... */

    public void info(String format, Object... args) {
        info(null, format, args);
    }

    public void info(Throwable thrown, String format, Object... args) {
        if (!logger.isInfoEnabled())
            return;

        if (logger instanceof LocationAwareLogger)
            ((LocationAwareLogger) logger)
                    .log(null, FQCN, INFO_INT, format, args, thrown);
        else
            logger.info(arrayFormat(format, args).getMessage(), thrown);
    }

    /* ... */
}

Hopefully SLF4J presents a solution for this (perhaps a separate JDK5 jar) so I can drop my warped logger wrapper wrapping class.

Scala for the Java programmer

Dave Copeland wrote a wonderful wiki, Another Tour of Scala, around the official A Tour of Scala. In Dave's version he presents Scala topics from the perspective of the Java programmer, explaining how Scala features looks coded in Java and commenting on usefulness and scrutability.

This is the best bootstrap into Scala resource for Java programmers (like me) I have seen. Thanks, Dave.

Tuesday, December 07, 2010

Wednesday, December 01, 2010

A new leaf

Today was my last day at JPMorgan Investment Bank where I worked with a great group of people in equities trading. I will miss them.

In a week or two I start my first day at Macquarie Group here in Houston at the energy/gas trading desks and turn over a new leaf. Leaf here means a page of a book. So I am beginning a new part in the diary of my life, a book I hope never closes.