In this Spring Boot RESTful Web Services Example, we will learn how to perform CRUD Operations (Create, Read, Update, Delete) using Spring RESTful Web Services with the support of Spring Data JPA. Our application will be deployed in the embedded Tomcat Server of Spring Boot. We will return the data in the form of both JSON and XML.In REST, manipulation of the resources is performed based on the common set of HTTP verbs.
- POST – To Create a resource
- GET – To Retrieve a resource
- PUT – To Update a resource
- DELETE – To Delete a resource
Based on the above HTTP verbs, our REST API does the below
- Create Student (POST) : Create a new Student (/student)
- Get Student By Id (GET) : Get a Student based on id (/student/1)
- List of All Students (GET) : Get all the students (/students)
- Update Student (PUT) : Update a Student (/student)
- Delete Student (DELETE) : Delete a Student (/student/1)
Creating table
Create STUDENT Table, simply Copy and Paste the following SQL query in the query editor to get the table created.
CREATE TABLE "STUDENT" ( "ID" NUMBER(10,0) NOT NULL ENABLE, "NAME" VARCHAR2(255 CHAR), "AGE" NUMBER(10,0) NOT NULL ENABLE, PRIMARY KEY ("ID") ); insert into "STUDENT" values (1,'JIP1',11); insert into "STUDENT" values (2,'JIP2',22); insert into "STUDENT" values (3,'JIP3',33); insert into "STUDENT" values (4,'JIP4',44);
Folder Structure:
- Create a Maven Webapp project (maven-archetype-webapp) “SpringBootRest” and create a package for our source files “com.javainterviewpoint” under src/main/java
- Now add the following dependency in the POM.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javainterviewpoint</groupId> <artifactId>SpringBootRest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>SpringBootRest</name> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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-jpa</artifactId> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc14</artifactId> <version>11.2.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> </project>
- Create the Java classes App.java, Student.java, StudentRepository.java and StudentController.java under com.javainterviewpoint folder.
The spring-boot-starter-parent is a special starter, it provides useful Maven defaults. Since we are developing a web application, we also need to add spring-boot-starter-web dependency.This will add dependencies such Tomcat, Jackson, Spring boot etc which are required for our application.
Spring Boot RESTful Web Services Example
application.properties
Place the application.properties file under the src/resources folder
#Oracle Connection settings spring.datasource.url=jdbc:oracle:thin:@rsh2:40051:mydb spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver #JPA properties spring.jpa.show-sql = true spring.jpa.hibernate.ddl-auto = update
StundentRepository.java
package com.javainterviewpoint; import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource public interface StudentRepository extends CrudRepository<Student, Long> { }
Spring Data REST will create an implementation of StudentRepository automatically during runtime.
@RepositoryRestResource annotation will direct Spring to create RESTful endpoints and also creates a HATEOAS service with Spring JPA
StudentController.java
package com.javainterviewpoint; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class StudentController { @Autowired StudentRepository studentRepository; //Create @RequestMapping(value = "/student", method = RequestMethod.POST) public Student createStudent(@RequestBody Student student) { return studentRepository.save(student); } //Read @RequestMapping(value="/student/{id}", method = RequestMethod.GET) public Student getStudentById(@PathVariable long id) { return studentRepository.findOne(id); } @RequestMapping(value="/students", method = RequestMethod.GET) public List getAllStudents() { return (List)studentRepository.findAll(); } //Update @RequestMapping(value = "/student", method = RequestMethod.PUT) public Student updateStudent(@RequestBody Student student) { return studentRepository.save(student); } //Delete @RequestMapping(value = "/student/{id}", method = RequestMethod.DELETE) public void deleteStudent(@PathVariable long id) { studentRepository.delete(id); } }
- We have annotated our “StudentController” class with @RestController, In Spring 4 @RestController annotation is introduced it is a combination of @Controller + @ResponseBody. So when using @RestController, you do not need to use @ResponseBody it is optional now
- @RequestBody: This annotation tells Spring to bind the incoming HTTP request body( object passed in the request). HTTP Message converters convert the HTTP request body into domain object based on Accept header present in the request.
- @PathVariable: This annotation will bind method argument to the URI template variable.
Since Jackson 2 is on the classpath, Spring uses MappingJackson2HttpMessageConverter automatically to convert the Student instance to JSON. In order to get XML instead of JSON we need to add a separate dependency “jackson-dataformat-xml”
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
App.java
package com.javainterviewpoint; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
The App class main() method is the triggering point of our application, it in-turn calls Spring Boot’s SpringApplication class run() method which bootstrap our App application and starts the tomcat server. We need to pass our App.class as an argument to our run() method.
Student.java
package com.javainterviewpoint; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Student { @Id @Column(name="ID") private long id; @Column(name="NAME") private String name; @Column(name="AGE") private long age; public Student() { super(); } public Student(long id, String name, long age) { super(); this.id = id; this.name = name; this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getAge() { return age; } public void setAge(long age) { this.age = age; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
Our Student class is a simple POJO consisting getters and setters of Student properties id, name, age.
Output :
Create a Student
In POSTMAN, select POST method, select the type as “application/json” and give the url as “http://localhost:8080/student”. Add the JSON object which we are going to pass in the Body
{
“id”:5,
“name”:”JIP5″,
“age”:55
}
POSTMAN will automatically add a header Content-Type as “application/json”, Now click on Send
You will get the Status as 200, which confirms that the Student has been created.
Retrieve a single student
In POSTMAN, select GET method, and give the url as “http://localhost:8080/student/3”.
Retrieve all students
select GET method, and give the url as “http://localhost:8080/students”
Update Student
select PUT method, select the type as “application/json” and give the url as “http://localhost:8080/student”. Add the JSON object which we are going to pass in the Body
{
“id”:4,
“name”:”JIP44444444″,
“age”:444
}
Delete Student
select DELETE method, and give the url as “http://localhost:8080/student/3”
Spring RestTemplate
Spring RestTemplate communicates with the HTTP server using REST principals. It uses HTTP verbs such as GET, POST, HEAD, PUT, DELETE etc. RestTemplate provides different methods to communicate that will accept URI template, URI variables, response type and request object as arguments. Below are some of the common methods of RestTemplate
DELETE | delete(java.lang.String, java.lang.Object…) |
GET | getForObject(java.lang.String, java.lang.Class, java.lang.Object…) |
getForEntity(java.lang.String, java.lang.Class, java.lang.Object…) | |
HEAD | headForHeaders(java.lang.String, java.lang.Object…) |
OPTIONS | optionsForAllow(java.lang.String, java.lang.Object…) |
POST | postForLocation(java.lang.String, java.lang.Object, java.lang.Object…) |
postForObject(java.lang.String, java.lang.Object, java.lang.Class, java.lang.Object…) | |
PUT | put(java.lang.String, java.lang.Object, java.lang.Object…) |
package com.javainterviewpoint; import java.util.List; import java.util.Map; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.client.RestTemplate; import com.javainterviewpoint.Student; public class SpringRestTemplateClient { public static final String REST_BASE_URI = "http://localhost:8080"; static RestTemplate restTemplate = new RestTemplate(); /**POST**/ public static void createStudent() { Student student = new Student(); student.setId(5); student.setName("JIP"); student.setAge(5); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); //headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity entity = new HttpEntity<>(student,headers); restTemplate.postForObject(REST_BASE_URI+"/student", entity,Student.class); } /**GET**/ private static void getStudent(int id) { Student student = restTemplate.getForObject(REST_BASE_URI+"/student/"+id, Student.class); System.out.println("**** Student with id : "+id+"****"); System.out.println("Id :"+student.getId()+" Name : "+student.getName()+" Age : "+student.getAge()); } public static void getAllStudents() { List<Map<String, Object>> studentList = restTemplate.getForObject(REST_BASE_URI + "/students", List.class); if (studentList != null) { System.out.println("**** All Students ****"); for (Map<String, Object> map : studentList) { System.out.println("Id : id=" + map.get("id") + " Name=" + map.get("name") + " Age=" + map.get("age")); } } else { System.out.println("No Students exist!!"); } } /**PUT**/ public static void updateStudent() { Student student = new Student(); student.setId(3); student.setName("JIP33333"); student.setAge(333); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(student,headers); restTemplate.put(REST_BASE_URI + "/student", entity,Student.class); } /**DELETE**/ public static void deleteStudent(int id) { restTemplate.delete(REST_BASE_URI + "/student/"+id); } public static void main(String args[]) { createStudent(); getAllStudents(); getStudent(2); updateStudent(); deleteStudent(4); } }
Output:
11:46:42.479 [main] DEBUG org.springframework.web.client.RestTemplate - Created POST request for "http://localhost:8080/student" 11:46:42.534 [main] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json] 11:46:42.551 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [Student [id=5, name=JIP, age=5]] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@123a213] 11:46:44.014 [main] DEBUG org.springframework.web.client.RestTemplate - POST request for "http://localhost:8080/student" resulted in 200 (null) 11:46:44.016 [main] DEBUG org.springframework.web.client.RestTemplate - Reading [class com.javainterviewpoint.Student] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@123a213] 11:46:44.042 [main] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8080/students" 11:46:44.050 [main] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json] 11:46:44.764 [main] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://localhost:8080/students" resulted in 200 (null) 11:46:44.764 [main] DEBUG org.springframework.web.client.RestTemplate - Reading [interface java.util.List] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@123a213] **** All Students **** Id : id=1 Name=JIP1 Age=11 Id : id=2 Name=JIP2 Age=22 Id : id=3 Name=JIP33333 Age=333 Id : id=4 Name=JIP44444444 Age=444 Id : id=5 Name=JIP Age=5 11:46:44.775 [main] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8080/student/2" 11:46:44.775 [main] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json] 11:46:45.491 [main] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://localhost:8080/student/2" resulted in 200 (null) 11:46:45.492 [main] DEBUG org.springframework.web.client.RestTemplate - Reading [class com.javainterviewpoint.Student] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@123a213] **** Student with id : 2**** Id :2 Name : JIP2 Age : 22 11:46:45.493 [main] DEBUG org.springframework.web.client.RestTemplate - Created PUT request for "http://localhost:8080/student" 11:46:45.493 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [Student [id=3, name=JIP33333, age=333]] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@123a213] 11:46:46.209 [main] DEBUG org.springframework.web.client.RestTemplate - PUT request for "http://localhost:8080/student" resulted in 200 (null) 11:46:46.209 [main] DEBUG org.springframework.web.client.RestTemplate - Created DELETE request for "http://localhost:8080/student/4" 11:46:47.622 [main] DEBUG org.springframework.web.client.RestTemplate - DELETE request for "http://localhost:8080/student/4" resulted in 200 (null)
Leave a Reply