How can I programmatically inject a Java CDI 1.1+ managed bean into a local variable in a static method?
To inject an instance of class C
:
javax.enterprise.inject.spi.CDI.current().select(C.class).get()
This is available in CDI 1.1+
null
-ing it? Mostly you want to keep an instance of your backing bean (get()
returned it) in your converter/validator for performance reasons (please look at the source code of CDI
's methods). I usually do this with a static field in the converter/validator: private static MyFooBackingBean FOO_CONTROLLER;
and later: if (null == FOO_CONTROLLER) { FOO_CONTROLLER = CDI.current().select(MyFooBackingBean.class).get(); }
Maybe annotations are missing here. –
Plourde Use for instance this utility class. You basically have to obtain instance of BeanManager
and than grab the bean you want from it (imagine something like JNDI lookup).
Update
You could also use CDI utility class offered in CDI 1.1
SomeBean bean = CDI.current().select(SomeBean.class).get();
Update 2
In CDI 2.0 you have to use BeanManager class for obtaining bean instances programatically.
@BRS
import javax.enterprise.inject.spi.CDI;
...
IObject iObject = CDI.current().select(IObject.class, new NamedAnnotation("iObject")).get();
With:
import javax.enterprise.util.AnnotationLiteral;
public class NamedAnnotation extends AnnotationLiteral<Named> implements Named {
private final String value;
public NamedAnnotation(final String value) {
this.value = value;
}
public String value() {
return value;
}
}
NamedAnnotation
can be used for any @Named
bean, not just IObject
s. ProgrammaticBeanLookup
takes more code than NamedAnnotation
, but can only be used for Class
or @Named String
, whereas the CDI
route can take in other annotations and/or a TypeLiteral
. ProgrammaticBeanLookup
also requires JNDI classes to be in the classpath, and manual population of a non-final static variable if it isn't. Moreover, BeanManager
isn't guaranteed to be threadsafe, so ProgrammaticBeanLookup
might have threading issues. –
Partly CDI
usage in a helper method, such as <T> T getNamedBean(Class<T> clazz, String name)
–
Partly The link suggested by @Petr Mensik is very useful. I am using the same code in my example.
Here is a way to get an instance of the class in instance methods/static methods. It is always better to code for interfaces instead of using the class name hard coded in the methods.
@Named(value = "iObject ")
@RequestScoped
class IObjectImpl implements IObject {.....}
//And in your method
IObject iObject = (IObject) ProgrammaticBeanLookup.lookup("iObject");
.........
//Invoke methods defined in the interface
This programmatic look up of beans can be quite useful when you have an application scoped object with method that requires an instance of a class that may change over time. So, it is always better to extract the interface and use programmatic bean look up for the sake of loose coupling.
CDI
methodology, which provides more versatile and typesafe lookups than ProgrammaticBeanLookup
–
Partly You should include qualifiers:
List<Annotation> qualifierList = new ArrayList();
for (Annotation annotation: C.class.getAnnotations()) {
if (annotation.annotationType().isAnnotationPresent(Qualifier.class)) {
qualifierList.add(annotation);
}
}
javax.enterprise.inject.spi.CDI.current()
.select(C.class, qualifierList.toArray(new Annotation[qualifierList.size()])
.get()
- You could define a parameter with the type of the bean interface in your static method, and pass an appropriate implementation reference. That would make it more unit-testing friendly.
- If you're using Apache Deltaspike, you can use BeanProvider#getContextualReference. It's easier than getting a javax.enterprise.inject.Instance, but, beware of dependent beans (see javadoc)!
© 2022 - 2024 — McMap. All rights reserved.