How to increase timeout AsyncRestTemplate class?

2019-06-09 19:37发布

I have developed some async web services with spring framework and REST, I have consumed it from a client created with spring class AsyncRestTemplate. Class return an object ListenableFuture<ResponseEntity<T>> (with the method getForEntity), which brings the value returned by the web service (with the method .get():<T>) . It works fine, however when the web service takes a lot time the method isDone() of ListenableFuture class return a value true, even when the web service has not finished to work.

If I try to recover the web service response with the method get() in the client and It has late a lot of time, I always get the follows message:

   "timestamp": "2018-05-29T22:42:26.978+0000",
   "status": 500,
   "error": "Internal Server Error",
   "message": "java.util.concurrent.ExecutionException: org.springframework.web.client.HttpServerErrorException: 503 null",
   "path": "/client/result"

Does someone knows how can i solve the problem?. I want the client shows me the web service response, even when the web service takes a lot time (I want to increase the timeout).

The server codes are the following:

Configuration Class:

@Configuration
@EnableAsync
public class ConfigurationClass {
    @Bean
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

Controller class:

@RestController
@RequestMapping("/server")
public class ControllerClass {

    @GetMapping("/start")
    @Async
    public CompletableFuture<String>  callService() throws InterruptedException{
        Thread.sleep(100000L);
        return CompletableFuture.completedFuture("OK");
    }
}

The client code (consumer) is the following:

@RestController
@RequestMapping("/client")
public class ControllerClass {

    private ListenableFuture<ResponseEntity<String>> entity;

    @GetMapping("/start")
    @Async
    public void callService() throws InterruptedException {
        AsyncRestTemplate restTemplate = new AsyncRestTemplate();
        entity = restTemplate.getForEntity("http://localhost:8080/server/start",
                 String.class);
    }

    @GetMapping("/state")
    public boolean getState() {
        try {
            return entity.isDone();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/result")
    public ResponseEntity<String> getResult() {
        try {
            return entity.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

I tried to increase the property timeout in application.property file, but it did not work.

# SPRING MVC (WebMvcProperties)
spring.mvc.async.request-timeout= 500000 # Amount of time before asynchronous request handling times out.

Thanks for your help, Regards.

1条回答
放荡不羁爱自由
2楼-- · 2019-06-09 20:10

For a better maintenance, you can config a AsyncRestTemplate bean:

@Bean
public AsyncRestTemplate asyncRestTemplate() {
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setTaskExecutor(new SimpleAsyncTaskExecutor());
    factory.setConnectTimeout(1000);//milliseconds
    factory.setReadTimeout(2000);//milliseconds
    return new AsyncRestTemplate(factory);
}

And then, autowired this bean:

@Autowired
private AsyncRestTemplate restTemplate;

After that, update your callService:

@GetMapping("/start")
public void callService() throws InterruptedException {
    entity = restTemplate.getForEntity("http://localhost:8080/server/start",
             String.class);
}

You can remove the @Async Annotation as the AsyncRestTemplate is Asynchronous.

查看更多
登录 后发表回答