You are here
Home > java >

How to write REST Consumer API using Spring Boot? : RestTemplate

How to write REST Consumer API using Spring Boot? : RestTemplateApart from three well known layers i.e. Presentation Layer, Service Layer and Data Layer, we may also have an Integration Layer. This layer generally works with the web services concept and connects two different applications to exchange data between them. One application refers to producer/provider, whereas other refers to consumers. However, we have already gone through the REST Producer API in another article where we had developed different operations to produce REST API. Now, we must have a question in mind ‘How to write REST Consumer API using Spring Boot? : RestTemplate’. We had also discussed a bit about RestTemplate( The Spring REST Client).

In fact, RestTemplate provides us Consumer methods to consume services provided by producer applications. We can even have various non-java Consumer applications. However, our RestTemplate is written in Java only. Accordingly, let’s start working on ‘How to write a REST Consumer API using Spring Boot?: RestTemplate’.

What will you learn from this article ?

1) What is RestTemplate and what is it used for?
2) What is the difference between the various methods of RestTemplate?
3) When to use, which method of RestTemplate?
4) How is the exchange () method used in implementing Rest Consumer Web Services?
5) Also, Which format of data does the producer application provide and which format of data does the consumer application receive?
6) What are all parameters of RestTemplate method to develop the consumer application?
7) How to write a REST Consumer API using Spring Boot: RestTemplate?
8) Additionally, How to use slf4j Logger effectively while implementing RestTemplate?
9) Finally, How to test the developed application?

What is Rest Template ?

In a nutshell, RestTemplate is a predefined class in Spring Boot REST project. Moreover  It helps in making HTTP calls to Producer application with all method types eg. GET, POST, PUT, DELETE etc. However Spring Boot framework doesn’t auto configure this class. It also supports JSON/XML to Object and Object to JSON/XML auto-conversion. Moreover, it requires Endpoint details from a producer application like IP, PORT, Paths, Method Type, Input data format and Output data format etc. Additionally, RestTemplate provides the exchange() method to consume the web services for all HTTP methods. In fact, RestTemplate helps in making HTTP Rest Calls.

What is difference between getForObject() and getForEntity() ?

Having knowledge of getforentity vs getforobject is important for us as we will be using these methods in our implementation.

getForObject(url, T.class) : It retrieves an entity using HTTP GET method on the given URL and returns T.  It doesn’t return Status, Header params but only Response Body.
getForEntity(url, T.class) : It retrieves an entity by using HTTP GET method for the given URL and returns ResponseEntity<T>.

What is difference between postForObject() and postForEntity() ?

postForObject(url, request, T.class) : It saves an entity using HTTP POST method on the given URL and returns T.  It doesn’t return Status, Header params but only Response Body.
postForEntity(url, request, T.class) : It saves an entity by using HTTP POST method for the given URL and returns ResponseEntity<T>.

What is exchange() method in RestTemplate used for ?

exchange() method supports making call to any Http method (GET/POST/PUT/DELETE/…..). Generally, it has below syntax.

exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object… uriVariables): ResponseEntity<T>

url : Producer application URL (RestController’s mrthod path)
HttpMethod : is an enum to provide method type.
HttpEntity : Request Body + HttpHeaders (it can also be null)
responseType : Class type of response
Object-var/args : used for sending multiple pathVariables

What is the format of data Consumer Application receives from Producer Application ?

If any RestController’s method returns a non-String type i.e. class or collection type then Data is converted into JSON format and provided to Consumer Application. Consumer application reads that data as a String (JSON is also a String only).

What all parameters are expected to write consumer methods in RestTemplate ?

In fact consumer method could be predictable on the already existing producer method. The producer method’s url, return type, Http method type, path variables etc. will decide the structure of your consumer method. Generally we expect following things to pass as parameters to RestTemplate’s methods.

  1. URL of Producer webservice
  2. Body of the request (in case of POST/PUT…)
  3. Media Type like APPLICATION_JSON, APPLICATION_XML, APPLICATION_PDF  etc. (in case of POST/PUT…)
  4. Http Method type
  5. Return type of producer method
  6. Path Variables (If any)

How to implement RestTemplate methods ?

