Search code examples
singletonquarkuscdiinject

Quarkus: Inject/Use CDI bean inside a non-CDI bean


I'm trying to inject my singleton bean into a non-bean class, but for now, I always get that my injected dependency is null.

Quarkus: 3.2.2

@Named("singletonConfiguration")
@Singleton
public class Configuration {

    private static Configuration INSTANCE = null;

        private Configuration() {
    }

    public static synchronized Configuration getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Configuration();
                }

        return INSTANCE;
    }
@Named("producerConfiguration")
@Singleton
public class ConfigurationProducer {

    @Produces
    @ApplicationScoped
    public Configuration produceConfiguration() {
        return Configuration.getInstance();
    }
}

I tried 2 different implementation, both of them dont work

public class Test {

        @Inject
    @Named("producerConfiguration")
    private ConfigurationProducer configurationProducer;

    public Test() {
    }

    public void doIt() {
        Configuration configuration = configurationProducer.produceConfiguration();
        System.out.println("TEST");
                // throw err *... because "this.configurationProducer" is null*
        System.out.println(configuration); 

    }

}

or

public class Test {

    @Inject
    @Named("producerConfiguration")
    Configuration configuration;

    public Test() {
    }

    public void doIt() {
        System.out.println("TEST");
        System.out.println(configuration); // -> print 'null'
    }
}

But if I use Configuration Singleton bean inside another bean, everything works

@ApplicationScoped
public class ConfigurationService {

    @Inject
    @Named("singletonConfiguration")
    Configuration config;


        .... (config is NOT null here)

}

PS if it will help, I can make Configuration class @ApplicationScoped insted of @Singleton


Solution

  • This is expected; CDI will only inject into instances of beans it manages - non-CDI classes won't work. If you want to fully leverage CDI, you should mostly stick to that and avoid injecting into non-CDI classes. However, that's not always possible and you can use programmatic lookup to do just that - the CDI way is via CDI.current.select(...).get() but in Quarkus I'd recommend Arc.container() to achieve the same.

    The main point is to be able to create a new instance of the Test class using the 'new' keyword. If there is a way to achieve this and have Test as part of CDI, that's fine. I just haven't found how to do it

    That depends on how is the test class created (is the no-args constructor or one that has only injectable dependencies?) and if you need to create the class instance before or after CDI container already runs. If you could turn the Test class into a CDI bean, you could then just ask the container for an instance of that bean via programmatic lookup.