Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to use EJB Asynchronous methods

I have two tasks that I need to perform say task1 and task2 which are a part of same business process. I have to give response to the end user when task1 completes so it's response time have to be minimized.

My current approach is to perform task1 and as soon as task1 is finished, invoke task2 method asynchronously. task2 is complicated and it's 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 in use) synchronous methods and asynchronous methods are run by different thread pools.

My initial assumption was that even if task2 is performing badly, task1 would have no impact, but sadly that's not true.

If task2 is performing badly, all threads from asynchronous thread pool will be occupied. This will cause task1 to wait for asynchronous threads to be free and hence task1 has impact.

The message in 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 a proper way to achieve what I'm trying to achieve here.

like image 316
ares Avatar asked Jan 13 '16 10:01

ares


People also ask

How do you issue asynchronous method calls?

The simplest way to execute a method asynchronously is to start executing the method by calling the delegate's BeginInvoke method, do some work on the main thread, and then call the delegate's EndInvoke method. EndInvoke might block the calling thread because it does not return until the asynchronous call completes.

What is asynchronous methods in Java?

An Asynchronous call does not block the program from the code execution. When the call returns from the event, the call returns back to the callback function. So in the context of Java, we have to Create a new thread and invoke the callback method inside that thread.

Can we call asynchronous method from another asynchronous method?

There's no rule that says that "asynchronous cannot call asynchronous". There are specific rules in place, such as "future cannot call future". A Queueable can call another Queueable, a Batchable can call another Batchable in the finish method, and Scheduleable methods can call Batchable and Queueable methods.

What are asynchronous business methods?

Session beans can implement asynchronous methods, business methods where control is returned to the client by the enterprise bean container before the method is invoked on the session bean instance.


2 Answers

I think @AccessTimeout is what you are looking for. I see an example here This will limit the amount of time that .doTask2() can run 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 the async process can take, use the handle.get(xx, TimeUnit.xx); method. You will also need to return Future and not just void to make it work.

I hope this suits your use case as you will need to call a .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);
    }

}
like image 41
rjdkolb Avatar answered Sep 23 '22 02:09

rjdkolb


Another alternative would be to increase the "Work request queue size" of the "EJB asynchronous method invocation settings" in the Admin Console. This is a queue, before the actual thread pool itself, so this might buy you some more time.

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

like image 60
matt freake Avatar answered Sep 23 '22 02:09

matt freake