Consider the following class definitions:
import com.codahale.logula.Logging
abstract class A extends Logging { log.info("from A") }
class C extends A { log.info("from C") }
They use Logula, a great logging library for Scala.
Creating an object of class C works great:
new C()
and produces the expected output:
INFO [2012-03-31 19:16:14,261] C: from A
INFO [2012-03-31 19:16:14,263] C: from C
But creating an instance of an anonymous sub-class of A
new A() {}
throws a NullPointerException:
Exception in thread "main" java.lang.NullPointerException
at com.codahale.logula.Log$.clean(Log.scala:25)
at com.codahale.logula.Log$.forName(Log.scala:23)
at com.codahale.logula.Log$.forClass(Log.scala:18)
at com.codahale.logula.Logging$class.log(Logging.scala:172)
at A.log(LoggingTraitTest.scala:3)
at A.<init>(LoggingTraitTest.scala:3)
at LoggingTraitTest$$anon$1.<init>(LoggingTraitTest.scala:8)
at LoggingTraitTest$delayedInit$body.apply(LoggingTraitTest.scala:8)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:60)
at scala.App$$anonfun$main$1.apply(App.scala:60)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:45)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:30)
at scala.App$class.main(App.scala:60)
at LoggingTraitTest$.main(LoggingTraitTest.scala:6)
at LoggingTraitTest.main(LoggingTraitTest.scala)
A similar exception is thrown if an anonymous sub-class of C is instantiated: new C() {}
Why is there any difference between an explicit and an anonymous class instantiation here?
Any hint about how I could find out what is happening would be welcome. Thanks in advance!
The problem is that Logula wants a canonical name for the class, which doesn’t exist for anonymous classes. See for example the documentation for
Class.getCanonicalName:So it looks like you’re out of luck on this one, but if you really, really needed to be able to use logging with anonymous classes, you could replace
getCanonicalNamewithgetSimpleNamein the following line (18) ofLog.scalain the Logula source:This gives me the following output:
Which is more or less what you want, probably. I’m not familiar enough with Logula to know whether this change would introduce headaches down the line, though.