Spring boot Exception Handling | @ExceptionHandler | @ControllerAdvice

PROGRAMMINGJava ExamplesC Examples
Java Examples
C Examples
C Tutorials
aws
JAVAEXCEPTIONSCOLLECTIONSSWINGJDBC
EXCEPTIONS
COLLECTIONS
SWING
JDBC
JAVA 8
SPRING
SPRING BOOT
HIBERNATE
PYTHON
PHP
JQUERY
PROGRAMMINGJava ExamplesC Examples
Java Examples
C Examples
C Tutorials
aws
In this tutorial, we will show you how to handle exceptions in Spring Boot REST API application.
This guide helps you to understand how to define generic/global exception handlers in spring boot application. Here I am going to implement a complete Spring boot restful service with all the CRUD operations and handling proper exception handling.
Spring Boot Strater 2.0.4 RELEASE
Spring Boot Starter WEB
Spring Boot Starter JDBC
MySql Connector
Java 1.8
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.onlinetutorialspoint</groupId>
  <artifactId>Spring-Boot-ExceptionHandling</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Spring-Boot-ExceptionHandling</name>
  <description>Spring Boot Exception Handling Example</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <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-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>

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

package com.onlinetutorialspoint.model;

public class Item {
    private int id;
    private String name;
    private String category;

    public Item() {
    }

    public Item(int id, String name, String category) {
        this.id = id;
        this.name = name;
        this.category = category;
    }

    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;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}

Preparing Spring Boot Error Response classes. This is the main response class representing response status, error message, and timestamp.
package com.onlinetutorialspoint.exception;

public class ItemErrorResponse {

    private int status;

    public ItemErrorResponse() {
    }

    private String message;
    private  long timeStamp;

    public ItemErrorResponse(int status, String message, long timeStamp) {
        this.status = status;
        this.message = message;
        this.timeStamp = timeStamp;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public long getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(long timeStamp) {
        this.timeStamp = timeStamp;
    }
}

Create ItemNotFoundException class, responsible for handling scenarios like when an item is not available in our database.
package com.onlinetutorialspoint.exception;

public class ItemNotFoundException extends RuntimeException{

    public ItemNotFoundException(String message) {
        super(message);
    }

    public ItemNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }

    public ItemNotFoundException(Throwable cause) {
        super(cause);
    }
}

Create a global ItemExceptionHandler, which handles ItemNotFoundException and all types of exceptions like 403, 500 and so on.
package com.onlinetutorialspoint.exception;

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

@ControllerAdvice
public class ItemExceptionHandler {

    @ExceptionHandler
    public ResponseEntity<ItemErrorResponse> handleException(ItemNotFoundException ine){
        ItemErrorResponse errorResponse = new ItemErrorResponse();
        errorResponse.setStatus(HttpStatus.NOT_FOUND.value());
        errorResponse.setMessage(ine.getMessage());
        errorResponse.setTimeStamp(System.currentTimeMillis());
        return new ResponseEntity<ItemErrorResponse>(errorResponse,HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler
    public ResponseEntity<ItemErrorResponse> handleException(Exception ex){
        ItemErrorResponse errorResponse = new ItemErrorResponse();
        errorResponse.setStatus(HttpStatus.BAD_REQUEST.value());
        errorResponse.setMessage(ex.getMessage());
        errorResponse.setTimeStamp(System.currentTimeMillis());
        return new ResponseEntity<ItemErrorResponse>(errorResponse,HttpStatus.BAD_REQUEST);
    }
}

@ControllerAdvice is used to apply the exception handling technique across the application. This annotation can be used on top of the class; then the class will act as a controller-advice.
@ControllerAdvice is something similar to an interceptor or a filter. It Pre-processes the request to the controller and Post-process the response to handle exceptions.
Define exception handler methods using @ExceptionHandler annotation given by the Spring Framework. It is going to return ResponseEntity.
ResponseEntity is a simple wrapper of HTTP response object; it provides fine-grained control to specify HTTP status codes, HTTP headers and response body.
We are creating ItemRepository having all CRUD operations.
package com.onlinetutorialspoint.repo;

import com.onlinetutorialspoint.exception.ItemNotFoundException;
import com.onlinetutorialspoint.model.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class ItemRepository {

    @Autowired
    JdbcTemplate template;

    /*Getting all Items from table*/
    public List<Item> getAllItems(){
        List<Item> items = template.query("select id, name,category from item",(result,rowNum)->new Item(result.getInt("id"),
                result.getString("name"),result.getString("category")));
        return items;
    }
    /*Getting a specific item by item id from table*/
    public Item getItem(int itemId){
        Item item = null;
        String query = "SELECT * FROM ITEM WHERE ID=?";
        try{
            item = template.queryForObject(query,new Object[]{itemId},new BeanPropertyRowMapper<>(Item.class));
        }catch(Exception e){
            throw new ItemNotFoundException("Item Not Found : "+itemId);
        }
        return item;
    }
    /*Adding an item into database table*/
    public int addItem(Item item){
        String query = "INSERT INTO ITEM VALUES(?,?,?)";
        return template.update(query,new Object[] {
                Integer.valueOf(item.getId()),item.getName(),item.getCategory()
        });
    }
    /*delete an item from database*/
    public int deleteItem(int id){
        String query = "DELETE FROM ITEM WHERE ID =?";
        int size = template.update(query,id);
        if(size == 0){
            throw new ItemNotFoundException("No Item Found to delete: "+id);
        }
        return size;
    }

    /*update an item from database*/
    public void updateItem(Item item){
        String query = "UPDATE ITEM SET name=?, category=? WHERE id =?";
        template.update(query,
                new Object[] {
                        item.getName(),item.getCategory(), Integer.valueOf(item.getId())
                });
    }
}

Creating Spring Boot RestController class
package com.onlinetutorialspoint.controller;

import com.onlinetutorialspoint.exception.ItemNotFoundException;
import com.onlinetutorialspoint.model.Item;
import com.onlinetutorialspoint.repo.ItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;

@RestController
public class ItemController {
    @Autowired
    ItemRepository itemRepo;

    @RequestMapping("/getAllItems")
    @ResponseBody
    public ResponseEntity<List<Item>> getAllItems(){
        List<Item> items =  itemRepo.getAllItems();
        return new ResponseEntity<List<Item>>(items, HttpStatus.OK);
    }

    @GetMapping("/item/{itemId}")
    @ResponseBody
    public ResponseEntity<Item> getItem(@PathVariable int itemId){
        if(itemId <= 0){
            throw new ItemNotFoundException("Invalid ItemId");
        }
        Item item = itemRepo.getItem(itemId);
        return new ResponseEntity<Item>(item, HttpStatus.OK);
    }

    @PostMapping(value = "/addItem",consumes = {"application/json"},produces = {"application/json"})
    @ResponseBody
    public ResponseEntity<Item> addItem(@RequestBody Item item,UriComponentsBuilder builder){
        itemRepo.addItem(item);
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(builder.path("/addItem/{id}").buildAndExpand(item.getId()).toUri());
        return new ResponseEntity<Item>(headers, HttpStatus.CREATED);
    }

    @PutMapping("/updateItem")
    @ResponseBody
    public ResponseEntity<Item> updateItem(@RequestBody Item item){
        if(item != null){
            itemRepo.updateItem(item);
        }
        return new ResponseEntity<Item>(item, HttpStatus.OK);
    }

    @DeleteMapping("/delete/{id}")
    @ResponseBody
    public ResponseEntity<Void> deleteItem(@PathVariable int id){
        itemRepo.deleteItem(id);
        return new ResponseEntity<Void>(HttpStatus.ACCEPTED);
    }
}

Main class
package com.onlinetutorialspoint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

mvn spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Spring-Boot-ExceptionHandling 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.0.4.RELEASE:run (default-cli) > test-compile @ Spring-Boot-ExceptionHandling >>>
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ Spring-Boot-ExceptionHandling ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ Spring-Boot-ExceptionHandling ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ Spring-Boot-ExceptionHandling ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\work\Spring-Boot-ExceptionHandling\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ Spring-Boot-ExceptionHandling ---
[INFO] No sources to compile
[INFO]
[INFO] <<< spring-boot-maven-plugin:2.0.4.RELEASE:run (default-cli) < test-compile @ Spring-Boot-ExceptionHandling <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.4.RELEASE:run (default-cli) @ Spring-Boot-ExceptionHandling ---

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.4.RELEASE)

2018-08-27 11:40:24.880  INFO 4584 --- [           main] com.onlinetutorialspoint.Application     : Starting Application on DESKTOP-RN4SMHT with PID 4584 (E:\work\Spring-Boot-Excepti
onHandling\target\classes started by Lenovo in E:\work\Spring-Boot-ExceptionHandling)
2018-08-27 11:40:24.896  INFO 4584 --- [           main] com.onlinetutorialspoint.Application     : No active profile set, falling back to default profiles: default
2018-08-27 11:40:25.146  INFO 4584 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWeb
ServerApplicationContext@2de77997: startup date [Mon Aug 27 11:40:25 IST 2018]; root of context hierarchy
2018-08-27 11:40:31.161  INFO 4584 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2018-08-27 11:40:31.317  INFO 4584 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-08-27 11:40:31.317  INFO 4584 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.32
2018-08-27 11:40:31.348  INFO 4584 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in pro
duction environments was not found on the java.library.path: [C:\Program Files\Java\jdk1.8.0_161\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\ProgramData\Oracle\Java
\javapath;C:\oraclexe\app\oracle\product.2.0\server\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\
MySQL\MySQL Server 5.5\bin;C:\php;C:\Apache24;C:\Apache24\bin;C:\Program Files\Java\jdk1.8.0_161\bin;D:\Softwares\apache-maven-3.5.2\bin;C:\Program Files\Git\cmd;C:\Program Files\Git
\mingw64\bin;C:\Program Files\Git\usr\bin;D:\Softwares\apache-ant-1.10.2\bin;C:\ProgramData\chocolatey\bin;;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\nodejs\;C:\Users\Lenovo\AppD
ata\Local\Programs\Python\Python36\Scripts\;C:\Users\Lenovo\AppData\Local\Programs\Python\Python36\;C:\Users\Lenovo\AppData\Local\Microsoft\WindowsApps;C:\Users\Lenovo\AppData\Local\
atom\bin;C:\Users\Lenovo\AppData\Local\Microsoft\WindowsApps;;C:\Program Files\Microsoft VS Code\bin;C:\Program Files\Docker Toolbox;C:\Users\Lenovo\AppData\Roaming\npm;.]
2018-08-27 11:40:31.567  INFO 4584 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-08-27 11:40:31.583  INFO 4584 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 6468 ms
2018-08-27 11:40:31.786  INFO 4584 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-08-27 11:40:31.786  INFO 4584 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-08-27 11:40:31.786  INFO 4584 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-08-27 11:40:31.786  INFO 4584 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-08-27 11:40:31.786  INFO 4584 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-08-27 11:40:32.911  INFO 4584 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.
web.servlet.resource.ResourceHttpRequestHandler]
2018-08-27 11:40:33.833  INFO 4584 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.Annota
tionConfigServletWebServerApplicationContext@2de77997: startup date [Mon Aug 27 11:40:25 IST 2018]; root of context hierarchy
2018-08-27 11:40:34.041  INFO 4584 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/item/{itemId}],methods=[GET]}" onto public org.springframework.http.Res
ponseEntity<com.onlinetutorialspoint.model.Item> com.onlinetutorialspoint.controller.ItemController.getItem(int)
2018-08-27 11:40:34.056  INFO 4584 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/delete/{id}],methods=[DELETE]}" onto public org.springframework.http.Re
sponseEntity<java.lang.Void> com.onlinetutorialspoint.controller.ItemController.deleteItem(int)
2018-08-27 11:40:34.056  INFO 4584 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/getAllItems]}" onto public org.springframework.http.ResponseEntity<java
.util.List<com.onlinetutorialspoint.model.Item>> com.onlinetutorialspoint.controller.ItemController.getAllItems()
2018-08-27 11:40:34.056  INFO 4584 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/updateItem],methods=[PUT]}" onto public org.springframework.http.Respon
seEntity<com.onlinetutorialspoint.model.Item> com.onlinetutorialspoint.controller.ItemController.updateItem(com.onlinetutorialspoint.model.Item)
.........
.........
Getting all Items :
Getting a specific Item:
Getting unavailable Item:
Deleting unavailable Item:
Invalid Item code format (General Exception handler)
Happy Learning 🙂


