Master java skills

Spring Boot Exception Handling

It is a good practice to handle exceptions and errors in APIs. By doing so, we can send proper response to the client. In this tutorial, we will learn how to handle exceptions in Spring Boot.

Before proceeding with exception handling, let us understand the following annotations.

@ControllerAdvice

@ControllerAdvice is a specialization of the @Component annotation which allows us to handle exceptions across the whole application in one global handling component. It can be seen as an interceptor of exceptions thrown by methods annotated with @RequestMapping and similar.

@ExceptionHandler

The @ExceptionHandler is used to handle the specific exceptions and sending the custom responses to the client.

Following code can be used to create @ControllerAdvice class to handle the exceptions globally

Example

Step 1 – Create a spring boot starter project in STS. Refer the below pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.7</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.javatrainingschool</groupId>
	<artifactId>spring-boot-exception-handling</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-exception-handling</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Step 2 – Create pojo class Product

package com.jts;

public class Product {

	private int id;
	private String name;

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + "]";
	}

	public Product(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Product() {
		super();
		// TODO Auto-generated constructor stub
	}
}

Step 3 – Create ProductController class

package com.jts;

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

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/products")
public class ProductController {
	
	private static Map<Integer, Product> productMap = new HashMap<>();
	
	static {
		
		Product soap = new Product(1, "Lux");
		productMap.put(soap.getId(), soap);

		Product mobilePhone = new Product(2, "Samsung");
		productMap.put(mobilePhone.getId(), mobilePhone);
		
	}
	
	@RequestMapping("/all")
	public Map<Integer, Product> getAllProducts(){
		return productMap;
	}
	
	@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
	public ResponseEntity<Object> updateProduct(@PathVariable("id") int id, @RequestBody Product product) {
		if (!productMap.containsKey(id))
			throw new ProductNotFoundException();
		else {
			productMap.put(id, product);
			return new ResponseEntity<>("Product is updated successfully", HttpStatus.OK);
		}
	}
}

Step 4 – Create ProductNotFoundException class

package com.javatrainingschool.exception;

public class ProductNotFoundException extends RuntimeException {
	
	private static final long serialVersionUID = 1L;

}

Step 5 – Create ControllerAdvice class

package com.javatrainingschool.controller;

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

import com.javatrainingschool.exception.ProductNotFoundException;

@ControllerAdvice
public class ProductExceptionController {
   @ExceptionHandler(value = ProductNotFoundException.class)
   public ResponseEntity<Object> exception(ProductNotFoundException exception) {
      return new ResponseEntity<>("Product is not found", HttpStatus.NOT_FOUND);
   }
}

Run and test the application

Run the application and test the following end points.

1. Get all the products

url – http://localhost:8080/products/all

2. Update the product (Success scenario)

3. Update the product (failed scenario)