Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Thursday, July 28, 2022

How To Use JDBCTemplate In Spring Boot With Swagger OpenAPI

JAVA,REST API,JDBCTemplate,Swagger,Open API,Spring Boot,programming,software development,technology
In this tutorial, we'll go over how to query or save data to already-existing database tables using JdbcTemplate and then expose those operations using REST APIs.

Using JdbcTemplate, we can run queries and stored procedures from our JAVA code and gain low-level database access.

👉 We'll be working with a sample MySQL database. Here are a couple of sample MySQL databases. I used the classicmodels sample database. This website contains the database and installation instructions. This database contains several tables, but for the purposes of this tutorial, we will only use the Customers table.

Create a Spring Boot Project

We created a new Spring Boot project with Spring Initializr, which will generate the basic structure of our Spring Boot project. The pom.xml file for this project is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.9</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.raven</groupId>
	<artifactId>spring-boot-jdbctemplate</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<name>spring-boot-jdbctemplate</name>
	<description>Spring Boot project with JDBCTemplate</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui -->
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-ui</artifactId>
			<version>1.6.9</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
We have added the following dependencies:
  • Spring Boot DevTools - necessary development tools  
  • Rest Repositories - to expose Spring Data repositories over REST. 
  • JDBC API - Database Connectivity API that defines how a client may connect and query a database.
  • MySQL Driver - JDBC driver for MySQL (for other DB you have to choose that dependency for that DB)
  • Springdoc OpenAPI - for Swagger UI.

Connect to the Database

In the application.properties file, we mentioned the MySQL database configurations and some Swagger OpenAPI-related configurations:
application-description=@project.description@
application-version=@project.version@
logging.level.org.springframework.boot.autoconfigure=ERROR

api.response-codes.ok.desc=OK
api.response-codes.badRequest.desc=BAD_REQUEST
api.response-codes.notFound.desc=NOT_FOUND

## first db
spring.datasource.jdbcUrl=jdbc:mysql://172.17.0.2:3306/classicmodels?useSSL=false
spring.datasource.username=root
spring.datasource.password=admin@123

JdbcTemplate Configuration

In the config package, we created a class called ApplicationConfiguration to configure the JdbcTemplate:
package com.raven.jdbctemplate.config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;

@Configuration
public class ApplicationConfiguration {
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate jdbcTemplate1(@Qualifier("dataSource") DataSource ds) {
        return new JdbcTemplate(ds);
    }
}
The annotation @Configuration indicates that this class contains one or more beans that can be used throughout the project.

We declared two beans using the @Bean annotation: dataSource and jdbcTemplate. The spring context will manage these beans, and we will not need to create a new instance each time we use them.

The @ConfigurationProperties annotation is used to construct the datasource by reading the application.properties file's spring.datasource property values.

We use the @Qualifier annotation to specify the datasource bean as our DataSource when creating a new instance of JdbcTemplate.

Customer Model

To begin, we create a CustomerModel class in the controller package to hold the data from the customer table. Here's our CustomerModel class from the model package:
package com.raven.jdbctemplate.model;

public class CustomerModel {
	private int customerNumber = 0;
	private String customerName = "";
	private String phone = "";
	private String address1 = "";
	private String city = "";
	private String country = "";

	public CustomerModel() {
		super();
	}

	public CustomerModel(int customerNumber, String customerName, String phone, String address1, String city, String country) {
		super();
		this.customerNumber = customerNumber;
		this.customerName = customerName;
		this.phone = phone;
		this.address1 = address1;
		this.city = city;
		this.country = country;
	}

	public int getCustomerNumber() {
		return customerNumber;
	}

