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