Spring-Boot-ExceptionHandling

File size: 97 KB
Downloads: 845


Spring Boot JdbcTemplate CRUD Operations Mysql
Spring Boot Redis Data Example CRUD Operations
How to use Spring Boot Random Port
Spring Boot How to change the Tomcat to Jetty Server
Spring Boot H2 Database + JDBC Template Example
Spring Boot In Memory Basic Authentication Security
Spring Boot MockMvc JUnit Test Example
Spring Boot JNDI Configuration – External Tomcat
Spring Boot EhCache Example
How to Create own Spring Boot Error Page
Spring Boot Kafka Consume JSON Messages Example
Advantages of Exception Handling
@Component,@Service,@Repository,@Controller in spring
Simple Spring Boot Example
Spring Boot JPA Integration Example

Spring Boot JdbcTemplate CRUD Operations Mysql
Spring Boot Redis Data Example CRUD Operations
How to use Spring Boot Random Port
Spring Boot How to change the Tomcat to Jetty Server
Spring Boot H2 Database + JDBC Template Example
Spring Boot In Memory Basic Authentication Security
Spring Boot MockMvc JUnit Test Example
Spring Boot JNDI Configuration – External Tomcat
Spring Boot EhCache Example
How to Create own Spring Boot Error Page
Spring Boot Kafka Consume JSON Messages Example
Advantages of Exception Handling
@Component,@Service,@Repository,@Controller in spring
Simple Spring Boot Example
Spring Boot JPA Integration Example
 


