Skip to main content

Backend & REST APIs

In this webinar we will discuss APIs and backend development. The backend framework of choice for this webinar is Spring Boot, and the database of choice is MySQL.

GitHub repository

YouTube Live

What is an API?

API stands for application programming interface, which is a set of definitions and protocols for building and integrating software.

Every website or application has two main parts: front-end and back-end, and those two parts need to be interconnected, in order for them to work as they should. This is done by implementing a REST Api.

What is a REST API?

A REST API (also known as RESTful API) is an application programming interface that conforms to the constraints of REST architectural style and allows for interaction with RESTful web services. REST stands for representational state transfer.

JSON

JSON stands for JavaScript Object Notation, and it is a lightweight data-interchange format. It is easy for humans to read and write, and it is easy for machines to parse and generate. We will use JSON to pass data between the front-end and the back-end.

This is how a JSON object looks like:

{
"firstName": "John",
"lastName": "Smith",
"age": 25
}

It is basically a collection of key-value pairs, where the key is a string, and the value can be a string, number, boolean, array or another JSON object.

The JSON would be the equivalent of the following Java class:

public class Person {
private String firstName;
private String lastName;
private int age;
}
tip

Due to the fact that age is an integer, and not a string, in the JSON object it is not surrounded by quotes.

HTTP

HTTP stands for Hypertext Transfer Protocol, and it is an application-layer protocol for transmitting hypermedia documents, such as HTML. It was designed for communication between web browsers and web servers, but it can also be used for other purposes.

HTTPS is the secure version of HTTP, and it is used to provide encrypted communication and secure identification of a network web server. HTTPS connections are now used for most websites, in order to protect their users' connections.

Types of requests

There are 4 main types of requests that you should be aware of:

  • GET - used to retrieve data from the server
  • POST - used to send data to the server
  • PUT - used to update data on the server
  • DELETE - used to delete data from the server

What tools will we use?

  • Spring Boot - the backend framework (Java)
  • Postman - used to test the API
  • Docker - used to run the database
  • MySQL - the database (in the docker container)

Hands-on

The easiest way to learn is by doing, so let's build a simple API together, that will handle CRUD operations for Toys.

info

CRUD stands for Create, Read, Update, Delete. These are the 4 basic operations that can be performed on a database.

Create a Spring Boot project

To create our Spring Boot project, we will use the Spring Initializr website. We will select the following options:

  • Project: Gradle Project
  • Language: Java
  • Spring Boot: 3.0.6
  • Dependencies: Spring Web, Spring Data JPA, MySQL Driver

After we download the project, we will open it in IntelliJ IDEA.

Prerequisites: The database

In order to run the database, we will use Docker. We will use the following Docker-compose file:

version: '3'
services:
sql:
image: mysql:8.0.32
container_name: he-30-sql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root

A docker compose file is a YAML file that defines how Docker containers should behave. We used this file to define a MySQL container, which will run on port 3306, and will have the root password set to "root".

To run the database, we will run the following command in the terminal:

docker-compose up

Prerequisites: The database schema and Spring Boot configuration

In order to connect to the database, we need to configure the application.yml file, which we will create in the src/main/resources folder. The file should contain the following:

spring:
datasource:
url: jdbc:mysql://localhost:3306/he-demo
username: root
password: root
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
hibernate:
ddl-auto: update
connection-url: jdbc:mysql://localhost:3306/he-demo
dialect: org.hibernate.dialect.MySQLDialect

This file contains the database connection details, and the Hibernate configuration. Hibernate is an ORM (Object Relational Mapping) framework, which allows us to map Java classes to database tables.

info

In the src/main/resources folder we will already have a application.properties file, which we will delete. This is because we will use the application.yml file instead.

MVC architecture

In order to understand how Spring Boot works, we need to understand the MVC architecture. MVC stands for Model-View-Controller, and it is a software design pattern commonly used for developing user interfaces that divides the related program logic into three interconnected elements.

  • Model - the data
  • View - the user interface
  • Controller - the logic

In order to have a clean architecture and structure our code, we will create the following packages:

  • controller
  • model
  • repository
  • service

Creating the Toy model

In the model package, we will create a new class called Toy, which will represent a toy. The class should look like this:

@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Toy {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String description;
private String image;
}

The @Entity annotation tells Hibernate that this class is an entity, and it should be mapped to a database table. The @Data annotation is a Lombok annotation, which generates getters, setters, equals, hashCode and toString methods. The @Builder annotation is also a Lombok annotation, which generates a builder method for the class. The @AllArgsConstructor annotation is a Lombok annotation, which generates a constructor with all the fields in the class. The @NoArgsConstructor annotation is a Lombok annotation, which generates a constructor with no arguments.

The @Id annotation tells Hibernate that this field is the primary key of the table. The @GeneratedValue annotation tells Hibernate that the value of this field will be generated automatically.

info

We had to use @AllArgsConstructor and @NoArgsConstructor because we used the @Builder annotation. If we didn't use the @Builder annotation, we wouldn't have needed to use the other two annotations.

Creating the Toy repository

In the repository package, we will create a new interface called ToyRepository, which will extend the JpaRepository interface. The interface should look like this:

public interface ToyRepository extends JpaRepository<Toy, Long> {
}

The JpaRepository interface is a Spring Data JPA interface, which provides CRUD operations for the entity that we pass as the first parameter, and the type of the primary key as the second parameter.

