CodeGym /Courses /Module 5. Spring /Lecture 177: Hands-on — implementing a simple REST API fo...

Lecture 177: Hands-on — implementing a simple REST API for a microservice

Module 5. Spring
Level 12 , Lesson 6
Available

Today we'll walk through a hands-on build of a microservice that manages the Customer entity. We'll implement CRUD operations, hook up a database via Spring Data JPA, and test everything with tools like Postman.


Step 1: prepare the environment and create a new project

First, create a new project. You can do it via Spring Initializr:

  1. Set the following options:
    • Project: Maven
    • Language: Java
    • Spring Boot Version: 3.0.x+
    • Dependencies:
      • Spring Web
      • Spring Data JPA
      • H2 Database (embedded database for testing)
      • Spring Boot DevTools (for easier development)
  2. Download the project and open it in your IDE (for example, IntelliJ IDEA).

Step 2: database configuration

Create the application.yml file in src/main/resources (if it's missing). Configure the H2 connection like this:


spring:
  datasource:
    url: jdbc:h2:mem:customerdb
    driver-class-name: org.h2.Driver
    username: sa
    password: password
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true

This file configures an in-memory (H2) database and tells Hibernate to automatically update the table schema. The show-sql option lets you see SQL queries in the console, which is super useful for debugging.


Step 3: create the Customer entity

Add the Customer class to package com.example.customer:


package com.example.customer;

import jakarta.persistence.*;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Automatic ID generation
    private Long id;

    @Column(nullable = false) // Field can't be null
    private String name;

    @Column(nullable = false, unique = true)
    private String email;

    public Customer() {
        // Default constructor for JPA
    }

    public Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getters and setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

We defined the Customer entity with fields id, name, and email. The @Entity annotation tells JPA that this class maps to a table in the database.


Step 4: create the repository

Create the CustomerRepository interface:


package com.example.customer;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository<Customer, Long> {
    // JpaRepository provides basic CRUD operations
}

This interface makes it easy to work with the DB without writing SQL. For example, methods like save(), findById(), findAll(), and deleteById() are available right after you add the repository.


Step 5: create the service

Add the CustomerService class:


package com.example.customer;

import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class CustomerService {

    private final CustomerRepository customerRepository;

    public CustomerService(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    public List<Customer> getAllCustomers() {
        return customerRepository.findAll();
    }

    public Customer getCustomerById(Long id) {
        return customerRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Customer not found with id: " + id));
    }

    public Customer createCustomer(Customer customer) {
        return customerRepository.save(customer);
    }

    public Customer updateCustomer(Long id, Customer updatedCustomer) {
        Customer existingCustomer = getCustomerById(id);
        existingCustomer.setName(updatedCustomer.getName());
        existingCustomer.setEmail(updatedCustomer.getEmail());
        return customerRepository.save(existingCustomer);
    }

    public void deleteCustomer(Long id) {
        customerRepository.deleteById(id);
    }
}

This class encapsulates the business logic for working with customers.


Step 6: create the REST controller

Add the CustomerController class:


package com.example.customer;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/customers")
public class CustomerController {

    private final CustomerService customerService;

    public CustomerController(CustomerService customerService) {
        this.customerService = customerService;
    }

    @GetMapping
    public List<Customer> getAllCustomers() {
        return customerService.getAllCustomers();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Customer> getCustomerById(@PathVariable Long id) {
        try {
            Customer customer = customerService.getCustomerById(id);
            return ResponseEntity.ok(customer);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Customer createCustomer(@RequestBody Customer customer) {
        return customerService.createCustomer(customer);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Customer> updateCustomer(@PathVariable Long id, @RequestBody Customer updatedCustomer) {
        try {
            Customer customer = customerService.updateCustomer(id, updatedCustomer);
            return ResponseEntity.ok(customer);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteCustomer(@PathVariable Long id) {
        customerService.deleteCustomer(id);
    }
}

The controller handles HTTP requests and calls the service methods. Here we use @RestController, @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping annotations to route requests.


Step 7: testing the REST API

Run the app: click Run in your IDE or run mvn spring-boot:run in the terminal.

Testing endpoints via Postman

  1. Get all customers (GET):
    • URL: http://localhost:8080/customers
    • Response: [ ] (empty list by default).
  2. Create a new customer (POST):
    • URL: http://localhost:8080/customers
    • Body (JSON):
      {
        "name": "John Doe",
        "email": "john.doe@example.com"
      }
      
    • Response: the created object.
  3. Get customer by ID (GET):
    • URL: http://localhost:8080/customers/1.
  4. Update a customer (PUT):
    • URL: http://localhost:8080/customers/1
    • Body (JSON):
      
      {
        "name": "Jane Doe",
        "email": "jane.doe@example.com"
      }
      
  5. Delete a customer (DELETE):
    • URL: http://localhost:8080/customers/1.

Step 8: error handling and improvements

If you try to delete or update a non-existent customer, the app should return 404. That's already handled in our controller using ResponseEntity and custom exceptions.


Congrats! You just built your first microservice with a REST API. Now you're ready to build more and scale!

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION