问题
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