The Right Way to Use EJB Asynchronous Methods

I have two tasks that I need to complete: task1 and task2 , which are part of the same business process. I have to give an answer to the end user when task1 completes, so the response time should be kept to a minimum.

My current approach is to execute task1 and once task1 is complete call the task2 method asynchronously. task2 is complex, and the response time is out of my control, as it has some external dependency.

 @Stateless public class SessionBean1 { @Inject SessionBean2 sessionBean2; public void doTask1(){ // task one stuff sessionBean2.doTask2(); } } @Stateless public class SessionBean2 { @Asynchronous public void doTask2(){ // do task2 stuff } } 

In websphere 8.0 (the EJB container used), synchronous methods and asynchronous methods are executed by different thread pools.

My initial assumption was that even if task2 does not work well, task1 will not be affected, but unfortunately this is not the case.

If task2 does not work well, all threads from the asynchronous thread pool will be busy. This will cause task1 expect asynchronous threads to be free, and therefore task1 has an effect.

Websphrere server logs: The request buffer for thread pool WorkManager.WebSphere_EJB_Container_AsynchMethods_Internal_WorkManager has reached its capacity

My question is what would be the right way to achieve what I am trying to achieve here.

+5
source share
2 answers

Another alternative would be to increase the size of the work request queue "Parameters for calling the asynchronous EJB method" in the administrator console. This is the queue in front of the pool thread itself, so it may buy you some more time.

Ideally, this should be used in conjunction with the timeouts suggested above.

+2
source

I think @AccessTimeout is what you are looking for. I see an example here. This will limit the amount of time that .doTask2 () can do and avoid your problem.

 @Stateless public class SessionBean1 { @Inject SessionBean2 sessionBean2; public void doTask1(){ // task one stuff sessionBean2.doTask2(); } } 

SessionBean2

 @Stateless public class SessionBean2 { @AccessTimeout(60000)//default timeunit is TimeUnit.MILLISECONDS @Asynchronous public void doTask2(){ // do task2 stuff } } 

As an alternative:

To limit the time that the async process can run, use handle.get (xx, TimeUnit.xx); method. You will also need to bring back the Future, not just the void, in order to make it work.

I hope this is appropriate for your use case, as you will need to call .get

 @Stateless public class SessionBean1 { @Inject SessionBean2 sessionBean2; public void doTask1(){ // task one stuff Future<Void> handle = sessionBean2.doTask2(); // do other stuff handle.get(10, TimeUnit.SECONDS);//If you want to block later } } 

SessionBean2

 @Stateless public class SessionBean2 { @Asynchronous public Future<Void> doTask2(){ // do task2 stuff new AsyncResult<Void>(Void); } } 
+2
source

Source: https://habr.com/ru/post/1240513/


All Articles