Δ
 Spring Boot – Hello World
 Spring Boot – MVC Example
 Spring Boot- Change Context Path
 Spring Boot – Change Tomcat Port Number
 Spring Boot – Change Tomcat to Jetty Server
 Spring Boot – Tomcat session timeout
 Spring Boot – Enable Random Port
 Spring Boot – Properties File
 Spring Boot – Beans Lazy Loading
 Spring Boot – Set Favicon image
 Spring Boot – Set Custom Banner
 Spring Boot – Set Application TimeZone
 Spring Boot – Send Mail
 Spring Boot – FileUpload Ajax
 Spring Boot – Actuator
 Spring Boot – Actuator Database Health Check
 Spring Boot – Swagger
 Spring Boot – Enable CORS
 Spring Boot – External Apache ActiveMQ Setup
 Spring Boot – Inmemory Apache ActiveMq
 Spring Boot – Scheduler Job
 Spring Boot – Exception Handling
 Spring Boot – Hibernate CRUD
 Spring Boot – JPA Integration CRUD
 Spring Boot – JPA DataRest CRUD
 Spring Boot – JdbcTemplate CRUD
 Spring Boot – Multiple Data Sources Config
 Spring Boot – JNDI Configuration
 Spring Boot – H2 Database CRUD
 Spring Boot – MongoDB CRUD
 Spring Boot – Redis Data CRUD
 Spring Boot – MVC Login Form Validation
 Spring Boot – Custom Error Pages
 Spring Boot – iText PDF
 Spring Boot – Enable SSL (HTTPs)
 Spring Boot – Basic Authentication
 Spring Boot – In Memory Basic Authentication
 Spring Boot – Security MySQL Database Integration
 Spring Boot – Redis Cache – Redis Server
 Spring Boot – Hazelcast Cache
 Spring Boot – EhCache
 Spring Boot – Kafka Producer
 Spring Boot – Kafka Consumer
 Spring Boot – Kafka JSON Message to Kafka Topic
 Spring Boot – RabbitMQ Publisher
 Spring Boot – RabbitMQ Consumer
 Spring Boot – SOAP Consumer
 Spring Boot – Soap WebServices
 Spring Boot – Batch Csv to Database
 Spring Boot – Eureka Server
 Spring Boot – MockMvc JUnit
 Spring Boot – Docker Deployment