[groovy-user] @Slf4j(value = "LOG") does not work if the "LOG" is invoked in default constructor

10 views
Skip to first unread message

ngandriau

unread,
Jul 6, 2013, 6:31:27 PM7/6/13
to us...@groovy.codehaus.org
It works perfectly in other usages, but when I use it in this situation,
illustrated with this gist <https://gist.github.com/ngandriau/5941469>
I get the following excepion:

<code>
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:113)
Caused by: java.lang.NullPointerException: Cannot invoke method info() on
null object
at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
at
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at
org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at TestLogASTAnnotation.<init>(TestLogASTAnnotation.groovy:14)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at
org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
at
org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:186)
at TestLogASTAnnotation.<clinit>(TestLogASTAnnotation.groovy:9)
... 3 more
</code>

I use groovy 2.1.5 with JDK 1.7.021 64bits on kubuntu 13.04 64bits

Any idea?

Thanks



--
View this message in context: http://groovy.329449.n5.nabble.com/Slf4j-value-LOG-does-not-work-if-the-LOG-is-invoked-in-default-constructor-tp5716061.html
Sent from the groovy - user mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Jim White

unread,
Jul 7, 2013, 1:26:48 AM7/7/13
to us...@groovy.codehaus.org
The problem has to do with the order of operations when a class is initialized.  It seems as though the static variable and it's initializer injected by the @Slj4j annotation is being appended to the static members for the class and therefore it is *last* of the static members to be initialized.  Therefore the initializer for staticInstanceOfMyClass is being called before LOG is initialized.

There is a simple fix though.  The static initializer block for a class is called *very last* (after all the static member initializers).  Therefore if you put your static initializer in a static initializer block instead of on the static member, it will work.  

Just break the single initialized static declaration into two like this:

// This must not have an initializer because LOG gets added as the last static member of the class.
static TestLogASTAnnotation staticInstanceOfMyClass

// This can go anywhere (and refer to any static member, regardless of where it is placed)
// even before the member declaration above and it will still get executed after all the
// static member initializers.
static {
     staticInstanceOfMyClass = new TestLogASTAnnotation()
}

Jim

Jim White

unread,
Jul 7, 2013, 1:29:54 AM7/7/13
to us...@groovy.codehaus.org
Note that this is not some Groovy weirdness.  It is fundamental Java arcana.

I do wonder though whether there is some way for the the annotation processing to inject its initialized static member as the first thing in the class so then it would behave as you would like without having to know about this fussy business.

Jim

Jochen Theodorou

unread,
Jul 8, 2013, 3:05:09 AM7/8/13
to us...@groovy.codehaus.org
Am 07.07.2013 07:29, schrieb Jim White:
> Note that this is not some Groovy weirdness. It is fundamental Java arcana.
>
> I do wonder though whether there is some way for the the annotation
> processing to inject its initialized static member as the first thing in
> the class so then it would behave as you would like without having to
> know about this fussy business.

I did not double check, but afaik we have something for that

bye blackdrag

--
Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
blog: http://blackdragsview.blogspot.com/
german groovy discussion newsgroup: de.comp.lang.misc
For Groovy programming sources visit http://groovy-lang.org
Reply all
Reply to author
Forward
0 new messages