Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blocking on ListenableFuture with timeout

I'm using Spring 4.2.3 AsyncRestTemplate.exchange() to call some API that will take several seconds, and i'm expecting that listenableFuture.get(1, TimeUnit.SECONDS) will block for 1 second and then throw TimeOutException.

What happens instead is that listenableFuture.get() will block for the whole time of the api call (more than 1 second)

    AsyncRestTemplate restTemplate = new AsyncRestTemplate();

    ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.exchange(URL, HttpMethod.GET, null, String.class);
    log.debug("before callback");

    //...add callbacks

    try{
        log.debug("before blocking");
        listenableFuture.get(1, TimeUnit.SECONDS);
    }catch (InterruptedException e) {
        log.error(":GOT InterruptedException");
    } catch (ExecutionException e) {
        log.error(":GOT ExecutionException");
    } catch (TimeoutException e) {
        log.info(":GOT TimeoutException");
    }

    log.info("FINISHED");

Output:

    09:15:21.596  DEBUG [main] org.springframework.web.client.AsyncRestTemplate:78 - Created asynchronous GET request for "http://localhost:4567/oia/wait?seconds=5"
    09:15:21.666  DEBUG [main] org.springframework.web.client.RestTemplate:720 - Setting request Accept header to [text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*]
    09:15:21.679  DEBUG [main] com.zazma.flow.utils.FutureTest:74 - before callback
    09:15:21.679  DEBUG [main] com.zazma.flow.utils.FutureTest:95 - before blocking
    09:15:26.709  DEBUG [main] org.springframework.web.client.AsyncRestTemplate:576 - Async GET request for "http://localhost:4567/oia/wait?seconds=5" resulted in 200 (OK)
    09:15:26.711  DEBUG [main] org.springframework.web.client.RestTemplate:101 - Reading [java.lang.String] as "text/html;charset=utf-8" using [org.springframework.http.converter.StringHttpMessageConverter@3a44431a]
    09:15:26.717   INFO [main] com.zazma.flow.utils.FutureTest:105 - FINISHED

Here is an example that the ListenableFuture.get() will work as expected when not created by the AsyncRestTemplate

SimpleAsyncTaskExecutor te = new SimpleAsyncTaskExecutor();
    ListenableFuture<String> lf = te.submitListenable(() -> {
        Thread.sleep(8000);
        return "OK";
    });

    lf.get(1, TimeUnit.SECONDS);
like image 699
Yoni Avatar asked Feb 16 '17 07:02

Yoni


1 Answers

You code is perfectly correct. What is causing a problem is a bug in spring framework. Although, I didn't manage to find it in spring's issue tracker (or possibly it is not documented), you can fix it by updating dependencies. For sure, your code will work with version of spring-web >= 4.3.2.RELEASE.

like image 171
dchrzascik Avatar answered Nov 05 '22 11:11

dchrzascik