Although we will take reference of REST API producer application that we developed in previous articles and call the already existing methods with the help of RestTemplate. Here, we are considering “Invoice” as our model class. Besides exchange() method, we will take one more alternate method to develop the template operations. Alternate method is commented in below code. Afterwards You can un-comment the same as per your requirement to test it accordingly.

Save Invoice

saveInv()
private void saveInv() {
		// 1. Producer application URL
		String url = "http://localhost:8080/invoice/rest/saveInvoice";
		// Send JSON data as Body
		String body = "{\"name\":\"INV11\", \"amount\":234.11,\"number\":\"INVOICE11\",\"receivedDate\":\"28-10-2020\",\"type\":\"Normal\",\"vendor\":\"ADHR001\",\"comments\" :\"On Hold\"}";
		// Http Header 
		HttpHeaders	headers = new HttpHeaders();
		//Set Content Type
		headers.setContentType(MediaType.APPLICATION_JSON);
		//requestEntity : Body+Header
		HttpEntity<String> request = new HttpEntity<String> (body,headers);
		// 2. make HTTP call and store Response (URL,ResponseType)
	//	ResponseEntity<String> response =  restTemplate.postForEntity(url, request, String.class);
		ResponseEntity<String> response =  restTemplate.exchange(url, HttpMethod.POST,request, String.class);
		// 3. Print details(body,status..etc)
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}", response.getStatusCode().name());

	}

Output:

Output
Response Body : Invoice '9' created
Status code value : 201
Status code : OK

Get All Invoices

getAllInvoices()
private void getAllInvoices() {
		String url = "http://localhost:8080/invoice/rest/getAllInvoices";
	    ResponseEntity<Invoice[]> response = restTemplate.getForEntity(url,Invoice[].class);
	//	ResponseEntity<Invoice[]> response = restTemplate.exchange(url, HttpMethod.GET, null, Invoice[].class);
		Invoice[] invs = response.getBody();
		List<Invoice> list = Arrays.asList(invs);

		logger.info("Response Body : {}", list);
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}", response.getStatusCode().name());
		logger.info("Headers {} :", response.getHeaders());
	}

Output:

output
Response Body : [Invoice(id=1, name=Inv1, amount=135.0, finalAmount=148.5, number=Inv02345, receivedDate=14-10-2020, type=normal, vendor=Vend2, comments=Ok), Invoice(id=2, name=Inv1, amount=135.0, finalAmount=148.5, number=Inv0234, receivedDate=14-10-2020, type=normal, vendor=Vend2, comments=on Hold), Invoice(id=3, name=Inv1, amount=135.0, finalAmount=148.5, number=Inv0234, receivedDate=14-10-2020, type=normal, vendor=Vend2, comments=on Hold), Invoice(id=4, name=Inv11, amount=124.0, finalAmount=null, number=Inv023411, receivedDate=24-10-2020, type=urgent, vendor=Vend24, comments=on Hold), Invoice(id=5, name=INV11, amount=234.11, finalAmount=257.521, number=INVOICE11, receivedDate=28-10-2020, type=null, vendor=null, comments=null), Invoice(id=7, name=INV11, amount=888.0, finalAmount=976.8, number=INVOICE11, receivedDate=28-10-2020, type=null, vendor=null, comments=null), Invoice(id=8, name=INV11, amount=234.11, finalAmount=257.521, number=INVOICE11, receivedDate=28-10-2020, type=Normal, vendor=ADHR001, comments=On Hold), Invoice(id=9, name=INV11, amount=234.11, finalAmount=257.521, number=INVOICE11, receivedDate=28-10-2020, type=Normal, vendor=ADHR001, comments=On Hold)]
Status code value : 200
Status code : CREATED
Headers [Content-Type:"application/json", Transfer-Encoding:"chunked", Date:"Thu, 29 Oct 2020 15:39:09 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"] :

Get One Invoice

getOneInvoice()
private void getOneInvoice() {
		String url = "http://localhost:8080/invoice/rest/find/{id}";
	//	ResponseEntity<String> response= restTemplate.getForEntity(url, String.class, 9);
		ResponseEntity<String> response= restTemplate.exchange(url, HttpMethod.GET, null, String.class, 7);
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}",response.getStatusCode().name());
	}

