1

Suppose I have some class with injections:

class MyBean {

    @Inject
    Helper helper;

    // all sorts of data
}

and this class was created in a way the CDI container is not aware of it like reflection, serialization or new. In this case the helper is null because the CDI did not initialize it for us.

Is there a way to tell CDI to "activate" the bean or at least its injection? e.g., as if it was created with Instance<MyBean>#get?

Right now I have a hack where I do the following:

class SomeClass {

    @Inject
    Instance<MyBean> beanCreator;

    void activateBean() {
        MyBean mybean = ... // reflection/serialization/new
        MyBean realBean = beanCreator.get();
        Helper proxy = realBean.getHelper();
        mybean.setHelper(proxy);
        beanCreator.destroy(realBean);
    }
}

This looks pretty bad but it works for everything I tested. It just shows what the end result is that I want.

Using Wildfly 10.1 if it matters.

Mark
  • 2,167
  • 4
  • 32
  • 64

1 Answers1

2

First of all, the way you use MyBean is not a CDI way; in fact you operate on so called non-contextual object. What you are doing is taking a non-CDI managed object and asking CDI to resolve injection points. This is quite unusual, as you handle part of the lifecycle (creation/destruction), while asking CDI to do the rest.

In your case, the MyBean class needs to become InjectionTarget, and that is the way you should start looking. In order to trigger injection you will want to do something like this (during creation of MyBean):

// Create an injection target from your given class
InjectionTarget<MyBean> it = beanManager.getInjectionTargetFactory(beanManager.createAnnotatedType(MyBean.class))
                .createInjectionTarget(null);
CreationalContext<MyBean> ctx = beanManager.createCreationalContext(null);
MyBean instance = new MyBean();
it.postConstruct(instance); // invoke @PostContruct
it.inject(instance, ctx); // trigger actual injection on the instance

Please note that this approach is usually clumsy (as in hard to make it work and maintain) and it might be better to instead turn your MyBean into a true CDI bean and leaving whole lifecycle management to CDI. For that, however, your question doesn't provide enough information.

Siliarus
  • 6,393
  • 1
  • 14
  • 30
  • Thanks. The context: `MyBean` is part of a state object i need to save and load, currently with serialization (see my previous [question](https://stackoverflow.com/questions/45828159/how-to-serialize-an-injected-bean)). I read that using injection in entities is not a good idea but this entity needs it. Also, where you write `new MyBean()` it can be replaced with deserialization or reflection, right? – Mark Sep 04 '17 at 15:23
  • Perhaps you should think about, if it is reasonable and necessary to give MyBean the responsibility it fulfills using Helper. Sometimes the structure is better, if you let some `Decorator`, `Adaptor` or even an `Iterator` handle that. These normally are beans which can be normal scoped created by the container and made able to work with your data-objects. – aschoerk Sep 04 '17 at 17:02
  • If you provide use case, of how the entity actually depend on such beans, then we can help refactor it to a much better design which will not require an injection into the entity. Ideally you should treat the entity as data, and have a separate bean to process that data – maress Sep 04 '17 at 21:17
  • @Mark Yes, I think you can use deserialization. The point of that line in my sample is to obtain a reference to actual instance. So it should work. – Siliarus Sep 05 '17 at 05:05
  • Iv'e tested this and the bean's injection is `null` so it doesn't work as it is :( – Mark Sep 06 '17 at 01:46
  • @maress OK, I asked the design question here: https://stackoverflow.com/questions/46066680/how-to-alter-the-design-so-that-entities-dont-use-injections – Mark Sep 06 '17 at 04:14
  • @aschoerk See comment to maress above. Siliarus perhaps you can look there too please. – Mark Sep 06 '17 at 04:15