Exception Handling in Springboot

Creating custom exceptions springboot

Exception Handling in Springboot

Introduction

In this article, we going to be looking at how to handle exceptions in spring boot and create custom exceptions. So basically, in this case, we will use the employee restApi we created lastly to implement exception handling.

You can read this article first to understand how to build a restApi using spring boot.

Creating the Exception directory

Ensure to have created an exception directory like the one created above. This is where you shall save all the exception classes.

Creating the Exception class

We will create a class called ResourceNotFoundException that gonna help us throw an exception whenever a user tries to find an employee who doesn't exist.

package com.alekinyua.restapiexceptions.exceptions;

public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

The class will extend the RuntimeException. Also, we will have to create a Constructor with a parameter message.

Creating the ExceptionHandler class

This exception handler class is responsible for catching and dealing with the custom exception created.

package com.alekinyua.restapiexceptions.exceptions;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ResourceNotFoundException.class)
    public Map<String, String> ResourceNotFound(ResourceNotFoundException exception){
        Map<String, String> error = new HashMap<>();
        error.put("error", exception.getLocalizedMessage());

        return error;
    }
}

This class is annotated with @ControllerAdvice annotation. It allows you to centralize your exception handling logic and apply it across multiple controllers in a Spring application.

public Map<String, String> ResourceNotFound(ResourceNotFoundException exception): This is the method that handles the ResourceNotFoundException. The method takes an instance of ResourceNotFoundException as a parameter, allowing access to the exception details, if needed.

The method returns the error map, which will be converted to a JSON response and sent back to the client when a ResourceNotFoundException occurs.

The method is annotated with 2 main annotations namely:

  1. @ResponseStatus(HttpStatus.BAD_REQUEST): This indicates that the HTTP status code to be returned by this method is "400 Bad Request." In the context of exception handling, it specifies the status code that should be sent back to the client when a ResourceNotFoundException is caught and handled by this method.

  2. @ExceptionHandler(ResourceNotFoundException.class): This line specifies that the following method should be invoked when a ResourceNotFoundException occurs within any controller of the application. It means that if a controller throws a ResourceNotFoundException, this method will be responsible for handling that exception.

I guess this is it, we can now start handling exceptions on our RestApi application.

Handling Exception at employee service

Whenever we try to find an employee by id who doesn't exist on the database, our RestApi application crashes. We are going to solve this problem by throwing a ResourceNotFoundException in any case we try to find an employee.

package com.alekinyua.restapiexceptions.service;

import com.alekinyua.restapiexceptions.entity.Employee;
import com.alekinyua.restapiexceptions.exceptions.ResourceNotFoundException;
import com.alekinyua.restapiexceptions.repository.EmployeeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

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


@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public Optional<Employee> getEmployee(Long id) {
        return Optional.ofNullable(employeeRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Employee with id " + id + " is not found")));
    }

    public List<Employee> getAllEmployees() {
        List<Employee> employees = employeeRepository.findAll();
        return employees;
    }

    public Employee saveEmployee(Employee employee){
        return employeeRepository.save(employee);
    }

    public Employee updateEmployee(Long id, Employee employeeToUpdate){
        Employee employee = employeeRepository.findById(id).
                orElseThrow(() -> new ResourceNotFoundException("Employee with id " + id + " is not found"));
        employee.setName(employeeToUpdate.getName());
        employee.setEmail(employeeToUpdate.getEmail());
        employee.setAge(employeeToUpdate.getAge());

        return employeeRepository.save(employee);
    }



    public void deleteEmployee(Long id){
        Employee employee = employeeRepository.findById(id).
                orElseThrow(() -> new ResourceNotFoundException("Employee with id " + id + " is not found"));
        if (employee != null){
            employeeRepository.delete(employee);
        }
    }
}

We handled the exceptions on the methods namely deleteEmployee(), getEmployee() and updateEmployee().

Thank you for following through with the article and let me know in the comments if there were any difficulties experienced.