Search code examples
javacdi

How to inject a Logger in an enum


When I try to inject my Logger producer in an enum, I get a NPE. How can I inject a Logger in an enum?

Example:

public enum MyEnum {

    HI("Hi there!"),
    HELLO("Hello mister!");

    @Inject
    private Logger log;

    private final String greeting;

    private MyEnum(String greeting) {
        this.greeting = greeting;
//        this.log = LoggerFactory.getLogger(this.getClass());
    }

    public String getGreeting() {
        log.debug("Method getGreeting called");
        return this.greeting;
    }

}

This class gives me a NPE on the log.debug() line. When I remove the @Inject and uncomment the this.log line it works.

Testcase looks like this:

@RunWith(Arquillian.class)
public class CoverKindTest {

    @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class, "test.war")
                .addClass(MyEnum.class)
                .addClass(LoggerProducer.class)
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }

    @Test
    public void testEnum() {
        MyEnum myEnum = MyEnum.HI;
        String greeting = myEnum.getGreeting();
        assertThat("Should give the greeting.", greeting, is("Hi there!"));
    }

}

Complete testable project for this question can be found here, MyEnum.class is the original question, MyEnum1.class is the solution without injection (working, but not what I am looking for) and MyEnum2.class is a suggested answer.

Edit: Updated the GitHub repo with a working solution. https://github.com/martijnburger/how-to-inject-a-logger-in-an-enum


Solution

  • Found a solution that works!

    I created a helper class as follows:

    public class LoggerHelper {
    
        private static Logger logger;
    
        private void injectLogger(@Observes @Initialized(ApplicationScoped.class) Object context, 
                Logger logger) {
            LoggerHelper.logger = logger;
        }
    
        public static Logger getLogger() {
            return logger;
        }
    
    }
    

    Now I can inject the logger in the Enum using:

    private final Logger log = LoggerHelper.getLogger();