Week 4 - Rest APIs

Java Annotations

Introduction to REST

Spring Boot Setup

Writing Endpoints

Message Formats

Input Validation

Practice

Assignment

Back end Track

Introduction

Setting up a new framework can feel like the biggest hurdle: a lot of configuration before you see the payoff. You have already done that hard part. Your Spring Boot project is ready, and now you can see how much functionality you can add with a small amount of code.

In this chapter, you will:

  1. Create a simple "Hello World" controller so you can see a working endpoint quickly.
  2. Rebuild the Categories controller from the Platzi Fake Store API: https://fakeapi.platzi.com/en/rest/categories/

<aside> 💡

Platzi FakeAPI is a popular fake backend API used by frontend developers to prototype e-commerce applications.

</aside>

Pre-requisites

“Hello World” Controller

With the setup done, this is all the code you need for your first endpoint:

package net.hackyourfuture.WeekFourRestAPI.controllers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FirstController {
  @GetMapping("/")
  public String helloWorld() {
    return "Hello World!";
  }
}

If within the package hierarchy of your main class, and if your main class is annotated with @SpringBootApplication , your controller will be picked up by Spring and be set-up automatically.

Then we test our controller with Postman by making a GET request to localhost:8080 ’s root path / :

Calling  on root  from Postman

Calling localhost:8080 on root / from Postman

That is a real HTTP endpoint. The browser or Postman sends a GET / request, Spring calls helloWorld(), and the response body contains Hello World!.

Do not worry if @RestController and @GetMapping still feel new. We will unpack them shortly while rebuilding the Categories API.

Now you are ready to build a controller with a more realistic functionality!

Exploring the target API (Platzi Fake Store Categories)

Before writing code, it’ll save time to first understand the API we are going to rebuild. Professional developers often start this way: they inspect the existing API contract, try a few requests, and then implement compatible behavior.

We will use the API's interactive documentation: Swagger UI*.

<aside> 💡

Swagger UI is an open-source tool that creates interactive API documentation from an OpenAPI specification. It lets you explore endpoints, inspect request and response shapes, and execute live requests directly in the browser.

</aside>

  1. Navigate to Swagger UI endpoint of Platzi fake store: https://api.escuelajs.co/docs.

    1. The page will have the Swagger logo:

      image.png

  2. Scroll down to the categories section.

    image.png

  3. Expand the GET /api/v1/categories operation.

  4. Click Try it out and execute a request directly in the browser.

    image.png

  5. Enter a value for the required parameters and execute a request directly in your browser:

     is the required parameter here. We have set it to 2 for testing a small response.

    limit is the required parameter here. We have set it to 2 for testing a small response.

We will implement the same basic category operations: listing categories, getting a single category, creating, updating, and deleting categories.

Package Structure

Below is a package structure you can refer to whenever you add a new feature. You will not create every file in this chapter, but this gives you the map.

<aside> ⚠️

Please note below folder structure starts from your main package: src/main/java/net/hackyourfuture/WeekFourRestAPI not the root of your project.

</aside>

📦 src/main/java/net/hackyourfuture/WeekFourRestAPI
├── 📄 WeekFourRestApiApplication.java
├── 📦 config/        # Global configuration
├── 📦 shared/        # Cross-cutting concerns
│   ├── 📦 exception/ # Exceptions not related to a feature
│   └── 📦 util/      # Common utility
└── 📦 category/                   ### Feature module ###
    ├── 📄 CategoryController.java   # Category is an example of course
    ├── 📄 CategoryService.java
    ├── 📦 models/    # Models of data our business logic operates on
    └── 📦 dto/       # Data Transfer Objects: Partial models focused on what downstream can send or understand
        ├── 📦 request/
        │   └── 📄 CreateCategoryRequest.java
        └── 📦 response/
            └── 📄 CategoryResponse.java

<aside> 💡

For example, a model for the Categories API should go under category/models/.

</aside>

<aside> 💡

Tests package Structure: As covered in Unit Testing with JUnit, test package structure shoud mirror that of main/ : src/**test**/java/net/hackyourfuture/WeekFourRestAPI .

</aside>

Category Model

First, you need a Java data model that can hold the category attributes returned by the target API:

image.png

To keep things focused, we will skip slugcreationAt, and updatedAt for now.

Create a new Java class named Category in the package net.hackyourfuture.WeekFourRestAPI.category.models.

<aside> 💡

To find the right place, look for the WeekFourRestAPI package in IntelliJ IDEA, then create the subpackages shown here: category.models. You can also revisit Package Structure section above.

</aside>

Remember that we added Lombok to the Spring project with Spring Initializr. Lombok lets us write less boilerplate:

package net.hackyourfuture.WeekFourRestAPI.category.models;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
public class Category {
  private Long id;
  private String name;
  private String image;
}

<aside> 💡

Since we’re now using Lombok annotations, when you first run the application, IntelliJ might ask you whether to “Enable Annotations Processing”, click Enable Annotations Processing .

This is for IntelliJ to process Lombok annotations and generate your Lombok code for build+run.

</aside>

Category Controller

Now let’s add our first controller!

Create a new file named CategoryController :

package net.hackyourfuture.WeekFourRestAPI.category;

import net.hackyourfuture.WeekFourRestAPI.category.models.Category;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping(value = "/api/v1/categories")
public class CategoryController {
  // Wrapping with ArrayList to make mutable; so we can add more categories later.
  private final List<Category> categories = new ArrayList<>(List.of(
      new Category(1L, "Clothes", "<https://i.imgur.com/QkIa5tT.jpeg>"),
      new Category(2L, "Electronics", "<https://i.imgur.com/ZANVnHE.jpeg>"),
      new Category(3L, "Furniture", "<https://i.imgur.com/Qphac99.jpeg>")
  ));

  @GetMapping
  public List<Category> getAllCategories() {
    return categories;
  }
}

<aside> 💡

The categories list is our temporary data store. In a real application, this data would usually come from a database, another service, or another API. For this first controller, keeping the data in memory helps us focus on endpoints.

</aside>

Run the server again. Your endpoint now serves categories at GET /api/v1/categories :

image.png

Controller Annotations Breakdown

Now let’s cover the annotations we used in CategoryController

@RestController

@RestController marks a class as a REST controller. Spring finds it during component scanning, creates an instance, and uses it to handle matching HTTP requests.

<aside> ⚠️

</aside>

@RequestMapping

@RequestMapping can bind a request path to a class or method. In our controller, it sets the base path for every endpoint in the class:

@RequestMapping("/api/v1/categories")

<aside> ❗

</aside>

@GetMapping

@GetMapping is a composed annotation. It is a shortcut for:

@RequestMapping(method = RequestMethod.GET)

In our controller, @GetMapping on getAllCategories() handles GET requests to the controller's base path: /api/v1/categories.

<aside> 💡

</aside>

Other Composed Mapping Annotations

Spring offers composed annotations for the common HTTP methods:

| --- | --- |

Reading a single category with @PathVariable

@PathVariable Binds a path segment in the URL to the method argument. We can use it to read the “id” passed in the path with GET /api/v1/categories/{id} endpoint:

Screenshot 2026-04-23 025250.jpg

// In CategoryController class, we add the below method

@GetMapping("/{id}")
public Category getCategoryById(@PathVariable Long id) {
  return categories.stream()
      .filter(category -> category.getId().equals(id))
      .findFirst()
      .orElse(null);
}

Testing it with Postman:

image.png

Filtering with @RequestParam

@RequestParam binds a query parameter from the URL to a method parameter. For example, ?name=cloth can be bound to a Java parameter: name.