"Welcome To Ashok IT" "Spring Boot & Microservices" Topic : RestClient Development(WebClient) Date : 09/01/2025 (Session - 102 & 103) _____________________________________________________________________________________________________________________________ Yesterday Session ================= * We completed working with Rest Client Development using RestTemplate Class from Spring Framework. * RestTemplate Class will not comes through AutoConfiguration, It should be Spring Bean explictly by the Programmer in Spring Boot Application. * RestTemplate Class contains several utility method to consume RestAPI's 1) getForEntity() 2) getForObject() 3) postForEntity() 4) postForObject() 5) put() 6) delete() 7) exchange() Today Session ============= Rest Client =========== * So far we developed the Rest API's and also how to generate documentation for Rest API's and also tested the Rest API's by using POSTMAN Tool and Swagger3/OpenAPI Documentation. * RestClient is a Java Program which is used to consume services from Rest API (or) Rest Client is used to access the Rest API's. * For Business-to-Business we will develop a program to access Rest API. * The Program which is accessing Rest API can be called as "Rest Client". * Inorder to develop Rest Client, We need Rest API Documentation. * Rest API documentation will be provided through Swagger3 and with out knowing the API Details Of Rest API we can't the RestClient Application. * We can develop the RestClient with following techniques 1) HttpClient >>>>>>>>>>>> JDK Library(java.net), Java11 Version 2) RestTemplate >>>>>>>>>>>> Spring Framework and currently its outdated. 3) WebClient >>>>>>>>>>>> Introduced in Spring 5.X. 4) FeignClient >>>>>>>>>>>> Spring Cloud. HttpClient ========= * HttpClient is an Predefined Class of JDK Library from Java11 Version. * By using HttpClient we can consume RestAPI's through Java Standalone Application. * We can create an object of HttpClient class by using Builder Design Pattern. * By using this mechanism we can make communicate with Rest API's either Synchronously (or) Asynchronously. * We can create the Object of HttpClient as below HttpClient httpClient = HttpClient.newHttpClient(); * We can create an object of HttpRequest Class by using Builder Design pattern HttpRequest request = HttpRequest.newBuilder().header("Header-Name","Header-value") .uri(URI.create(RestAPI_URL)) .get/post/patch/put(HttpRequest.BodyHandlers.ofString(payloaddata)).build(); * We can send the Request to Rest API HttpResponse response = httpClient.send(request,HttpResponse.BodyHandlers.ofString()); Example ======= * Create the Spring Boot Application with "Web" Starter Application.java ================ package com.ashokit; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.fasterxml.jackson.core.PrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootApplication public class Application implements CommandLineRunner{ public static void main(String[] args) { SpringApplication.run(Application.class, args); } public void run(String... args) throws Exception { //getRequestByHttpClient(); postRequestByHttpClient(); } public void getRequestByHttpClient()throws Exception { // Creating the HttpClient Object HttpClient httpClient = HttpClient.newHttpClient(); // Creating HttpRequest Object HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8899/api/wishes/")).GET() .build(); // Sending request to RestAPI HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { String responseBody = response.body(); System.out.println(responseBody); } else { System.out.println("HttpRequest Has beeen failed......" + response.statusCode()); } } public void postRequestByHttpClient()throws Exception{ //Preparing PersonDTO objet for Request Body PersonDTO person = new PersonDTO("Kiran", "Mumbai", "kiran@gmail.com", "XYZ Street"); //Creating ObjectMapper object ObjectMapper mapper = new ObjectMapper(); //Converting the JavaObject into JSON String String requestBody = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(person); System.out.println("Request Body:::"+ requestBody); // Creating the HttpClient Object HttpClient httpClient = HttpClient.newHttpClient(); // Creating HttpRequest Object HttpRequest request = HttpRequest.newBuilder() .header("Content-Type", "application/json") .header("Accept", "application/json") .uri(URI.create("http://localhost:8899/api/persons/")) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); //Sending the Request HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); //checking response if(response.statusCode() == 201) { System.out.println(response.body()); }else { System.out.println("HttpRequest Has been failed :::::" + response.statusCode()); } } } OUTPUT ====== Request Body::: { "name" : "Kiran", "location" : "Mumbai", "emailId" : "kiran@gmail.com", "address" : "XYZ Street" } { "id":3003, "name":"Kiran", "location":"Mumbai", "emailId":"kiran@gmail.com", "address":"XYZ Street", "createdDate":"2023-09-20" } RestTemplate ============ * RestTemplate is used to develop the Rest Client in synchronous manner that means after making Rest Call we have to wait until we received response from Rest API then only our execution will continue. * RestTemplate is an predefined Class which does not comes through Auto Configuration process... It must be created object for this class either by using "new" keyword with @Bean method Example ======= 1) RestTemplate rt = new RestTemplate(); (or) 2) @Bean public RestTemplate getRestTemplateObj(){ return new RestTemplate(); } RestTemplate class contains lot of utility methods such as getForEntity(),getForObject(),postForEntity(),exchange() etc., NOTE: ===== * JdbcTemplate,RestTemplate,NamedParameterJdbcTemplate,JndiTemplate etc., classes are given based template method design pattern which says that the template class takes care of common logics and programmer should take care of Specific Logics. * WebClient is modern API which is used to develop Rest Client and by using webclient we can develop both synchronous & Unsynchronous clients and we can say that Webclient is replacement of RestTemplate. * Feign Client is part of Spring Cloud Library. Steps for Developing Rest Client Program ======================================== 1) Create new Spring boot project(37_SpringBootRest_RestClientDevelopment_App) with below dependencies * Spring Web * Spring Dev Tools 2) Develop the ApplicationConfig to mark the RestTemplate as Spring Bean ApplicationConfig.java ======================= package com.ashokit.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ApplicationConfig { //Mark the RestTemplate class as spring bean @Bean public RestTemplate getRestTemplateObject() { return new RestTemplate(); } } 3) Develop the RestClient Program in Main Class Application.java ================ package com.ashokit; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; @SpringBootApplication public class Application implements ApplicationRunner { @Autowired private RestTemplate restTemplate; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @SuppressWarnings("deprecation") @Override public void run(ApplicationArguments args) throws Exception { //API Details :::: http://localhost:8899/api/wishes/ // :::: GET Request API with out PathVariable // :::: String As Response String endPointURL = "http://localhost:8899/api/wishes/"; ResponseEntity forEntity = restTemplate.getForEntity(endPointURL, String.class); int statusCodeValue = forEntity.getStatusCodeValue(); if(statusCodeValue == 200) { System.out.println("API Response ::::" + forEntity.getBody()); //Getting Response Body } //API Details :::: http://localhost:8899/api/wishes//{username} // :::: Path Variable name :::: username // :::: GET Request API With PathVariables // :::: String as Response endPointURL = "http://localhost:8899/api/wishes/{username}"; ResponseEntity forEntity2 = restTemplate.getForEntity(endPointURL, String.class, Map.of ("username","Mahesh","password","Ashokit")); HttpStatusCode statusCode = forEntity2.getStatusCode(); if(statusCode.is2xxSuccessful()) { String responseBody = forEntity2.getBody(); System.out.println("API Response::::::" + responseBody); } //working with getForObject() String responseBody = restTemplate.getForObject(endPointURL, String.class, Map.of("username","Ashok")); System.out.println("API Response::::" + responseBody); } } OUTPUT ====== API Response :::::: Welcome To Customer Controller... API Response :::::: Welcome To Customer Controller Mahesh API Response :::::: Welcome To Customer Controller Ashok NOTE ==== * Make sure Producer Application should be run and UP and also verify those API's are working or not by testing through postman (or) Swagger. IIQ) Differences between getForEntity() Vs getForObject() ? -> getForEntity() return type is ResponseEntity which contains more details of response object(Response status code,Response Body,Response Headers etc.,) -> getForObject() return type is T(Typed Parameter) simply will returns only Response Body. Application.java ================ package com.ashokit; import java.time.LocalDate; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import com.ashokit.dto.PersonDTO; import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootApplication public class Application implements ApplicationRunner { @Autowired private RestTemplate restTemplate; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @SuppressWarnings("deprecation") @Override public void run(ApplicationArguments args) throws Exception { //API Details :::: http://localhost:8732/customers/wishes // :::: GET Request API with out PathVariable // :::: String As Response String endPointURL = "http://localhost:8732/customers/wishes"; ResponseEntity forEntity = restTemplate.getForEntity(endPointURL, String.class); int statusCodeValue = forEntity.getStatusCodeValue(); if(statusCodeValue == 200) { System.out.println("API Response ::::" + forEntity.getBody()); //Getting Response Body } //API Details :::: http://localhost:8732/customers/wishes/{username} // :::: Path Variable name :::: username // :::: GET Request API With PathVariables // :::: String as Response endPointURL = "http://localhost:8732/customers/wishes/{username}"; ResponseEntity forEntity2 = restTemplate.getForEntity(endPointURL, String.class, Map.of ("username","Mahesh")); HttpStatusCode statusCode = forEntity2.getStatusCode(); if(statusCode.is2xxSuccessful()) { String responseBody = forEntity2.getBody(); System.out.println("API Response::::::" + responseBody); } //working with getForObject() String responseBody = restTemplate.getForObject(endPointURL, String.class, Map.of("username","Ashok")); System.out.println("API Response::::" + responseBody); //working with exchange() endPointURL = "http://localhost:8732/customers/wishes"; ResponseEntity exchangeMessage = restTemplate.exchange(endPointURL, HttpMethod.GET, null, String.class); if(exchangeMessage.getStatusCodeValue() == 200) { String responseMessage = exchangeMessage.getBody(); System.out.println("API Response:::::" + responseMessage); } //API Details ::: http://localhost:8899/api/persons/ ::: Post Request ::: Input as JSON & Output as JSON PersonDTO dto = new PersonDTO(); dto.setName("Test-1"); dto.setEmailId("test-1@ashokit.com"); dto.setContactNo("1232323333"); dto.setLocation("Hyderabad"); //converting the Java Object into JSON ObjectMapper objectMapper = new ObjectMapper(); String jsonString = objectMapper.writeValueAsString(dto); System.out.println("JSON String::::" + jsonString); //Prepare Headers HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); //Preparing the HttpRequest using HttpEntity object with headers HttpEntity request = new HttpEntity<>(jsonString,headers); ResponseEntity postForEntity = restTemplate.postForEntity("http://localhost:8899/api/persons/", request, String.class); if(postForEntity.getStatusCodeValue() == 201) { String postResponse = postForEntity.getBody(); System.out.println("API Response:::::" + postResponse); } } } OUTPUT ====== API Response :::: Welcome To Customer Controller... API Response :::: Welcome To Customer Controller Mahesh API Response :::: Welcome To Customer Controller Ashok API Response :::: Welcome To Customer Controller... JSON String ::::{"id":null,"name":"Test1","location":"Hyderabad","contactNo":"1232323333","emailId":"test1@ashokit.com","createdDate":null} API Response :::: Person Registered Successfully With Person ID Has :::::13 Assignment ========== * RestTemplate --------------> PostForObject(),put() * RestTemplate Class Utiltity Methods 1) getForEntity() 2) getForObject() 3) postForEntity() 4) postForObject() 5) put() 6) delete() 7) exchange() * RestTemplate Class will support the "Synchronous Calls" and also called as "Blocking Call" Nature. WebClient ========= * Developing RestClient application using "WebClient" and this webclient given from Spring 5.x Version onwards. * Webclient can support for both synchronous & Asynchronous Communications. * Working with Webclient is nothing but Spring Reactive Programming. * Spring Reactive Programming is one kind of programming style which can be executed Java logic based on events. * Inorder to support Reactive Programming in Spring Boot we need to use the following starter i.e., "Springboot-starter-webflux" (Reactive Web) in our pom.xml file. * In Reactive Programming we have two important keywords 1) mono >>>>>> Mono object always representing Single Response from Rest API. 2) flux >>>>>> Flux object always representing the Continous Response from Rest API. Steps for Developing WebClient Application =========================================== 1) Create Spring Boot Application with below starters - Spring Web - Spring Reactive Web 2) Develop the Client Application for below code Application.java ================ package com.ashokit; import java.net.URI; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.WebClient; import com.ashokit.dto.PersonDTO; import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootApplication public class Application implements ApplicationRunner{ public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(ApplicationArguments args) throws Exception { //Creating WebClient object WebClient webClient = WebClient.create(); //Defining the endpoint URL String endPointURL = "http://localhost:8899/api/login/"; String responseMessage = webClient.get() //This is for testing Get Request API .uri(new URI(endPointURL)) //This for defining the REST API URL .retrieve() //This for retrieving API Response Body .bodyToMono(String.class)//Defining Response Type .block();//It will block thread until we got response from Rest API System.out.println("API Response::::::" +responseMessage); System.out.println("================================================================="); //Callback methods webClient.get() .uri(new URI(endPointURL)) .retrieve() .bodyToMono(String.class) .subscribe(Application :: responseHandling); //API Details ::: http://localhost:8899/api/persons/ PersonDTO dto = new PersonDTO(); dto.setName("Test-2"); dto.setEmailId("test-2@ashokit.com"); dto.setContactNo("1232323333"); dto.setLocation("Hyderabad"); //converting the Java Object into JSON ObjectMapper objectMapper = new ObjectMapper(); String jsonString = objectMapper.writeValueAsString(dto); System.out.println("JSON String::::" + jsonString); //WebClient using post API String postResponse = webClient.post() .uri(new URI("http://localhost:8732/persons/")) .contentType(MediaType.APPLICATION_JSON) .bodyValue(jsonString) .retrieve() .bodyToMono(String.class) .block(); System.out.println("Post Response:::::"+ postResponse); } public static void responseHandling(String message) { System.out.println("API Response::::::" + message); } } OUTPUT ====== API Response::::::Welcome To Customer Controller... =================================================== API Response::::::Welcome To Customer Controller... JSON String::::{"id":null,"name":"Test-2","location":"Hyderabad","contactNo":"1232323333","emailId":"test- 2@ashokit.com","createdDate":null} Post Response:::::Person Registered Successfully With Person ID Has :::::15