Create a RESTful CRUD Application with Spring Boot

In this article, I will show the main endpoint needed to have a CRUD application. I show explain how to create those endpoints to be RESTful compliant.

I’ve already created a simple Spring Boot application in a recent article. And in another one, I’ve connected an existing Spring Boot application to a PostgreSQL database. From there, I will create many endpoints to end up with a CRUD application.

Content:

  • Introduction
  • Read endpoints
  • Create endpoints
  • Delete endpoints
  • Update endpoints

Introduction

The CRUD operations are the most basic operations a backend can have. It consists of Create, Read, Update and Delete. I can find those operations in any back office.

And what about the RESTful API? It’s about how I write my URLs, how I build the payload, the HTTP methods used, and what to return.

I’ll give more details while creating the endpoints.

Read Endpoints

First thing first, which HTTP method to use? GET.

How to write the URL? It depends on the items returned, let’s say I want to return all the vehicles:

GET /vehicles

Always in plural! Nothing more. And if I want only one vehicle:

GET /vehicles/{id}

Replacing the variable id with the Id of the vehicle I want to return. Notice that the root of the URL, vehicles, it’s still in plural. Because, from all the list of vehicles, I want the one with the given Id.

And now, the response. When asking for all the vehicles, I must return a list with many items, with many vehicles. Most of the time, it’s formatted in JSON.

And when I want one vehicle from its Id, it must return one item (not a list with one item).

The return HTTP code in both cases must be 200, Ok.

Let’s implement them in Spring Boot.

@RestController
@RequiredArgsConstructor
public class VehicleController {

    private final VehicleService vehicleService;

    @GetMapping("/vehicles")
    public ResponseEntity<List<VehicleDto>> allVehicles() {
        return ResponseEntity.ok(vehicleService.allVehicles());
    }

    @GetMapping("/vehicles/{id}")
    public ResponseEntity<VehicleDto> getVehicle(@PathVariable Long id) {
        return ResponseEntity.ok(vehicleService.getVehicle(id));
    }

}

I can find all the described before in the code.

  • The annotation @GetMapping which reflects the HTTP method GET, and the URL of the vehicle entity;
  • The ResponseEntity return type which will create a JSON response;
  • The wrapped response List<VehicleDto> or VehicleDto returning a list of vehicles or a single vehicle;
  • And the HTTP code 200 when calling ResponseEntity.ok.

Create Endpoints

As before, which HTTP method to use? POST.

As before, if I want to create a vehicle, I must write my URL like this:

POST /vehicles '{...}'

Why in plural again? Because I want to append a new vehicle to the existing list of vehicles.

And this time, I have to upload a body, with the data of the vehicle to create. It will be in JSON.

The response must be a 201 Created HTTP code with the body of the created and a URL where I can find the created vehicle. A URL like the one used to find one vehicle described before.

Let’s see the implementation in Spring Boot.

    @PostMapping("/vehicles")
    public ResponseEntity<VehicleDto> createVehicle(@Valid @RequestBody VehicleDto vehicleDto) {
        VehicleDto createdVehicle = vehicleService.createVehicle(vehicleDto);
        return ResponseEntity.created(URI.create("/vehicles/" + vehicleDto.getId())).body(createdVehicle);
    }

Now, I have:

  • The @PostMapping annotation to indicate the POST HTTP method;
  • The ResponseEntity<VehicleDto> to return the created vehicle;
  • The @RequestBody VehicleDto input parameter as the received body to create the vehicle;
  • The HTTP response code 201 Created at ResponseEntity.created;
  • And. theURL of the created vehicle with URI.create(“/vehicles/” + vehicleDto.getId()).

Delete Endpoints

To delete vehicles, I already have an HTTP method for that: DELETE.

And the URL will be as simple as before:

DELETE /vehicles/{id}

The vehicles with the Id of the vehicle to delete. Why in plural again? Because of all the existing vehicles, I want to delete the one with the given Id.

The first level in the URL will always be in the plural.

The response used to be to return the deleted object with the HTTP code 200 Ok.

Let’s go now to the implementation with Spring Boot:

    @DeleteMapping("/vehicles/{id}")
    public ResponseEntity<VehicleDto> deleteVehicle(@PathVariable Long id) {
        return ResponseEntity.ok(vehicleService.deleteVehicle(id));
    }
  • I can see the DELETE HTTP method in the annotation @DeleteMapping;
  • The parametrized URL at “/vehicles/{id}” with the id value passed at @PathVariable Long id;
  • And the 200 Ok return value at ResponseEntity.ok.

Update Endpoints

The last CRUD operation is the Update. Still, I can do the Update operation in several ways:

  • I can update a single field of an entity;
  • or I can replace an entire entity at once.

In both cases, I must send a body. Which HTTP methods allows me to send a body? I can do it with POST, PUT or PATCH.

  • The definition of POST is that the uploaded content will produce a different result every time I upload it. This is the definition of not idempotent. Let’s rephrase it: if I upload the same body of a vehicle two times in a row, the application will return with two different Ids, the application will create two different vehicles. This is not what I want for the Update operation;
  • The definition of PUT is to replace the existing content with the received content. This matches with the Replace operation. Now, PUT is idempotent, I can upload many times the same vehicle body, and it will replace it in the application and return the updated vehicle again and again. The same action will produce the same result;
  • And the definition of PATCH is to update a small part of an existing entity. This matches with the Update operation. The PATCH method is also idempotent.

What about the URL? I want to update one vehicle from all the existing vehicles. This means that I have the vehicles in the first part and the parametrized Id in the second part.

Let’s see the call of the Replace operation:

PUT /vehicles/{id} {...}

And the call of the Update operation:

PATCH /vehicles/{id} {...}

And the return type for both cases should be the updated entity with a 200 Ok HTTP code.

Let’s see the implementation in Spring Boot:

    @PutMapping("/vehicles/{id}")
    public ResponseEntity<VehicleDto> updateVehicle(@PathVariable Long id, @Valid @RequestBody VehicleDto vehicleDto) {
        return ResponseEntity.ok(vehicleService.updateVehicle(id, vehicleDto));
    }

    @PatchMapping("/vehicles/{id}")
    public ResponseEntity<VehicleDto> patchVehicle(@PathVariable Long id, @RequestBody VehicleDto vehicleDto) {
        return ResponseEntity.ok(vehicleService.patchVehicle(id, vehicleDto));
    }
  • I can see both HTTP methods at @PutMapping and @PatchMapping;
  • Both endpoints have the parametrized URL at “/vehicles/{id}” with the injected Id at @PathVariable Long id;
  • Both endpoints have the incoming body at @RequestBody VehicleDto vehicleDto. But I use the @Valid annotation for the PUT and not for the PATCH. Why? When I replace my vehicle, I must ensure that all the mandatory fields are received. With the PATCH, I must update only the received fields (I skip those with null);
  • And finally, return a 200 Ok with ResponseEntity.ok.

Conclusion

Those are the main operations to have a CRUD application.

Then come the more advanced REST endpoints for more advanced operations, like search, get children, sort and limit…

But I won’t talk about those now. Maybe in another article.

You may say want to see the explanatory video.

And I also share you the Github repository.

If you want to learn more about good quality code, make sure to follow me on Youtube.


Never Miss Another Tech Innovation

Concrete insights and actionable resources delivered straight to your inbox to boost your developer career.

My New ebook, Best Practices To Create A Backend With Spring Boot 3, is available now.

Best practices to create a backend with Spring Boot 3

3 responses to “Create a RESTful CRUD Application with Spring Boot”

  1. […] won’t handle the backend part, as I’ve already written an article about […]

    Like

  2. […] finally, I’ve also created some endpoints to have the main CRUD operations, Create, Read, Update and […]

    Like

  3. […] The backend part of the CRUD operations can be found in this article. […]

    Like

Leave a reply to How to use React for a CRUD application – The Dev World – Sergio Lema Cancel reply

Discover more from The Dev World - Sergio Lema

Subscribe now to keep reading and get access to the full archive.

Continue reading