@Slf4j fails with static initializer #368

Closed
lombokissues opened this Issue Jul 14, 2015 · 10 comments

Projects

None yet

4 participants

@lombokissues
Collaborator

Migrated from Google Code (issue 295)

@lombokissues
Collaborator

๐Ÿ‘ค hartmut.benz ย  ๐Ÿ•— Oct 28, 2011 at 14:13 UTC

The code below produces the compile error
Cannot reference a field before it is defined
(lombok 0.10.1, eclipse 3.7.1, maven-lombok-plugin 0.10.1, Ubuntu 10.4)

Here is the code:

@ lombok.extern.slf4j.Slf4j
public class LombokTest {
static {
log.error( "Cannot reference a field before it is defined" );
}
}

@lombokissues
Collaborator

๐Ÿ‘ค hartmut.benz ย  ๐Ÿ•— Oct 28, 2011 at 14:15 UTC

Oh...and java 1.6.0_26-b03

@lombokissues
Collaborator

๐Ÿ‘ค grootjans ย  ๐Ÿ•— Nov 07, 2011 at 19:49 UTC

Fixed in 99e36bf. Will be in next version after 0.10.2

@lombokissues lombokissues added this to the 0.10.3 milestone Jul 14, 2015
@lombokissues
Collaborator

๐Ÿ‘ค pe.fips ย  ๐Ÿ•— Nov 10, 2011 at 12:57 UTC

Sorry, but I have to reopen this issue, since your fix broke injecting of static fields in enums. See the example:

public class Issue295 {
@ lombok.Log
public enum AnEnum {
A,
B;
}

public static void main(String[] args) {
AnEnum keks = AnEnum.A;
}
}

The simple solution would be to insert the static fields after the enum constants.
We should also treat static fields in javac in the same way, so this should be done there as well.

If nobody picks this up earlier, I will provide a fix for this tomorrow.

@lombokissues lombokissues reopened this Jul 14, 2015
@lombokissues
Collaborator

๐Ÿ‘ค pe.fips ย  ๐Ÿ•— Nov 10, 2011 at 13:05 UTC

Please note that the example above compiles, but you should get an java.lang.ExceptionInInitializerError when you run it.

@lombokissues
Collaborator

๐Ÿ‘ค pe.fips ย  ๐Ÿ•— Nov 13, 2011 at 08:12 UTC

Fixed in 0d75d56.

@lombokissues lombokissues removed the accepted label Jul 14, 2015
@lombokissues
Collaborator

๐Ÿ‘ค reinierz ย  ๐Ÿ•— Nov 21, 2011 at 23:02 UTC

Now in release 0.10.4

@lombokissues lombokissues modified the milestone: 0.10.3, 0.10.4 Jul 14, 2015
@lombokissues
Collaborator

End of migration

@muued
muued commented Mar 11, 2016

Today I tried to log something in an enum constructor which lead to a NullPointerException, because the log field was not yet initialized.
After reading this thread, it seems like trying to initialize the log field before the enum constants to be able to use it in their initialization process is not viable either.
If this is correct, it may be helpful to mention this circumstance on the feature page of the log annotation!

@tafit3
tafit3 commented Mar 11, 2016

Static field initializers in enums execute after the initializers of enum constants. This is a java language feature, so the hint on the feature page may be useful, but your problem is out of scope of lombok.

"It is a compile-time error to reference a static field of an enum type from constructors, instance initializers, or instance variable initializer expressions of the enum type, unless the field is a constant variable (ยง4.12.4)."
https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.9.3

However, if there is a static nested class, it will be initialized before the enum constants, so the following would work:

enum Example {
    A, B;

    private static class $LogContainer {
        static Logger log = Logger.getLogger(Example.class.getCanonicalName());
    }

    Example() {
        $LogContainer.log.info("Initializing: " + name());
    }
}

Could lombok somehow replace the "log" with "$LogContainer.log"? Another (pretty ugly) solution is to name the nested class "log" and delegate all the calls:

enum Example {
    A, B;

    private static class log {
        static Logger log = Logger.getLogger(Example.class.getCanonicalName());

        static void info(String message) {
            log.info(message);
        }
    }

    Example() {
        log.info("Initializing: " + name());
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment