Search code examples
javaconcurrencydependency-injectionjava-ee-7

Java EE 7 - Injection into Runnable/Callable object


Concurrency Utilities(JSR 236) has been introduced in Java EE 7.

Is there any way how to inject my EJBs into Runnable/Callable object?

Specifically I want something like this:

ejb with business logic

@LocalBean
public class MyEjb {
    public void doSomeStuff() {
        ... do some stuff ...
    }
}

runnable/callable class where I want to inject instance of MyEjb

public class MyTask implements Runnable {
    @EJB
    MyEjb myEjb;

    @Override
    public void run() {
        ...
        myEjb.doSomeStuff();
        ...
    }
}

Object which starts the new task

@Singleton
@Startup
@LocalBean
public class MyTaskManager {
    @Resource
    ManagedExecutorService executor;

    @PostConstruct
    void init() {
        executor.submit(new MyTask());
    }
}

myEjb field in MyTask is always null. I suppose there could help JNDI lookup, but is there any proper way how to do this?


Solution

  • You have to give the container a chance to inject the EJB into your Task instance. You can do this by using a dynamic instance like in this code:

    @Stateless
    public class MyBean {
        @Resource
        ManagedExecutorService managedExecutorService;
        @PersistenceContext
        EntityManager entityManager;
        @Inject
        Instance<MyTask> myTaskInstance;
    
        public void executeAsync() throws ExecutionException, InterruptedException {
        for(int i=0; i<10; i++) {
            MyTask myTask = myTaskInstance.get();
            this.managedExecutorService.submit(myTask);
        }
    }
    

    Because you don't create the instance with the new operator but rather over CDI's instance mechanism, the container prepares each instance of MyTask when calling myTaskInstance.get().