amsalk
amsalk

Reputation: 599

cdi injected dependency resolved to null in a bean created by a producer method

I am trying to inject a dependency into a bean (Some/OtherImpl), annotated with @Named but the dependency (configurationService) always gets resolved to null (Resources#getConfiguratioService is not called) when a new instance of that bean is created in the controller (MyCtrl) by using its producer method.

However if I try to inject ConfigurationService directly into the controller, the method Resources#getConfiguratioService executes and creates new instance of the ConfigurationService which gets injected into the controller.

This is how it looks like

public class Resources() {
  @Produces
  public ConfigurationService getConfigurationService() {
      return new ConfigurationService(Constants.CONFIG);
  }
}

public abstract class MyAbstractClass {

  @Inject
  private transient ConfigurationService configurationService; // getter+setter

}

@Named
public class SomeImpl extends MyAbstractClass implements Serializable {
  // ...
}

@Named
public class OtherImpl extends MyAbstractClass implements Serializable {
  // ...
}

@Named
@ViewScoped
public class MyCtrl {

  @Inject
  private SomeImpl someImpl;

  @Produces
  public SomeImpl getSomeImpl() {
    return new SomeImpl(MyStringParam);
  }

}

Can you please tell me what am I doing wrong here? Is there a way how to fix it? Every hint will be appreciated. Thx in advance!

Upvotes: 2

Views: 1419

Answers (1)

Siliarus
Siliarus

Reputation: 6753

The problem here is that you are creating the instance of SomeImpl 'manually' using the new keyword. In that case, you create/provide the object, no injection takes place, and you hand over this object to CDI. From there on, any injection point of type SomeImpl and with default qualifiers will use your producer to create the bean. Producers are often a way to turn non-CDI objects into CDI bean but have the limitation that injection doesn't happen; note that this limitation is sometimes an actual advantage because some other framework might resolve injection or otherwise instantiate and change the instance and you just pass it over to CDI (example - integration with EJB).

As a solution, delete the producer and let CDI create the instance on its own. CDI will invoke a no-arg constructor (or a constructor with injectable params if present) to create the instance and then perform injection into this new object.

From there on, your code should work just as you expect it to.

In rare cases where you cannot let CDI managed the whole lifecycle and actually need to manually create instance and still inject into it, InjectionTargetFactory is what you are looking for.It requires a but BeanManager.getInjectionTargetFactory() is the starting point you need.

Upvotes: 3

Related Questions