简体   繁体   中英

How can we make asynchronous REST api call in Java?

I am using Spring RestTemplate and want to make a call to another service that doesn't return any response body. So, I don't want to wait for the response. So, it's just fire and forget, and continue with the remaining code. I am thinking of creating a new Thread to do this but really not sure what's the correct approach.

If you use Java 11, java support asynchronous HTTP Client. Asynchronous client using CompletableFuture in the back. You can see javadoc .

HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://openjdk.java.net/"))
            .timeout(Duration.ofMinutes(1))
            .header("Content-Type", "application/json")
            .POST(BodyPublishers.ofFile(Paths.get("file.json")))
            .build();

    client.sendAsync(request, BodyHandlers.ofString())
            .thenApply(response -> { System.out.println(response.statusCode());
                return response; } )
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println);

The correct approach is to execute the async with a callback (using DeferredResult , like this (assuming we have a class someClass that we want to retrieve from the API:

@GetMapping(path = "/testingAsync")
public DeferredResult<String> value() throws ExecutionException, InterruptedException, TimeoutException {
   AsyncRestTemplate restTemplate = new AsyncRestTemplate();
   String baseUrl = "http://someUrl/blabla";
   HttpHeaders requestHeaders = new HttpHeaders();
   requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
   String value = "";

   HttpEntity entity = new HttpEntity("parameters", requestHeaders);
   final DeferredResult<String> result = new DeferredResult<>();
   ListenableFuture<ResponseEntity<someClass>> futureEntity = restTemplate.getForEntity(baseUrl, someClass.class);

   futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<someClass>>() {
      @Override
      public void onSuccess(ResponseEntity<someClass> result) {
         System.out.println(result.getBody().getName());
         result.setResult(result.getBody().getName());
      }

      @Override
      public void onFailure(Throwable ex) {
         result.setErrorResult(ex.getMessage());
      }
  });

  return result;
}

There are many ways you can use to fire the request using the AsyncRestTemplate

The simplest way is just like restTemplate and call exchange method:

AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
JSONObject json = new JSONObject();
json.put("firstName","testUser");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<String>(json.toString(), headers);

Class<String> responseType = String.class;
ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.exchange("https://xxxxx.com/", HttpMethod.POST, requestEntity,responseType );

// If you want for the result then you can use 
 try {
        //waits for the result
        ResponseEntity<String> entity = future.get();
        //prints body source code for the given URL
        log.info(entity.getBody());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
}

If we want to play with the failure (fallback scenario) or success in that case we can use the below code :

AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
JSONObject json = new JSONObject();
json.put("firstName","testUser");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<String>(json.toString(), headers);

 //final DeferredResult<String> result = new DeferredResult<>();
 ListenableFuture<ResponseEntity<String>> future = 
 asyncRestTemplate.postForEntity("https://xxxx.com", requestEntity, String.class);

  future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {

 @Override
 public void onFailure(Throwable ex) {
// insert into the table or log or some other decision
 log.info(ex.getMessage());
 }

        @Override
        public void onSuccess(ResponseEntity<String> result) {
            log.info(result.getBody());
            log.info("Sucess");
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM