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.
For a better maintenance, you can config a AsyncRestTemplate bean:
And then, autowired this bean:
After that, update your callService:
You can remove the
@Async
Annotation as theAsyncRestTemplate
is Asynchronous.