7

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, i.e. 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?

Petr Mensik
  • 26,874
  • 17
  • 90
  • 115
Dimitri
  • 301
  • 2
  • 13

1 Answers1

2

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.

Petr Mensik
  • 26,874
  • 17
  • 90
  • 115