Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use dependency injection in JAXB unmarshalled objects?

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?

like image 823
Udo Avatar asked Oct 19 '25 07:10

Udo


2 Answers

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);

  ...
}
like image 68
Udo Avatar answered Oct 21 '25 22:10

Udo


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.

like image 31
WW. Avatar answered Oct 21 '25 20:10

WW.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!