angus
angus

Reputation: 3330

Return Rest CompletableFuture with different Http status

The following method will return a list of Strings with status OK.

@Async
@RequestMapping(path = "/device-data/search/asyncCompletable", method = RequestMethod.GET)
public CompletableFuture<ResponseEntity<?>> getValueAsyncUsingCompletableFuture() {
    logger.info("** start getValueAsyncUsingCompletableFuture **");
    // Get a future of type String
    CompletableFuture<List<String>> futureList = CompletableFuture.supplyAsync(() -> processRequest());
    return futureList.thenApply(dataList -> new ResponseEntity<List<String>>(dataList, HttpStatus.OK));
}

I would like to make this method more robust by adding the following features:

1) Since fetching the data will take some time ( processRequest())) than in the meanwhile I would like to return status ACCEPTED so there will be some notification for the user.

2) In case the list is empty then I want to return status NO_CONTENT.

How can I add these enhancements in the same method?

Thank you

Upvotes: 2

Views: 5351

Answers (1)

Sachith Dickwella
Sachith Dickwella

Reputation: 1490

Even though this is an @Async function, you're waiting for processRequest() to complete and thenApply() function takes the results and set HttpStatus.NO_CONTENT to ResponseEntity despite the results status.

You return that already processed result list, just like a synchronized invoke. I would rather let the client to decide if the List is empty or not, after an immediate response.

@Async
@RequestMapping(path = "/device-data/search/asyncCompletable", method = RequestMethod.GET)
public CompletableFuture<ResponseEntity<List<String>>> getValueAsyncUsingCompletableFuture() {
    return CompletableFuture.supplyAsync(() -> ResponseEntity.accepted().body(processRequest()));
}

In the client code, once the get response via RestTemplate of WebClient wait for the response or continue the rest of the tasks.

CompletableFuture<ResponseEntity<List<String>>> response = ... // The response object, should be CompletableFuture<ResponseEntity<List<String>>> type hence returns from the upstream endpoint.
System.out.println(response.get().getBody()); // 'get()' returns a instance of 'ReponseEntity<List<String>>', that's why 'getBody()' invokes.

Well this CompletableFuture.get() is a blocking function and it would wait the current thread until the response arrives. You can continue without blocking for the response until particular response is required in the code.

Upvotes: 1

Related Questions