Accessing REST End-point using Spring WebClient

In this blog we will be seeing sample code on how to access the REST End-point using Spring WebClient.

Since there is no active development of RestTemplate, the recommendation is to use WebClient.

With reference to my previous blog in this blog will show an approach to perform Integration test or access the Stock App API using Spring WebClient.

In below code,

  • I have commented out the Bearer Token, since we are not using it
  • First test case uses the RestTemplate for demonstration.
  • Second test case, demonstrates the synchronous approach.
  • Third one is async way of accessing the end-point.

package com.demo.stock.webclient;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;

import reactor.core.publisher.Mono;

@SpringBootTest
public class StockApiWebClient {


    // If we have bearer token we can pass as an environment variable.
   // currently this is commented
     // @Value("${BEARER_TOKEN}")
    // private String bearerToken;

    public final static String API_ENDPOINT = "https://my-stock-boot-app.herokuapp.com";
    public final static String API_ENDPOINT_PATH = "/stock-app/about";

    @Test
    public void simpleRestTemplateClient() {
        HttpHeaders httpHeaders = new HttpHeaders();
        //httpHeaders.add("Authorization","Bearer "+this.bearerToken);

        String url = UriComponentsBuilder.fromHttpUrl(API_ENDPOINT+API_ENDPOINT_PATH)
                //.queryParam("query", "Microsoft News")
                .build()
                .toUriString();

        HttpEntity<?> entity = new HttpEntity<Object>(httpHeaders);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET,entity,String.class);
        System.out.println(response.getBody());
        assertEquals(HttpStatus.OK, response.getStatusCode());
    }

    @Test
    public void simpleWebClient() {

        WebClient client = WebClient.create(API_ENDPOINT);

        //Mono represents a container, that is going to publish or emit a single item in the future
        // when the item is emitted we can use it.
        // in our case it would be a response entity of string
        Mono<ResponseEntity<String>> monoResponse = client.get()     //fire a GET request
                                               .uri(API_ENDPOINT_PATH)
                                               .retrieve()
                                               .toEntity(String.class);

        //To perform a synchronized access, using block method
        ResponseEntity<String> response = monoResponse.block();
        System.out.println(response.getBody());

        assertEquals(200,response.getStatusCodeValue());
    }

    @Test
    public void simpleWebClientAsync() throws InterruptedException {

        WebClient client = WebClient.create(API_ENDPOINT);

        //Mono represents a container, that is going to publish or emit a single item in the future
        // when the item is emitted we can use it.
        // in our case it would be a response entity of string
        Mono<ResponseEntity<String>> monoResponse = client.get() //fire a GET request
                                               .uri(API_ENDPOINT_PATH) //we can use a template here
                                              // .header("Authorization","Bearer "+this.bearerToken) // commented out
                                               .retrieve()
                                               .toEntity(String.class);

        //To perform a Async access, using block method
        monoResponse.subscribe(response -> {
            System.out.println(response.getBody());
            assertEquals(200,response.getStatusCodeValue());    
        });

        System.out.println("Call invoked as async using webclient");
        Thread.sleep(5000);//sleep 5 seconds 
    }
}

In each cases the output will be printed as below,

{"apiName":"Stock Backend API","version":"v1","description":"Simple stock api app, for determining profit or loss based on the investement"}