Reputation: 1001
I want to get an idea of using ManagedExecutorService in stateless bean. Basically i am trying to send a http call in a separate thread inside my j2EE application. executorService send this request and wait for x number of seconds to receive response, if no response comes in specified seconds OR get exeception then do another try(X times) and then finally give a feedback that either https service call successfully done or failed. Here is my code
@SuppressWarnings("EjbEnvironmentInspection")
@Resource
ManagedExecutorService executorService;
public static final long RETRY_DELAY = 3000;
public static final int MAX_RETRIES = 3;
executorService.execute(() -> {
int retry = 0;
Collection<Info> responseInfo = null;
while (responseInfo == null && retry++ < MAX_RETRIES) {
try {
responseInfo = httpsService.requestAccessInfo(requestInfo);
Thread.sleep(RETRY_DELAY);
} catch (Exception e) {
log.error("Error while receiving response retry attempt {}", retry);
}
}
boolean status = filledLockAccessInfo==null ? false : true;
event.fire(regularMessage(status,GENERATION_RESULT);
});
Can someone tell me is it a right way to do this OR not.
Upvotes: 0
Views: 270
Reputation: 45339
You shouldn't need to forcibly sleep (Thread.sleep(RETRY_DELAY);
). What you need is an asynchronous invocation of the service that can support timeout.
The following two methods use the completable future API's timeout and error handling to implement that.
The following use recursion to retry the given number of times:
private static Collection<Info> callService(int retryCount) {
try {
CompletableFuture<Collection<Info>> f = invoke();
return f.get(RETRY_DELAY, TimeUnit.MILLISECONDS);
}catch(TimeoutException te) {
if(retryCount > 0) {
return callService(retryCount - 1);
} else {
throw new RuntimeException("Fatally failed!!");
}
} catch(Exception ee) {
throw new RuntimeException("Unexpectedly failed", ee);
}
}
Note that the executorService
object is passed in the second argument of supplyAsync
private static CompletableFuture<Collection<Info>> invoke() {
return CompletableFuture.supplyAsync(() -> {
//call
return httpsService.requestAccessInfo(requestInfo);;
}, executorService);
}
With that, you can simply call it with the number of retries:
Collection<Info> responseInfo = callService(MAX_RETRIES);
To make the above call run asynchronously, you can replace the preceding statement with:
CompletableFuture.supplyAsync(() -> callService(MAX_RETRIES))
.thenAccept(res -> System.out.println("Result: " + res));
This will make the call in the background. Later, you can check how it completed:
f.isCompletedExceptionally() //will tell whether it completed with an exception.
Upvotes: 1