Add a stateful bean using a producer and polymorphism with CDI in JEE

人走茶凉 提交于 2019-12-24 09:05:44

问题


I'm really new to JEE CDI but tried half of last night to find a solution to a problem.

I have a Controller Class that, when startup is called, should inject a stateful bean using a Producer depending on a parameter. This mentioned stateful bean itself contains an injected bean itself.

To be honest, not sure if this works at all, any feedback is highly appreciated=)

Here is some dummy code that should help understand what I want to do (based oin https://docs.jboss.org/weld/reference/1.0.0/en-US/html/producermethods.html). Probably I totally messed up a lot of stuff now... but I was not able to find an example how this kind of problem can be solved or I was not able to understand it=/

Controller (main service)

@Singleton
@Startup
public class Controller
{

    private IEngine engine;

    @PostConstruct
    private void startup(int typeID) 
    {
        Factory f = new Factory();
        engine = f.getEngine(typeID)
    }

 }

Factory

public class Factory
{
    @Produces
    public IEngine getEngine(int typeID) 
    {
        if(typeID==1)
        {
          return new EngineA();
        }    
        else
        {
          return new EngineB();
        }

    }

IEngine interface for polymorphism

public interface IEngine 
{
    void startUp();
}

Here is an Example of EngineA, EngineB is simuliar

@Stateful
public class EngineA implements IEngine
{

    @Inject
    private CoinManager cm;

    //@Override
    public void startUp() 
    {
      cm.doSomeThing();
    }
}

Unfortunately this, even if working, is not allowing me to use @injection in EngineA. In fact, cm in EngineA is null. How can I bring this to work?

BR and THX! Stefan


回答1:


Alright, let's take a step back and look at it. Firstly, do not invoke producers yourself. Let CDI do the job and just go ahead and tell it where to inject it. Your Controller could look like this (but it probably won't, there are multiple misunderstanding in your post).

@Singleton
@Startup
public class Controller
{
    @Inject // just tell CDI to give you this
    // it won't be this easy here, but it is just to give you an idea
    private IEngine engine;

}

With CDI, you want to avoid creating instances via new when possible. The reason is, once you yourself create an instance, CDI does not have control over creation and hence cannot inject anything into it! This is where your null comes from.

Now, if you have a producer...

1) It has to be placed in a bean class (assuming this is OK)

2) Any parameter of producer method has to be injectable

3) Producers usually do create instances via new, therefore CDI cannot inject anything in. If you need that, you might want to look into another approach (producers are often used to turn non-CDI objects into bean, therefore they have no need for injection into produced beans).

Your producer has a parameter int typeID meaning for CDI to even be able to call and instantiate anything via this method, it needs to have this injectable (for int you would need another producer I imagine). Or, you could place a logic retrieving that typeID directly inside producer method instead of passing it as param.

To sum up, the approach you will want to take depends on how and when do you retrieve your int typeID and if it can change during runtime. In any case I would suggest you drop producer method and instead take a look at Instance<?> in combination with @Qualifier. That should give you enough versatility and dynamic resolution.



来源:https://stackoverflow.com/questions/43423594/add-a-stateful-bean-using-a-producer-and-polymorphism-with-cdi-in-jee

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!