5

How can you integrate Spring Retry with external calls with AsyncRestTemplate? If it's not possible, is there another framework that supports it?

My use case:

public void doSomething() throws ExecutionException, InterruptedException {

    ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.getForEntity("http://localhost/foo", String.class);

    // do some tasks here

    ResponseEntity<String> stringResponseEntity = future.get(); // <-- How do you retry just this call?

}

How do you retry this future.get() call? If the external service returns a 404, I want to avoid calling those tasks in between again and just retry the external call? I can't just wrap future.get() with a retryTemplate.execute() because it won't actually make another call to the external service.

Glide
  • 20,235
  • 26
  • 86
  • 135

1 Answers1

0

You have to wrap the entire doSomething (or at least the template operation and get) in a retry template.

EDIT

Instead of calling get() you could add a ListenableFutureCallback to the future; something like this...

final AtomicReference<ListenableFuture<ResponseEntity<String>>> future = 
    new AtomicReference<>(asyncRestTemplate.getForEntity("http://localhost/foo", String.class));

final CountDownLatch latch = new CountDownLatch(1);
future.addCallback(new ListenableFutureCallback<String>() {

    int retries;

    @Override
    public void onSuccess(String result) {

         if (notTheResultIWant) {
             future.set(asyncTemplate.getFor (...));
             future.get().addCallback(this);    
             retries++;        
         }
         else {
              latch.countDown();
         }
    }

    @Override
    public void onFailure(Throwable ex) {
         latch.countDown();
    }

});


if (latch.await(10, Timeunit.SECONDS) {
    ...
    future.get().get();
}
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • 1
    By doing that, I'd execute the calls in between the template operation and get as well, right? Is there a way to retry just the external call and have the methods in between execute asynchronously? (i.e. the template operation and get *could* be moved to the top of the method, but by doing `future.get()`, the current thread will be blocked which defeats the purpose of using `AsyncRestTemplate` for the external call. – Glide Mar 07 '16 at 15:21