I have a factory class
@ApplicationScoped /* 'ApplicationScoped' is not a must */
class MyFactory {
@Inject
private IService aService;
...
}
And an JAXB annotated class
@XmlRootElement(name = "item")
class AnItem {
@Inject
MyFactory myFactory;
...
}
AnItem
is instantiated by JAXB from an XML file.
The problem is that myFactory
is null
. If I replace this by
...
MyFactory myFactory = new MyFactory();
...
then myFactory.aService
is null.
How can I use dependency injection within classes created by JAXB?
The following solution is inspired by a Block of Adam Warski, see also BeanManager Javadoc
At first I'll need two utility methods:
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Utils {
public static BeanManager getBeanManager() {
try {
InitialContext initialContext = new InitialContext();
return (BeanManager) initialContext.lookup("java:comp/BeanManager");
} catch (NamingException e) {
throw new RuntimeException("Failed to retrieve BeanManager!", e);
}
}
public static <T> T getBean(Class<T> c) {
T result = null;
BeanManager bm = getBeanManager();
Set<Bean<?>> beans = bm.getBeans(c);
if (! beans.isEmpty()) {
Bean<?> bean = beans.iterator().next();
result = c.cast(bm.getReference(bean, c, bm.createCreationalContext(bean)));
}
return result;
}
}
Class AnItem
has then to be changed like this:
@XmlRootElement(name = "item")
class AnItem {
MyFactory myFactory = Utils.getBean(MyFactory.class);
...
}
I think you have some code in the wrong class, which is causing dependencies to be around the wrong way, which in turn makes the objects difficult to construct correctly.
Item
looks like a newable class (sometimes known as an entity). Newable classes are not created by your container, but are created by service classes. Jaxb is an example of a service. The service classes are created by your DI container.
I would re-evaluate your need to have Item
hold a reference to myFactory
. You have not shown this in your question, but there must be a method in Item
that makes a call to something in myFactory
.
This code should be moved out of Item
into a different class (perhaps a new service) that accepts an item
as a parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With