Learn, Build, Deploy

Building a RESTful CRUD API using Spring Boot

Table of Contents

Getting Set Up and Creating an Entity Object

Welcome to this series of guides to help you get build a RESTful CRUD API using Java Spring Boot. After this series, we will then write some tests, integrate this with a CICD pipeline, and even deploy your service to AWS! ๐Ÿ˜ฎ

You will be introduced to libraries such as spring-boot-starter-web, Lombok, Java Persistence API (JPA), as well as the H2 in-memory database to get you up and running as quickly as possible.

What are we building and how can we interact with it?

We are going to build a Reservation Management Service (RMS) which will have the following functionality:

Action

HTTP Verb

Endpoint

Create new reservation

POST

/api/v1/reservation

Read the reservation

GET

/api/v1/reservation/{reservationId}

Update the reservation

PUT

/api/v1/reservation/{reservationId}

Delete the reservation

DELETE

/api/v1/reservation/{reservationId}

As a result of building this API, any client will be able to easily make reservations using the RMS!

CAN WE GET STARTED ALREADY!? Damn..๐Ÿ™„

Creating the RMS Spring Boot project

Create a new Spring Boot project using the Spring Initializr, or clone my repository to obtain the starter files (fork the repo and checkout branch part-1-starter-files).

Copy the following to make your life easier ๐Ÿ˜‰
  • Project type – Gradle
  • Language – java
  • Spring Boot version – 2.4.1 (use the latest LTS version of Spring Boot)
  • group ID – com.rms
  • Artifact ID – reservationservice
  • Service Name – reservationservice
  • packaging – I have chosen a WAR file, however, for the demo, it does not matter which one you choose ๐Ÿ™‚
  • Starter Dependencies
    • Spring Web – Provides everything you need to make a Spring Boot app quickly.
    • Lombok – An annotation rich library that helps remove more boilerplate code
    • Spring Data JPA – Provides various annotations, interfaces , and implementations to enable you to interact with a database quickly.
    • H2 – An in-memory database.

The Project Structure

After importing the project, there will already some folders and files created for you including:

  • bin – This is where compiled code will be placed, as well as the generated JAR / WAR file
  • gradle – Enables us to use gradle commands without needing to install gradle on our local machines.
  • src/main– This is where all our application code and application configuration will be kept.
  • src/test – where all our automated tests for the API will live, however, for this demo, we will not focus on the unit testing aspect. More on this soon!
  • build.gradle – where we plugin our dependencies so that we do not need to install the library JAR’s ourselves.
  • README.md – the readme for your project.

We will dive deeper into these various files and directories through out the guide, so that you become more comfortable navigating around the project. For the time being, lets start building our Reservation Management Service!

The build.gradle file

This is where dependencies will be imported from. We can tell gradle to manage our dependencies for us so that we do not have to handle this ourselves ๐Ÿ˜Ž. Your build.gradle file will look something like this:

plugins {
     id 'org.springframework.boot' version '2.4.1'
     id 'io.spring.dependency-management' version '1.0.10.RELEASE'
     id 'java'
     id 'war'
 }
 group = 'com.rms'
 version = '0.0.1-SNAPSHOT'
 sourceCompatibility = '11'
 configurations {
     compileOnly {
         extendsFrom annotationProcessor
     }
 }
 repositories {
     mavenCentral()
 }
 dependencies {
     implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
     implementation 'org.springframework.boot:spring-boot-starter-web'
     compileOnly 'org.projectlombok:lombok'
     runtimeOnly 'com.h2database:h2'
     annotationProcessor 'org.projectlombok:lombok'
     providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
     testImplementation 'org.springframework.boot:spring-boot-starter-test'
 }
 test {
     useJUnitPlatform()
 }

Notice that in the dependencies section, we can see that spring-boot-starter-data-jpa, spring-boot-starter-web, lombok, and h2 are being used, as we selected at project initialisation. These dependencies pull in multiple libraries for us so we can get going with building the RMS.

Time to Start Coding – But Where to Begin? ๐Ÿค”

We have been told that for a customer to make a reservation, the client will need to provide the following data to the service, which we need to store in our database:

  • A unique ID to identify the reservation
  • First Name
  • Last Name
  • Number of Guests
  • Reservation Date
  • Reservation Time
Step 1: Creating the database representation of a Reservation
  • Create a new package called entity.
  • Create a class called ReservationEntity. Within this class we can represent what our reservation data will look like.
  • Entity – An object representation of an item of a table in a database, also known as a Data Access Object (DAO). The Entity may contain certain “metadata” fields that relate to the object being stored in the database that the rest of the application does not necessarily need to know about e.g. createdAt, or updatedAt fields.
  • A DAO’s only purpose is to make interactions with the database and that’s it. Therefore, We should not have any custom business logic within our entities.
package com.rms.reservationservice.entity;

import lombok.*;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDateTime;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Data
@Builder
@Entity
@Table(name = "reservation")
public class ReservationEntity {
    @Id
    private String id; 
    private String firstName;
    private String lastName;
    private LocalDateTime reservationTime;
    private int numberOfGuests;
    private int duration;
 }

…Let’s understand all these new Entity annotations…

  • @NoArgsConstructor (access = PROTECTED) – Exists only for JPA. We are not going to be using this ourselves. (see more here)
  • @AllArgsConstructor – This gives us the option of creating ReservationEntity objects via a constructor call to be saved into the database. (see more here)
  • @Data – This Provides nested annotations to remove some more boilerplate code (see more here).
  • @Builder – Enables you to use the builder design pattern to create immutable objects in a slightly more verbose manner. (see more here)
  • @Table (name = โ€˜reservationโ€™) – This specifies the details of the table that will be used to persist the entity in the database. In this case, we are able to override the name of the table to be reservation. (see more here). On the other hand, if we did not provide this annotation, the table name would consequently be defaulted to our entity name.
  • @Entity – Indicates that this is an Entity object, which will represent a single row of the reservation table in the database.
  • @Id – Indicates to JPA that this is the ReservationEntity‘s primary key, which is something that we will generate later. As a result, we will be able to perform faster database lookups.

Note on the @Entity annotation โ€“ When we save an object in the database, we use an Object Relational Mapper (ORM) such as Hibernate to handle the mapping from an object to a relational database for us so we donโ€™t have to. The Spring Data JPA Starter dependency that we selected when creating the project provides the hibernate implementation for us! EVEN LESS BOILERPLATE CODE!

If you have had any trouble with this, fork the project and checkout branch part-1-creating-reservation-entity and compare your code against mine.

๐ŸŽ‰ You made to the end of Part 1! That wasn’t so bad, was it?๐ŸŽ‰

We are now ready to connect to a database and see the tables being created.
In Part 2: Creating the Repository Layer, we are going to start to interact with a database by creating the Repository layer and configuring the H2 database. See you there!