Output:

output
Response Body : {"id":9,"name":"INV11","amount":234.11,"finalAmount":257.521,"number":"INVOICE11","receivedDate":"28-10-2020","type":"Normal","vendor":"ADHR001","comments":"On Hold"}
Status code value : 200
Status code : OK

Update Invoice

updateInvoice()
private void updateInvoice() {
		String url = "http://localhost:8080/invoice/rest/modify/{id}";
		String body = "{\"name\":\"INV13\",\"amount\":888}";
		// Request Header
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		// requestEntity = Body + header
		HttpEntity<String> requestEntity = new HttpEntity<String>(body, headers);
	//	restTemplate.put(url, requestEntity, 7);
		ResponseEntity<String> response= restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class, 7);
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}",response.getStatusCode().name());
		logger.info("Response Headers : {}", response.getHeaders());
	}

Output:

output
Response Body : null
Status code value : 205
Status code : RESET_CONTENT
Response Headers : [Content-Length:"0", Date:"Thu, 29 Oct 2020 15:43:27 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]

Delete Invoice

deleteInvoice()
private void deleteInvoice() {
		String url = "http://localhost:8080/invoice/rest/remove/{id}";
	//	restTemplate.delete(url, 6);
		ResponseEntity<String> response= restTemplate.exchange(url, HttpMethod.DELETE, null, String.class,5);
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}",response.getStatusCode().name());
		logger.info("Response Headers : {}", response.getHeaders());
	}

Output:

output
Response Body : Invoice '5' deleted
Status code value : 200
Status code : OK
Response Headers : [Content-Type:"text/plain;charset=UTF-8", Content-Length:"19", Date:"Thu, 29 Oct 2020 15:46:56 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]

Complete Code

We created one Spring Boot Starter Project named “SpringBootRestTemplate” with dependencies ‘Lombok’ and ‘Spring Web’. Still if you are new to SpringBoot & Lombok, visit internal links as SpringBoot & Lombok accordingly. Furthermore, in the main class(SpringBootRestTemplateApplication.java) we wrote code of RestTemplate object creation and utilized it via auto-wiring. Besides this modification, we created two new classes Invoice.java(Model class) and a Runner class RestTemplateRunner.java(class having all methods). From the run() method of RestTemplateRunner.java uncomment the respective method required to test accordingly. In the end, Project structure will look like below screenshot.

How to write REST Consumer API using Spring Boot : RestTemplate

SpringBootRestTemplateApplication.java
package com.dev.springboot.rest.template;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class SpringBootRestTemplateApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootRestTemplateApplication.class, args);
	}
	
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}
}
Invoice.java
package com.dev.springboot.rest.template.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Invoice {
	
	private Long id;
	private String name;
	private Double amount;
	private Double finalAmount;
	private String number;
	private String receivedDate;
	private String type;
	private String vendor;
	private String comments;
	
}
RestTemplateRunner.java
package com.dev.springboot.rest.template.runner;

import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.dev.springboot.rest.template.entity.Invoice;

@Component
public class RestTemplateRunner implements CommandLineRunner {

	private Logger logger = LoggerFactory.getLogger(RestTemplateRunner.class);
	
	@Autowired
	RestTemplate restTemplate;
	
