Home > other >  CompletableFuture.get() outputs rather status than response body
CompletableFuture.get() outputs rather status than response body

Time:12-09

I have the following scenario: I set up a client which sends an aynchronous HTTP reuqest to the server. The client receives a CompletableFuture. So far evertything works fine. However, I cannot access the response of the request I am sending.

completableFuture.get().body()

rather contains the status of the request. In more detail, I am getting

{"cancelled":false,"done":true,"completedExceptionally":false,"numberOfDependents":0}

How can I get the acutal result?

Here is my code...

Rest Controller

@RestController
public class WorkerJController {

    @Autowired
    private WorkerJService service;

    @GetMapping(value = "/JobList", produces = MediaType.APPLICATION_JSON_VALUE)
    public CompletableFuture<ResponseEntity> getJobListFunction() throws JsonProcessingException, InterruptedException {
        return CompletableFuture.completedFuture(service.getJobListFunction()).thenApply(ResponseEntity::ok);
    }
}

Service

@Service
public class WorkerJService {

    public static ArrayList<someThing> randomList = new ArrayList<>();

    @Async
    public CompletableFuture<String> getJobListFunction() throws JsonProcessingException, InterruptedException {
        randomList.add(new someThing("abc", "dfe"));
        ObjectMapper mapper = new ObjectMapper();
        TimeUnit.SECONDS.sleep(5);
        return CompletableFuture.completedFuture(mapper.writeValueAsString(jobList));
    }
}

Async Config

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name = "taskExecutor")
    public Executor taskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(3);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("AsynchThread-");
        executor.initialize();
        return executor;

I send the HTTP request as follows:

HttpClient client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_1_1)
        .followRedirects(HttpClient.Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
        .build();

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("http://localhost:8080/JobList"))
        .timeout(Duration.ofMinutes(2))
        .GET()
        .build();

CompletableFuture<HttpResponse<String>> cf = client
        .sendAsync(request, HttpResponse.BodyHandlers.ofString());

CodePudding user response:

CompletableFuture.completedFuture(service.getJobListFunction()) wraps the CompletableFuture returned by service.getJobListFunction() into another CompletableFuture.

Just chain the response from the service directly with the thenApply() instead:

@GetMapping(value = "/JobList", produces = MediaType.APPLICATION_JSON_VALUE)
public CompletableFuture<ResponseEntity> getJobListFunction() throws JsonProcessingException, InterruptedException {
    return service.getJobListFunction().thenApply(ResponseEntity::ok);
}
  • Related