CDI Injecting

Common Stupid Thing

Injection does not work?

DID YOU GET your instance from container????!!!!!

If you just "new SomeThing()", SomeThing is not injected with dependencies it requires. So SomeThing needs to be injected, too!

ARE YOU expecting injected bean in its construction method?

Bean is injected AFTER construction method, or AT construction when construction method with parameter is annotated @Inject

At instance creation time:

  • @Inject

    • without qualifier, then inject @Default implementation, or

    • with qualifier (example) @Inject @QualifierAnnotation BeanType bean;

  • for JSF, bean needs to be accessible through EL

  • Field DI - just inject

  • Constructor DI

    • without constructor DI, when initialize, container uses its default constructor, and at the time the bean is NOT injected with fields, etc.

    • if wish to get injected before constructor is called, use @Inject annotated constructor (can have only one)

      • @Inject public ExampleBean(CDIBean1 b1, EJBBean b2) {this.....}

    • otherwise, move initialization code to an initialization method and use @PostConstruction call back

  • Setter DI: @Inject public void setProcessor(final Processor processor)...

  • @Any

    • when multiple implementations of one interface exist

      • if try to inject without @Any, container will fail

    • want to inject them all

    • @Inject public void getAllExampleBeanImplementations(@Any Instance<ExampleBean> beans) {...}

  • Dynamically inject with javax.enterprise.inject.Instance

    • allows to dynamically obtain instances with combination of

      • required type

      • qualifiers

    • use when

      • bean type / qualifiers vary dynamically at runtime

      • depend on deployment, there may be no bean which satisfies

      • want to iterate all beans (@Any)

    • @Inject @PayBy(CHEQUE) Instance<PaymentProcessor> chequePaymentProcessor;

    • @Any : see above

    • use get() to obtain single instance

    • use iterator() to get instances

  • @New (deprecated) (use @Dependent is recommended)

    • @New is a built-in qualifier type

    • to obtain a new instance not bound to the declared scope

    • @New(Class<?>) - specifies the bean class of the new instance

    • use with @Produces

  • Event observer (see CDI Events)

  • Producer methods: @Produces public Processor getProcessor(@Inject final Gateway gateway) {...

Note: all above are still performed at bean instance-creating time

Programmatic Injection:

With javax.inject.Provider<T>

which enables

  • retrieving multiple instances (fully-constructed and injected)

  • lazy / optional retrieval of instance

  • breaking circular dependencies

  • abstracting scope

  • to apply qualifier at run time: get().select(new AnnotationLiteral<Fancy>(){}).get();

also see Instance javadoc

@Inject Provider<BeanType> beanProvider;

.....

Bean oneBean = beanProvider.get();

Bean secondBean = beanProvider.get();.....

With javax.enterprise.inject.Instance<T>

@Inject

private Instance<?> lazyProvider;

With CDI utility

javax.enterprise.inject.spi.CDI.current().select(C.class).get()

NOTE: It's slow and can leak, check here

https://rmannibucau.wordpress.com/2015/03/02/cdi-and-instance-3-pitfalls-you-need-to-know/

Instance interface and Provider interface

http://docs.oracle.com/javaee/7/api/javax/inject/Provider.html

http://docs.oracle.com/javaee/6/api/javax/enterprise/inject/Instance.html

Provider:

  • for any type T can be injected, can also inject Provider<T>

  • compare with injecting T directly, provider enables

    • retrieve multiple instances (direct injecting only do once at initialization stage)

    • lazy or optional retrieval

    • breaking circular dependencies

    • abstracting scope - look up an instance in a smaller scope from an instance in a containing scope (do not understand, just copy here)

Instance:

  • allows dynamically obtain instances of beans with a specified combination of required type and qualifiers

  • in certain situations, injection is not most convenient, for example, may not when

    • bean type / qualifiers vary dynamically at run time

    • depending upon deployment there may be no bean which satisfies the type and qualifiers

    • would like to iterate over all beans of certain type

Provider is sub interface of Instance, Provider.get inherit Instance.get; Provider.get()

  • returns a contextual reference for the unique bean that matches

    • the required type, and

    • the required qualifiers, and

    • is eligible for inject into the class into which the parent Instance was injected