I'm implementing an application-scoped service (to be further injected into JAX-RS/JAX-WS service or a servlet, does not matter) which would spawn some processing via ManagedExecutorService or ManagedThreadFactory. Inside processing code (a Runnable instance), I want to use injected resources like EntityManager, DataSource and web service references. The first solution was like this:
@ApplicationScoped
class MyService {
@Resource private ManagedExecutorService mes;
public void request(String param) {
mes.submit(new MyTask(param));
}
}
class MyTask implements Runnable {
// constructor skipped
@Resource private DataSource ds;
public void run() {
// do processing
}
}
Inside MyTask.run(), the ds
field appears to be null. Okay, this happens because the MyTask instance is not a managed bean, ie it wasn't created by a DI container, so injection is not available for it. Let's change direct instantiation to contextual instance:
@ApplicationScoped
class MyService {
@Resource ManagedExecutorService mes;
@Inject private Instance<MyTask> instance;
public void request(String param) { // <- no way to pass param to MyTask()!
mes.submit(instance.get());
}
}
This works as desired. But is this the right/best way to achieve what I want? Generally, the problem is, how do I create injected/managed instances on demand at runtime. Furthermore, in the latter case I have no ability to pass any parameter to MyTask constructor - is that possible at all, or do I have to introduce MyTask.setParam() method to configure an instance of MyTask?
Passing of parameters to constructor is forbidden by CDI specification - container can only call default constructor or constructor which is annotated with @Inject
, see CDI spec - 3.1.1. Which Java classes are managed beans . So yes, you will have to introduce setter here.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.