18

I must be stupid or something, but I seem not to be able to use the varargs-utilizing parameterized logging methods of SLF4J. An example:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingTest {

    @Test
    public void loggingTest() {
        Logger logger = LoggerFactory.getLogger(this.getClass());
        int x = 0xdeadbeef;
        long y = 0xdeadbeef;
    
        try {
            throw new Exception("This is a mighty exception!");
        } catch(Exception e) {
            logger.error("I wanna log {} and {} and {} with backtrace", x, y, 3, e);
        }
    }
}

On the logging method, eclipse produces such a warning:

The method error(String, Object, Object) in the type Logger is not applicable for the arguments (String, int, long, int, Exception)

and fails to compile.

However, if I change the logging call to:

logger.error("I wanna log {} and {} and {} with backtrace", new Object[]{x, y, 3, e});

It compiles and runs as expected (logging 3 "variables" and the exception stack trace).

The library versions are: slf4j-api-1.7.5.jar, slf4j-log4j12-1.7.5.jar and log4j-1.2.14.jar, if it makes any difference.

If anybody would point out the shortcomings of my thinking abilities, it'd be very much appreciated!

Community
  • 1
  • 1
Manjabes
  • 1,884
  • 3
  • 17
  • 34
  • You have 3 placeholders in your string but 4 arguments -- is this on purpose? – fge Jul 18 '13 at 06:48
  • 2
    Yes: http://slf4j.org/faq.html#paramException – Manjabes Jul 18 '13 at 06:49
  • I think [this answer](http://stackoverflow.com/a/7689819/1523342) explains it very nicely. – mthmulders Jul 18 '13 at 06:50
  • Well, according to the FAQ, that the first attempt fails to compile is expected; however, I don't see how the second can work... – fge Jul 18 '13 at 06:54
  • @mthmulders do I understand correctly that if I substitute my raw int's and long's with Integers and Longs then it should work? Because I tried, and it does not. – Manjabes Jul 18 '13 at 07:07
  • I've reproduced your setup (except running it as Java application instead of unit test) and your example runs just fine on an Oracle JDK 1.7.0_21. What version of Java and what JVM are you using? – mthmulders Jul 18 '13 at 07:23
  • @mthmulders, jdk1.7.0_05 – Manjabes Jul 18 '13 at 07:28
  • With 1.7.0_13 its working fine, too. Debugging I can see the primitive variables are boxed into their `Long` and `Integer` counterparts, just as one would expect. – mthmulders Jul 18 '13 at 07:31
  • Updated to 7u25, still the same – Manjabes Jul 18 '13 at 07:40
  • I was going to suggest checking the compiler preferences in your IDE with regard to "boxing and unboxing consversions" -- when I set the boxing preference from the default ('ignore') to 'error', but I continued to have the same compile failure even with the code that you said works by explicitly creates an Object array. I am tempted to think that you have one of the following: a) a much older version of the slf4j api somewhere on your classpath; b) compiler preferences set for JDK 1.5 or earlier; or c) multiple java versions installed and you're not really using the one you think you're using. – ZachOfAllTrades Sep 30 '13 at 15:38

1 Answers1

30

I did some additional investigation, and the only way to get a compile error for

logger.error("I wanna log {} and {} and {} with backtrace", x, y, 3, e);

and not for

logger.error("I wanna log {} and {} and {} with backtrace", new Object[]{x, y, 3, e});

is to use a version of the SLF4J API prior to 1.7 (in which support for varargs was introduced). You probably need to dig into your classpath (or server runtime?) to find where the following statement fails to be true:

The library versions are: slf4j-api-1.7.5.jar, slf4j-log4j12-1.7.5.jar and log4j-1.2.14.jar, if it makes any difference.

(because it certainly makes precisely the difference that you have observed)

ZachOfAllTrades
  • 1,083
  • 11
  • 15