Spring Boot + Jersey + Spring Data JPA Build REST CRUD APIs Example
Hello everyone, today we will learn how to develop CRUD REST APIs using the integration of Jersey with Spring boot, JPA/Hibernate, and H2DB as a database.
The spring-boot-starter-jersey is a starter for building RESTful web applications using JAX-RS and Jersey. It is an alternative to spring-boot-starter-web.
Jersey RESTful Web Services framework is an open source, production quality, framework for developing RESTful Web Services in Java. It provides support for JAX-RS APIs and serves as a JAX-RS Reference Implementation.
What we’ll build?
We are developing CRUD REST APIs using the integration of Jersey with Spring boot, JPA/Hibernate, and H2DB as a database.
- /api/v1/employees - GET
- /api/v1/employees - POST
- /api/v1/employees/{id} - PUT
- /api/v1/employees/{id} - DELETE
- /api/v1/employees/{id} - GET
Application Directory Structure
Maven[pom.xml]
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project.
<?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.7.0</version>
<relativePath />
</parent>
<groupId>com.knf.demo</groupId>
<artifactId>springboot-jersey-hibernate-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-jersey-hibernate-crud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create Employee Entity
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Column(name = "email_address", nullable = false)
private String emailId;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
}
- @Entity annotation defines that a class can be mapped to a table. And that is it, it is just a marker, like for example Serializable interface.
- @Table annotation allows you to specify the details of the table that will be used to persist the entity in the database.
- In JPA the object id is defined through the @Id annotation and should correspond to the primary key of the object's table.
- @Column Specifies the mapped column for a persistent property or field. If no Column annotation is specified, then the filed names will be used for mapping.
Create Employee Repository
public interface EmployeeRepository
extends CrudRepository<Employee, Long> {
}
CrudRepository is a Spring Data interface for generic CRUD operations on a repository of a specific type. It provides several methods out of the box for interacting with a database.
Create Employee Controller
@Component
@Path("/api/v1")
public class EmployeeController {
@Autowired
private EmployeeRepository employeeRepository;
@GET
@Produces("application/json")
@Path("/employees")
public List<Employee> getAllEmployees() {
return (List<Employee>) employeeRepository.findAll();
}
@GET
@Produces("application/json")
@Consumes("application/json")
@Path("/employees/{id}")
public ResponseEntity<Employee> getEmployeeById
(@PathParam(value = "id") Long employeeId) {
Employee employee = employeeRepository
.findById(employeeId).orElseThrow();
return ResponseEntity.ok().body(employee);
}
@POST
@Produces("application/json")
@Consumes("application/json")
@Path("/employees")
public Employee createEmployee(Employee employee) {
return employeeRepository.save(employee);
}
@PUT
@Produces("application/json")
@Consumes("application/json")
@Path("/employees/{id}")
public ResponseEntity<Employee> updateEmployee
(@PathParam(value = "id") Long employeeId,
@RequestBody Employee employeeDetails) {
Employee employee = employeeRepository
.findById(employeeId).orElseThrow();
employee.setEmailId(employeeDetails.getEmailId());
employee.setLastName(employeeDetails.getLastName());
employee.setFirstName(employeeDetails.getFirstName());
return ResponseEntity
.ok(employeeRepository.save(employee));
}
@DELETE
@Produces("application/json")
@Consumes("application/json")
@Path("/employees/{id}")
public Map<String, Boolean> deleteEmployee
(@PathParam(value = "id") Long employeeId) {
Employee employee = employeeRepository
.findById(employeeId).orElseThrow();
employeeRepository.delete(employee);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return response;
}
}
- If any class is annotated with @Component it will be automatically detected by using a classpath scan.
- The @Path annotation is used to specify the URI through which a resource and an API can be accessed.
- The @Autowired annotation can be used to autowire bean on the setter method, constructor, a property or methods with arbitrary names and/or multiple arguments.
- @GET specifies the method that responds to a GET request.
- @POST specifies the method that responds to POST requests.
- @PUT specifies the method that responds to a PUT request.
- @DELETE specifies the method that responds to the DELETE request.
- @Produces defines media types for the response such as XML, PLAIN, JSON etc. It defines the media type that the methods of a resource class or MessageBodyWriter can produce.
- @Consumes defines the media type that the methods of a resource class or MessageBodyReader can produce.
Jersey Configuration
@Component
public class JerseyConfiguration extends ResourceConfig {
public JerseyConfiguration() {
register(EmployeeController.class);
}
}
Spring Boot Main Driver
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Spring Boot @SpringBootApplication annotation is used to mark a configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning.
It's the same as declaring a class with @Configuration, @EnableAutoConfiguration and @ComponentScan annotations.
Local environment setup
>> Download the source code - click here
>> Execute the command - mvn clean install
>> Run the app as a Java application or execute mvn spring-boot:run