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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…