I know that messing with threads inside an EJB is a big no-no, but I would just like to ask for advice on how handle this case. My EJB is calling an external Web service which may sometimes return a "busy" status. When that happens, I would like to wait for a while and then resubmit the request using the same data as before.
What would be the best way to implement this?
Thread. sleep() method can be used to pause the execution of current thread for specified time in milliseconds. The argument value for milliseconds can't be negative, else it throws IllegalArgumentException .
Thread. sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.
Note that sleep is a static method, which means that it always affects the current thread (the one that is executing the sleep method). A common mistake is to call t. sleep() where t is a different thread; even then, it is the current thread that will sleep, not the t thread.
Thread. sleep is bad! It blocks the current thread and renders it unusable for further work.
EJB 3.1 brought a new @Asynchronous
feature that you can take advantage of:
@Asynchronous
@TransactionAttribute(NOT_SUPPORTED)
public Future<WebServiceResult> callWebService(int retries) {
WebServiceResult result = webService.call();
if (!result.equals(BUSY)) {
return result;
}
if (retries <= 0) {
throw new TooBusyException();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return callWebService(retries - 1);
}
Then simply call you web service with:
Future<WebServiceResult> result = yourEJB.callWebService(1);
// Can do some interesting stuff here.
// ...
// ...
result.get(2, SECONDS); // Block for up to 2 seconds.
As you can see you get configurable number of retries and timeout for free.
How does this differ from just calling Thread.sleep()
? Returning Future
is more explicit and manageable. Also I don't think Thread.sleep()
is that harmful. The only problem is that this EJB instance can now longer be reused by other clients. With Future
asynchronous invocation happens inside some other EJB and thread pool. As to importance of Thread#interrupt()
inside the catch block, refer Why invoke Thread.currentThread.interrupt() when catch any InterruptException?
Another idea: use aspect around calling web service, catch BusyException
once and retry.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With