Search code examples
javajakarta-eejava-ee-6cdi

@Inject only working for POJOs created by CDI container?


I just want to confirm that I fully understood the prerequisites for CDI to work. If I have a class A:

public class A {
    @Inject private B b;
}

Now when I instantiate this class using:

A a = new A();

In that case, A.b will be null.

But if I define in another class a member:

@Inject A a;

and later use a, a.b will be correctly populated?

Does CDI only work if the class requiring an injection was also created by CDI container? Or what am I missing if injections turn out to be null while creating a POJO using ordinary instantiation with new (yes, I got beans.xml in place)?


Solution

  • While others have stated correctly that for the most part DI containers will not inject dependencies into bean that they did not instantiate this is not entirely true.

    Spring has a wonderful feature that will autowire the bean when you create it using new A(). You just have to use AspectJ and mark your bean with the @Configurable annotation.

    @Configurable
    public class A {
        @Inject private B b;
    }
    

    Its actually kind of an awesome feature cause you can do Active Record style POJO's while still honoring your DI (its in fact how Spring Roo does it).

    You should also know that with Spring you can autowire a bean programmatically after its been instantiated with the AutowireCapableBeanFactory. This is how it typically autowires JUnit Test Case Classes because JUnit creates the test case classes.

    Yes Spring is not CDI but in theory you could write your own @Configurable for CDI or there is probably a CDI way of doing the above.

    That being said the above is sort of a sophisticated feature (and kind of a hack) and as @JanGroth mentioned understaning the lifecycle bean management of the container is critical whether its CDI, Spring, Guice etc.