CDI multithreading

拈花ヽ惹草 提交于 2019-12-11 09:55:10

问题


We want to optimize our application. There is some streight linear work going on, that can be executed in multiple threads with smaller working sets.

Our typical service is accessed using the @Inject annotation from within our CDI-managed beans. Also such a service could have it's own dependencies injected, i.e.:

public class MyService {

   @Inject
   private OtherService otherService;

   @Inject
   private DataService1 dataService1;

   ...

   public void doSomething() {
     ...
   }
}

Because I can not use @Inject inside the class implementing Runnable. (It's not container managed.) I tried to pass the required services to the class before starting the thread. So, using something like this, makes the service instance (myService) available within the thread:

Class Thread1 implements Runnable{
   private MyService myService

   public Thread1(MyService myService){
      this.myService = myService;
   }

   public void run(){
      myService.doSomething();
   } 
}

Following the call-hierarchy the call to doStometing() is fine, because a reference to myService has been passed. As far as I understand CDI, the injection is done the moment the attribute is accessed for the first time, meaning, when the doStomething() method tries to access either otherService or dataService1, the injection would be performed.

At that point however I receive an exception, that there is no context available.

I also tried to use the JBossThreadExecuter class instead of Plain-Threads - it leads to the very same result.

So the question would be, if there is a nice way to associate a context (or request) with a created Thread?

For EJB-Beans, I read that marking a method with @Asynchronous will cause the method to be run in a managed thread which itself will be wired to the context. That would basically be exactly what I'm searching for.

Is there a way to do this in CDI?

Or is there any way to obtain a context from within a unmanaged thread?


回答1:


Weld allows programmatic context management, (there's an example in the official docs).

But before you go this way give EJBs a chance )
@Async invocation functionality is there exactly for your case. And as a bonus you'll get timeout interception and transaction management.




回答2:


When you kick off an async process, your @RequestScoped and @SessionScoped objects are no longer in scope. That's why you get resolution errors for the injected @RequestScoped objects. Using @Stateless without a CDI scope is essentially @Dependent. You can use @ApplicationScoped objects or if you're on CDI 1.1 you can start up @TransactionScoped.




回答3:


You have to use JavaEE 7 feature, the managed executor. So it will provide a context for your runnable. I'm not sure if your JBoss version is JavaEE 7 compatible. At least Glassfish 4 is, and that approach works. See details here




回答4:


Easiest Solution one can think of is Ejb Async.

They are powerful, does the job and most importantly the concurrency is handled by the container(which could be an issue at some point of time if its not properly managed).

Just a simple use case lets say if we have written a rest service and each request spawns 10 threads(ex using CompletableFuture or anything) to do some long processing tasks and for an instance if 500 requests are made then how will the threads be managed, how the app behaves, does it waits for a thread from the thread pool, what is the timeout period, etc etc and to add to our comfort what happens when the threads are Deamon Threads. We can avoid these overheads to some extent using EJBs.

Its always a good thing to have a friend from the technical services team to help us with all these container specific implementations.



来源:https://stackoverflow.com/questions/21284191/cdi-multithreading

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