Creating the Toy service

In the service package, we will create a new class called ToyService, which will contain the business logic for the Toy entity. The class should look like this:

@Service
@RequiredArgsConstructor
public class ToyService {
private final ToyRepository toyRepository;

public Toy getToy(Long id) {
return toyRepository.findById(id).orElseThrow();
}

public Toy createToy(Toy toy) {
return toyRepository.save(toy);
}

public Toy updateToy(Toy toy) {
return toyRepository.save(toy);
}

public void deleteToy(Long id) {
toyRepository.deleteById(id);
}

public List<Toy> getAllToys() {
return toyRepository.findAll();
}
}

The @Service annotation tells Spring that this class is a service, and it should be instantiated and injected into other classes. The @RequiredArgsConstructor annotation is a Lombok annotation, which generates a constructor with all the fields in the class that are required (in this case the ToyRepository field).

The getToy method retrieves a toy from the database, based on the id. The createToy method creates a toy in the database. The updateToy method updates a toy in the database. The deleteToy method deletes a toy from the database, based on the id. The getAllToys method retrieves all the toys from the database.

info

The .findById(), .save(), .deleteById() and .findAll() methods are provided by the JpaRepository interface that is extended by the ToyRepository interface.

Creating the Toy controller

In the controller package, we will create a class called ToyController which will contain the endpoints for the Toy entity. The class should look like this:

@RestController
@RequestMapping("api/v1/toy")
@RequiredArgsConstructor
public class ToyController {
private final ToyService toyService;

@GetMapping("{id}")
public Toy getToy(@PathVariable Long id) {
return toyService.getToy(id);
}

@GetMapping
public List<Toy> getAllToys() {
return toyService.getAllToys();
}

@PostMapping
public Toy createToy(@RequestBody Toy toy) {
return toyService.createToy(toy);
}

@PutMapping
public Toy updateToy(@RequestBody Toy toy) {
return toyService.updateToy(toy);
}

@DeleteMapping("{id}")
public void deleteToy(@PathVariable Long id) {
toyService.deleteToy(id);
}
}

The @RestController annotation tells Spring that this class is a controller, and it should be instantiated and injected into other classes. The @RequestMapping annotation tells Spring that all the endpoints in this class will start with api/v1/toy. The @RequiredArgsConstructor annotation is a Lombok annotation, which generates a constructor with all the fields in the class that are required (in this case the ToyService field).

The getToy method is mapped to the GET api/v1/toy/{id} endpoint, and it retrieves a toy from the database, based on the id. The getAllToys method is mapped to the GET api/v1/toy endpoint, and it retrieves all the toys from the database. The createToy method is mapped to the POST api/v1/toy endpoint, and it creates a toy in the database. The updateToy method is mapped to the PUT api/v1/toy endpoint, and it updates a toy in the database. The deleteToy method is mapped to the DELETE api/v1/toy/{id} endpoint, and it deletes a toy from the database, based on the id.

info

The @GetMapping, @PostMapping, @PutMapping and @DeleteMapping annotations are shortcuts for the @RequestMapping annotation, which is why we don't need to specify the HTTP method in the @RequestMapping annotation.

Testing the application

After we build and run the application, we can test the endpoints using Postman. We can create a new toy by sending a POST request to the api/v1/toy endpoint, with the following body:

{
"name": "Teddy Bear",
"description": "A cute teddy bear",
"image": "https://codingshadows.com/teddy-bear.jpg"
}

We can retrieve the toy by sending a GET request to the api/v1/toy/{id} endpoint, where {id} is the id of the toy that we want to retrieve. We can retrieve all the toys by sending a GET request to the api/v1/toy endpoint. For example, if we want to retrieve the toy with the id 1, we would send a GET request to the api/v1/toy/1 endpoint. This would return the following response:

{
"id": 1,
"name": "Teddy Bear",
"description": "A cute teddy bear",
"image": "https://codingshadows.com/teddy-bear.jpg"
}

We can update a toy by sending a PUT request to the api/v1/toy endpoint, with the following body:

{
"id": 1,
"name": "Teddy Bear",
"description": "A cute updated teddy bear",
"image": "https://codingshadows.com/teddy-bear.jpg"
}

If we now send a GET request to the api/v1/toy/1 endpoint, we will get the following response:

{
"id": 1,
"name": "Teddy Bear",
"description": "A cute updated teddy bear",
"image": "https://codingshadows.com/teddy-bear.jpg"
}

We can delete a toy by sending a DELETE request to the api/v1/toy/{id} endpoint, where {id} is the id of the toy that we want to delete. For example, if we want to delete the toy with the id 1, we would send a DELETE request to the api/v1/toy/1 endpoint.

Instead of Postman we may also use Swagger to test the endpoints. Swagger is a tool that allows us to document and test our REST APIs. It provides a user interface that allows us to test the endpoints without having to use Postman. To use Swagger, we need to add the following dependency to the build.gradle file:

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

After we build and run the application, we can access the Swagger UI at http://localhost:8080/swagger-ui.html. We can use the Swagger UI to test the endpoints.

Conclusions

In this tutorial we learned how to create a simple REST API with Spring Boot, as well as using other tools such as Docker, Postman and Swagger. We also learned how to use Lombok to reduce boilerplate code.