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.
Important links
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;
}
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.
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.
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.
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.
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.
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.