Since starting, I was always confuse of how to deal with InterruptedException and how to properly cancel the http request if they are taking too much time. I have a library in which I am making an URL basis on user id passed in DataKey object and then make http call to the URL using AsyncRestTemplate.
I am using exchange method of AsyncRestTemplate
which returns back a ListenableFuture
.
Below is my code -
public class DataClient implements Client {
// using spring 4 AsyncRestTemplate
private final AsyncRestTemplate restTemplate = new AsyncRestTemplate();
@Override
public DataResponse executeSync(DataKey keys) {
Future<DataResponse> responseFuture = executeAsync(keys);
DataResponse response = null;
try {
response = responseFuture.get(keys.getTimeout(), TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
// do we need to catch InterruptedException here and interrupt the thread?
Thread.currentThread().interrupt();
// also do I need throw this RuntimeException at all?
throw new RuntimeException("Interrupted", ex);
} catch (TimeoutException ex) {
// log here and return DataResponse object
responseFuture.cancel(true); // terminating the tasks that got timed out so that they don't take up the resources? Will this work?
} catch (Exception ex) {
// log here and return DataResponse object
}
return response;
}
@Override
public ListenableFuture<DataResponse> executeAsync(final DataKey keys) {
final SettableFuture<DataResponse> responseFuture = SettableFuture.create();
final org.springframework.util.concurrent.ListenableFuture orig =
restTemplate.exchange(createURL(keys), HttpMethod.GET, keys.getEntity(), String.class);
orig.addCallback(
new ListenableFutureCallback<ResponseEntity<String>>() {
@Override
public void onSuccess(ResponseEntity<String> result) {
responseFuture.set(new DataResponse(result.getBody(), DataErrorEnum.OK,
DataStatusEnum.SUCCESS));
}
@Override
public void onFailure(Throwable ex) {
DataLogging.logErrors(ex, DataErrorEnum.ERROR_SERVER, keys);
responseFuture.set(new DataResponse(null, DataErrorEnum.ERROR_SERVER,
DataStatusEnum.ERROR));
}
});
// propagate cancellation back to the original request
responseFuture.addListener(new Runnable() {
@Override public void run() {
if (responseFuture.isCancelled()) {
orig.cancel(false); // I am keeping this false for now
}
}
}, MoreExecutors.directExecutor());
return responseFuture;
}
}
And we are calling like this -
// if calling executeSync() method directly
DataResponse response = DataClientFactory.getInstance().executeSync(dataKey);
Is it possible to interrupt AsyncRestTemplate call if request is taking too long? I believe, we cannot interrupt RestTemplate calls but not sure on AsyncRestTemplate whether we can do that or not.
Also I am not sure how do I verify whether AsyncRestTemplate calls can be interrupted or not.
Aucun commentaire:
Enregistrer un commentaire