	@Override
	public void run(String... args) throws Exception {
		saveInv();
//		getAllInvoices();
//		getOneInvoice();
//		updateInvoice();
//		deleteInvoice();
	}
	
	
	private void saveInv() {
		// 1. Producer application URL
		String url = "http://localhost:8080/invoice/rest/saveInvoice";
		// Send JSON data as Body
		String body = "{\"name\":\"INV11\", \"amount\":234.11,\"number\":\"INVOICE11\",\"receivedDate\":\"28-10-2020\",\"type\":\"Normal\",\"vendor\":\"ADHR001\",\"comments\" :\"On Hold\"}";
		// Http Header 
		HttpHeaders	headers = new HttpHeaders();
		//Set Content Type
		headers.setContentType(MediaType.APPLICATION_JSON);
		//requestEntity : Body+Header
		HttpEntity<String> request = new HttpEntity<String> (body,headers);
		// 2. make HTTP call and store Response (URL,ResponseType)
	//	ResponseEntity<String> response =  restTemplate.postForEntity(url, request, String.class);
		ResponseEntity<String> response =  restTemplate.exchange(url, HttpMethod.POST,request, String.class);
		// 3. Print details(body,status..etc)
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}", response.getStatusCode().name());

	}
	
	private void getAllInvoices() {
		String url = "http://localhost:8080/invoice/rest/getAllInvoices";
	    ResponseEntity<Invoice[]> response = restTemplate.getForEntity(url,Invoice[].class);
	//	ResponseEntity<Invoice[]> response = restTemplate.exchange(url, HttpMethod.GET, null, Invoice[].class);
		Invoice[] invs = response.getBody();
		List<Invoice> list = Arrays.asList(invs);

		logger.info("Response Body : {}", list);
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}", response.getStatusCode().name());
		logger.info("Headers {} :", response.getHeaders());
	}

	private void getOneInvoice() {
		String url = "http://localhost:8080/invoice/rest/find/{id}";
	//	ResponseEntity<String> response= restTemplate.getForEntity(url, String.class, 9);
		ResponseEntity<String> response= restTemplate.exchange(url, HttpMethod.GET, null, String.class, 7);
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}",response.getStatusCode().name());
	}
	
	private void updateInvoice() {
		String url = "http://localhost:8080/invoice/rest/modify/{id}";
		String body = "{\"name\":\"INV13\",\"amount\":888}";
		// Request Header
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		// requestEntity = Body + header
		HttpEntity<String> requestEntity = new HttpEntity<String>(body, headers);
	//	restTemplate.put(url, requestEntity, 7);
		ResponseEntity<String> response= restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class, 7);
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}",response.getStatusCode().name());
		logger.info("Response Headers : {}", response.getHeaders());
	}
	
	private void deleteInvoice() {
		String url = "http://localhost:8080/invoice/rest/remove/{id}";
	//	restTemplate.delete(url, 6);
		ResponseEntity<String> response= restTemplate.exchange(url, HttpMethod.DELETE, null, String.class,5);
		logger.info("Response Body : {}", response.getBody());
		logger.info("Status code value : {}", response.getStatusCodeValue());
		logger.info("Status code : {}",response.getStatusCode().name());
		logger.info("Response Headers : {}", response.getHeaders());
	}
	
}

How to test the application ?

To run the application for testing , right click on Project then select Run As >> Spring Boot App. Additionally, please uncomment the respective method called in run() of RestTemplateRunner.java to test the methods one by one. Further you can verify your output by comparing the output given in previous section.

How to convert ResponseEntity to Java object ?

Sometimes many developers face issue in converting ResponseEntity to Java Objects. Although this part is somewhat tricky. Further, in order to clarify this problem, here we will discuss three solutions to get it done.

Solution#1 : By using getForEntity() method and returning Array Of Objects

ResponseEntity<Invoice[]> response = restTemplate.getForEntity(url, Invoice[].class);

Invoice[] invs = response.getBody();
List<Invoice> list = Arrays.asList(invs);
System.out.println("Response Body : " +list);

Solution#2 : By using exchange() method and returning List Of Objects

ResponseEntity<List<Invoice>> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<Invoice>>() {});

List<Invoice> list = response.getBody();
System.out.println("Response Body : " +list);

Solution#3 : By using exchange() method and returning Array Of Objects

ResponseEntity<Invoice[]> response = restTemplate.exchange(url, HttpMethod.GET, null, Invoice[].class);

Invoice[] invs = response.getBody();
List<Invoice> list = Arrays.asList(invs);
System.out.println("Response Body : " +list);

Moreover, we can use any solution to get it done based on our requirement and scenario. Furthermore, in order to get complete code implementation, visit getAllInvoices() method of this article.

Summary

Almost every REST application will have these operations we learnt in this article. In other words, no REST API can be developed without these operations. So, you have learnt the mandatory concepts of ‘How to write REST Consumer API using Spring Boot? : RestTemplate’. In addition, for further learning on RestTemplate, kindly visit official site. Also in upcoming articles we will be learning other types of REST Clients.

close

Leave a Reply

Top