	public void setCustomerNumber(int customerNumber) {
		this.customerNumber = customerNumber;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getAddress1() {
		return address1;
	}

	public void setAddress1(String address1) {
		this.address1 = address1;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	@Override
	public String toString() {
		return "CustomerModel [customerNumber=" + customerNumber + ", customerName=" + customerName + ", phone=" + phone
				+ ", address1=" + address1 + ", city=" + city + ", country=" + country + "]";
	}
}
We use some columns to map in CustomerModel, but you are free to map other columns from the Customer table.

Repository

Make a repository package and add the CustomerRepository interface to it. The CustomerRepository interface defines a collection of abstract methods for performing database CRUD operations:
package com.raven.jdbctemplate.repository;

import java.util.List;
import java.util.Optional;
import com.raven.jdbctemplate.model.CustomerModel;

public interface CustomerRepository {
    // gets the total record count
    int count();

    // saves a customer
    int saveCustomer(CustomerModel customerModel);

    // updates an existing customer
    int updateCustomer(CustomerModel customerModel, int id);

    // deletes ann existing customer
    int deleteCustomer(int id);

    // get all customer
    List<CustomerModel> findAll();

    // get a customer by CustomerNumber
    Optional<CustomerModel> findByCustomerNumber(int id);
}

Repository Implementation

We now add the CustomerJDBCRepository class to the repository package. This class will implement the CustomerRepository interface and will have complete control over all CRUD operations:
package com.raven.jdbctemplate.repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
import com.raven.jdbctemplate.model.CustomerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

@Repository
public class CustomerJDBCRepository implements CustomerRepository {

    @Qualifier("jdbcTemplate")
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int count() {
        return jdbcTemplate
                .queryForObject("select count(*) from customers", Integer.class);
    }

    @Override
    public int saveCustomer(CustomerModel customerModel) {
        String sql = "INSERT INTO customers(customerName, contactLastName, contactFirstName, phone, addressLine1, city, country) " +
                "VALUES(?,?,?,?,?,?,?)";
        return jdbcTemplate.update(sql, customerModel.getCustomerName(),
                customerModel.getCustomerName().split(" ")[1],
                customerModel.getCustomerName().split(" ")[0],
                customerModel.getPhone(),
                customerModel.getAddress1(),
                customerModel.getCity(),
                customerModel.getCountry());
    }

    @Override
    public int updateCustomer(CustomerModel customerModel, int id) {
        String sql = "UPDATE customers " +
                "SET customerName= ?, contactLastName= ?, contactFirstName= ?, phone=?, addressLine1=?, " +
                "city= ?, country= ? WHERE customerNumber= ?;";
        return jdbcTemplate.update(sql, customerModel.getCustomerName(),
                customerModel.getCustomerName().split(" ")[1],
                customerModel.getCustomerName().split(" ")[0],
                customerModel.getPhone(),
                customerModel.getAddress1(),
                customerModel.getCity(),
                customerModel.getCountry(),
                id);
    }

    @Override
    public int deleteCustomer(int id) {
        String sql = "DELETE FROM customers WHERE customerNumber = ?";
        return jdbcTemplate.update(sql, id);
    }

    @Override
    public List<CustomerModel> findAll() {
        String sql = "select customerNumber, customerName, phone, addressLine1, city, country from customers";
        return jdbcTemplate.query(sql, new CustomerRowMapper());
    }

    @Override
    public Optional<CustomerModel> findByCustomerNumber(int id) {
        String sql = "select customerNumber, customerName, phone, addressLine1, city, country from customers where customerNumber = ?";
        return jdbcTemplate.query(sql, new CustomerRowMapper(), id).stream().findFirst();
    }

    private class CustomerRowMapper implements RowMapper<CustomerModel> {

        @Override
        public CustomerModel mapRow(ResultSet rs, int rowNum) throws SQLException {
            return new CustomerModel(rs.getInt("customerNumber"),
                    rs.getString("customerName"),
                    rs.getString("phone"),
                    rs.getString("addressLine1"),
                    rs.getString("city"),
                    rs.getString("country"));
        }
    }
}
CustomerRowMapper, an inner class that implements the RowMapper interface, has been declared. Because RowMapper has a method for mapping rows to objects, we override the mapRow() method, which maps rows from the ResultSet to CustomerModel. CustomerRowMapper is a database retrieval tool that can return a single or a list of customer records.
 
Use jdbcTemplate.queryForObject() to retrieve a single row or value. We are only concerned with the count(*) value in this case. 

To retrieve the data, we used the query() method of JdbcTemplate, which will retrieve the records from the database based on the SQL query and map the records to CustomerModel objects using CustomerRowMapper.

The update() method of JdbcTemplate is used to perform insert, update, and delete operations, and it accepts a string containing your SQL query and values as arguments.

Controller

Make a controller package that contains the CustomerController class:
package com.raven.jdbctemplate.controller;

import com.raven.jdbctemplate.model.CustomerModel;
import com.raven.jdbctemplate.repository.CustomerJDBCRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Optional;

@CrossOrigin(origins = "*", allowedHeaders = "*", maxAge = 4800, allowCredentials = "false", methods = {
		RequestMethod.POST, RequestMethod.GET, RequestMethod.PUT, RequestMethod.DELETE })

@RestController
@RequestMapping("/api/customer")
@Tag(description = "APIs related with Customers", name = "Customer")
public class CustomerController {

	private CustomerJDBCRepository customerJDBCRepository;

	@Autowired
	public CustomerController(CustomerJDBCRepository customerJDBCRepository) {
		this.customerJDBCRepository = customerJDBCRepository;
	}

	@Operation(summary = "Total record count", description = "Get total Customer count")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "${api.response-codes.ok.desc}", content = {
					@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = CustomerModel.class))) }),
			@ApiResponse(responseCode = "400", description = "${api.response-codes.badRequest.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }),
			@ApiResponse(responseCode = "404", description = "${api.response-codes.notFound.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }) })
	@RequestMapping(value = "/getRecordNumber", method = RequestMethod.GET)
	@ResponseBody
	public int getRecordNumber() {
		return customerJDBCRepository.count();
	}

	@Operation(summary = "All customer", description = "Get all customer details")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "${api.response-codes.ok.desc}", content = {
					@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = CustomerModel.class))) }),
			@ApiResponse(responseCode = "400", description = "${api.response-codes.badRequest.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }),
			@ApiResponse(responseCode = "404", description = "${api.response-codes.notFound.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }) })
	@RequestMapping(value = "/getAllCustomer", method = RequestMethod.GET)
	@ResponseBody
	public List<CustomerModel> getAllCustomer() {
		return customerJDBCRepository.findAll();
	}

	@Operation(summary = "Customer details by customer number", description = "Customer details by customer number")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "${api.response-codes.ok.desc}", content = {
					@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = CustomerModel.class))) }),
			@ApiResponse(responseCode = "400", description = "${api.response-codes.badRequest.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }),
			@ApiResponse(responseCode = "404", description = "${api.response-codes.notFound.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }) })
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Optional<CustomerModel> getCustomerByNumber(@PathVariable("id") int id) {
		return customerJDBCRepository.findByCustomerNumber(id);
	}

	@Operation(summary = "Save customer details", description = "Save customer details")
	@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "${api.response-codes.ok.desc}"),
			@ApiResponse(responseCode = "400", description = "${api.response-codes.badRequest.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }),
			@ApiResponse(responseCode = "404", description = "${api.response-codes.notFound.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }) })
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	@ResponseBody
	public int save(@Valid @RequestBody CustomerModel customerModel) {
		return customerJDBCRepository.saveCustomer(customerModel);
	}

	@Operation(summary = "Update customer details", description = "Update customer details using customer number")
	@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "${api.response-codes.ok.desc}"),
			@ApiResponse(responseCode = "400", description = "${api.response-codes.badRequest.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }),
			@ApiResponse(responseCode = "404", description = "${api.response-codes.notFound.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }) })
	@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
	@ResponseBody
	public int update(@Valid @RequestBody CustomerModel customerModel, @PathVariable("id") int id) {
		return customerJDBCRepository.updateCustomer(customerModel, id);
	}

	@Operation(summary = "Delete a customer", description = "Delete a customer using customer number")
	@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "${api.response-codes.ok.desc}"),
			@ApiResponse(responseCode = "400", description = "${api.response-codes.badRequest.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }),
			@ApiResponse(responseCode = "404", description = "${api.response-codes.notFound.desc}", content = {
					@Content(examples = { @ExampleObject(value = "") }) }) })
	@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
	@ResponseBody
	public int delete(@PathVariable("id") int id) {
		return customerJDBCRepository.deleteCustomer(id);
	}
}
The @RestController annotation is added to the controller class, informing Spring Boot that this is a REST-based service and that the request/response data will be serialized or deserialized to JSON automatically. 

The request base path was specified in @RequestMapping as /api/customer. The @RequestMapping annotation informs the Spring container that the specified HTTP endpoint is available for this service.

@Tag is an Open API annotation that allows you to change resource details like the resource name and description.
 
Another Open API annotation is @Operation, which is used to customize the API's name and description.

@ApiResponses is another Open API annotation that specifies the API response format, such as success and error response formats.


👉 Run the application now. The Swagger UI is accessible at http://localhost:8080/swagger-ui/index.html, where we can see a list of APIs:
JAVA,REST API,JDBCTemplate,Swagger,Open API,Spring Boot,Spring,


You can download the source code.
Happy coding!!! 😊
in

References


Tuesday, June 08, 2021

How to consume RESTful service (REST API) in Spring Boot.

springboot,java,autowired,requestmapping,restcontroller,programming,software development,technology
Spring Boot is used to create RESTful APIs. At the same time, we can use RestTemplate to consume RESTful services, such as payment services or weather services, in Spring Boot.

Public REST API

We will use a public RESTful service in this tutorial. Numerous websites offer public RESTful services. https://reqres.in/ has some useful RESTful services. It includes the GET, POST, PUT, PATCH, and DELETE rest APIs.

We use a RESTful service, which is accessible at https://reqres.in/api/users?page=1. I used a web browser to call this service, and it returned a list of dummy user details in JSON format, as shown below:
{ 
  "page":1, 
  "per_page":6, 
  "total":12, 
  "total_pages":2,
  "data":[
  	{"id":1,"email":"george.bluth@reqres.in","first_name":"George",
    	"last_name":"Bluth","avatar":"https://reqres.in/img/faces/1-image.jpg"},
  	{"id":2,"email":"janet.weaver@reqres.in","first_name":"Janet",
    	"last_name":"Weaver","avatar":"https://reqres.in/img/faces/2-image.jpg"},
  	{"id":3,"email":"emma.wong@reqres.in","first_name":"Emma",
    	"last_name":"Wong","avatar":"https://reqres.in/img/faces/3-image.jpg"},
  	{"id":4,"email":"eve.holt@reqres.in","first_name":"Eve",
    	"last_name":"Holt","avatar":"https://reqres.in/img/faces/4-image.jpg"},
  	{"id":5,"email":"charles.morris@reqres.in","first_name":"Charles",
    	"last_name":"Morris","avatar":"https://reqres.in/img/faces/5-image.jpg"},
  	{"id":6,"email":"tracey.ramos@reqres.in","first_name":"Tracey",
    	"last_name":"Ramos","avatar":"https://reqres.in/img/faces/6-image.jpg"}
  ], 
  "support": { 
  	"url":"https://reqres.in/#support-heading", 
  	"text":"To keep ReqRes free, contributions towards server costs are appreciated!" 
  	} 
}

Use of RestTemplate

RestTemplate is a very useful class provided by Spring. We can communicate with RESTful services by using RestTemplate.

You must first create a Spring Boot application. Spring Initializr can be used to create a Spring Boot application, and your project must include the Spring Web dependency. Simply download the zip file, unzip it in your desired location, and import the project into your preferred IDE.

If you look closely at the JSON document, you'll notice that it requires three classes to hold the data - a main class and two sub-classes to support the main class. The main class is responsible for capturing the entire JSON document data, and there are two sub-classes for data (actually user details) and support.

So, for the Data class, write the following code:
package com.example.springresttemplate;

public class DataClass {                
	private int id;
	private String email;
	private String first_name;
	private String last_name;
	private String avatar;

	public int getId() { return id;}
	public void setId(int id) { this.id = id; }

	public String getEmail() { return email; }
	public void setEmail(String email) { this.email = email; }

	public String getFirst_name() { return first_name; }
	public void setFirst_name(String first_name) { this.first_name = first_name; }

	public String getLast_name() { return last_name; }
	public void setLast_name(String last_name) { this.last_name = last_name; }

	public String getAvatar() { return avatar; }
	public void setAvatar(String avatar) { this.avatar = avatar; }

	@Override
	public String toString() { 
	  return "DataClass [id=" + id + ", email=" + email + ", first_name=" +
		 first_name + ", last_name=" + last_name + ", avatar=" + avatar + "]"; 
	}
}

Now, for the Support class, write the following code:
package com.example.springresttemplate;

public class SupportClass {
	private String url;
	private String text;

	public String getUrl() { return url; }
	public void setUrl(String url) { this.url = url; }
	public String getText() { return text; }
	public void setText(String text) { this.text = text; }

	@Override
	public String toString() { return "SupportClass [url=" + url + ", text=" + text + "]"; }
}

Finally, here is a listing for the Main class:
package com.example.springresttemplate;
import java.util.Arrays;
            
public class MainClass {
	private int page;
	private int per_page;
	private int total;
	private int total_pages;
	private DataClass[] data;
	private SupportClass support;

	public int getPage() { return page; }
	public void setPage(int page) { this.page = page; }

	public int getPer_page() { return per_page; }
	public void setPer_page(int per_page) { this.per_page = per_page; }

	public int getTotal() { return total; }
	public void setTotal(int total) { this.total = total; }

	public int getTotal_pages() { return total_pages; }
	public void setTotal_pages(int total_pages) { this.total_pages = total_pages; }

	public DataClass[] getData() { return data; }
	public void setData(DataClass[] data) { this.data = data; }

	public SupportClass getSupport() { return support; }
	public void setSupport(SupportClass support) { this.support = support; }

	@Override
	public String toString() {
	  return "MainClass [page=" + page + ", per_page=" + per_page + ", total=" +
		total + ", total_pages=" + total_pages + ", data=" + Arrays.toString(data) +
		  ", support=" + support + "]";
	}
}

Now, in the controller class RestFulController, we create a web request method, as shown in the code below:
package com.example.springresttemplate;
// imports are removed
            
@RestController
@RequestMapping("/restful")
public class RestFulController {    
	private static final Logger LOGGER = Logger.getLogger(RestFulController.class);

	@Autowired
	RestTemplate restTemplate;

	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public void getUsers(HttpServletRequest request) {
		MainClass mainClass = this.restTemplate.getForObject("https://reqres.in/api/users?page=1", 
								MainClass.class);
		LOGGER.info("Response -> " + mainClass.toString());
	}
}

We've used RestTemplate to create a simple GET web request method for interacting with a RESTful service. We called a RESTful service using the getForObject() method, which retrieves the data and stores it in MainClass before logging the result to the console.

Now, open any browser and navigate to this URL: http://localhost:8080/restful/users, then return to your IDE and open the console. The end result is shown below:
2021-06-08 09:56:03 INFO RestFulController:24 - Response -> MainClass
[
	page=1, per_page=6, total=12, total_pages=2, 
	data=[DataClass [id=1,email=george.bluth@reqres.in, first_name=George, last_name=Bluth, 
		avatar=https://reqres.in/img/faces/1-image.jpg], 
	DataClass [id=2, email=janet.weaver@reqres.in, first_name=Janet, last_name=Weaver, 
		avatar=https://reqres.in/img/faces/2-image.jpg], 
	DataClass [id=3, email=emma.wong@reqres.in, first_name=Emma, last_name=Wong, 
		avatar=https://reqres.in/img/faces/3-image.jpg], 
	DataClass [id=4, email=eve.holt@reqres.in, first_name=Eve, last_name=Holt, 
		avatar=https://reqres.in/img/faces/4-image.jpg], 
	DataClass [id=5, email=charles.morris@reqres.in, first_name=Charles, last_name=Morris, 
		avatar=https://reqres.in/img/faces/5-image.jpg], 
	DataClass [id=6, email=tracey.ramos@reqres.in, first_name=Tracey, last_name=Ramos, 
		avatar=https://reqres.in/img/faces/6-image.jpg]], 
	support=SupportClass[url=https://reqres.in/#support-heading, 
	text=To keep ReqRes free, contributions towards server costs are appreciated!]
]

In this manner, we can use RestTemplate in Spring to call RESTful services.
I'll write a tutorial on how to POST/PUT/DELETE RESTful services using RestTemplate later.
in

Popular posts