Spring Boot - Handling Exceptions In REST



In this post, we will see how to handle exceptions using Custom Exception and send error response in REST apis. Here we read error messages from properties file, using Message Bundle.


Project Structure:

Spring Boot - Handling Exceptions In REST


pom.xml

<?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.7.11</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.javainspires</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot - Rest - Exception Handling</description>
	<properties>
		<java.version>11</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>

DemoApplication.java

package com.javainspires.demo;

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

@SpringBootApplication
public class DemoApplication {

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

}

Employee.java

package com.javainspires.demo;

public class Employee {
    private Integer empId;
    private String empName;

    public Employee(Integer empId, String empName) {
        this.empId = empId;
        this.empName = empName;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }
}

EmployeeService.java

package com.javainspires.demo;

import org.springframework.stereotype.Service;

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

@Service
public class EmployeeService {

    private List<Employee> employeeList = new ArrayList<>();
    EmployeeService(){
        employeeList.add(new Employee(1011,"John"));
        employeeList.add(new Employee(1012,"Noel"));
        employeeList.add(new Employee(1013,"Ben"));
    }
    public Optional<Employee> getEmployeeById(Integer empId){
            return   employeeList.stream().filter(emp->empId == emp.getEmpId()).findFirst();
    }
}

EmployeeController.java

package com.javainspires.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.server.PathParam;
import java.util.Optional;

@RestController
@RequestMapping(value = "/employee")
public class EmployeeController extends BaseController{

    @Autowired EmployeeService employeeService;

    @GetMapping(value = "/{empId}")
    public Employee getEmployee(@PathVariable(name = "empId") Integer empId){
        Optional<Employee> employee = employeeService.getEmployeeById(empId);
        if(employee.isEmpty()){
            throw new EmployeeNotFoundException("ERROR01",empId);
        }
        return employee.get();
    }

}

BaseController.java

package com.javainspires.demo;

import com.fasterxml.jackson.databind.ser.Serializers;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;

@Component
public class BaseController {

    @ResponseBody
    @ExceptionHandler({BaseServiceException.class})
    public ResponseEntity<ErrorResponse> handleException(BaseServiceException e, WebRequest webRequest){
        ErrorResponse errorResponse = new ErrorResponse();
        errorResponse.setErrorCode(e.getErrorCode());
        errorResponse.setErrorMessage(e.getMessage());
        ServletWebRequest servletWebRequest = (ServletWebRequest) webRequest;
        errorResponse.setPath(servletWebRequest.getRequest().getRequestURI());
        return new ResponseEntity<>(errorResponse,e.getHttpStatus());
    }
}

BaseServiceException.java

package com.javainspires.demo;

import org.springframework.http.HttpStatus;

import java.io.Serializable;

public class BaseServiceException extends RuntimeException{
    private final HttpStatus httpStatus;
    private final String errorCode;
    private final String errorMsg;
    private final Serializable[] args;

    public BaseServiceException(HttpStatus status,String errorCode, Serializable... args){
        this.httpStatus = status;
        this.errorCode = errorCode;
        this.errorMsg = null;
        this.args = args;
    }

    @Override
    public String getMessage() {
        if(this.errorMsg == null){
            return MessageBundle.getInstance().getMessage(this.errorCode,this.args);
        }
        return this.errorMsg;
    }

    public HttpStatus getHttpStatus() {
        return httpStatus;
    }

    public String getErrorCode() {
        return errorCode;
    }
}

EmployeeNotFoundException.java

package com.javainspires.demo;

import org.springframework.http.HttpStatus;

import java.io.Serializable;

public class EmployeeNotFoundException extends BaseServiceException {
    public EmployeeNotFoundException(String errorCode, Serializable... args) {
        super(HttpStatus.NOT_FOUND, errorCode, args);
    }
}

MessageBundle.java

package com.javainspires.demo;

import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.Locale;

@Component
public class MessageBundle {

    private static ReloadableResourceBundleMessageSource messageSource;

    private static MessageBundle messageBundle;

    public MessageBundle() {
        //empty
    }

    private static synchronized ReloadableResourceBundleMessageSource getMessageSourceInstance() {
        if (messageSource != null) {
            return messageSource;
        } else {
            messageSource = new ReloadableResourceBundleMessageSource();
            messageSource.setBasename("classpath:locale/messages");
            messageSource.setCacheMillis(3600);
            messageSource.setUseCodeAsDefaultMessage(true);
            return messageSource;
        }
    }

    public static synchronized MessageBundle getInstance() {
        if (messageBundle == null) {
            messageBundle = new MessageBundle();
        }
        return messageBundle;
    }

    public String getMessage(String errorCode, Object... args) {
        ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = getMessageSourceInstance();

        String messagePattern = reloadableResourceBundleMessageSource.getMessage(
                errorCode, null, new Locale("en", "US")
        );
        return args != null ? MessageFormat.format(messagePattern, args) : messagePattern;
    }
}

ErrorResponse.java

package com.javainspires.demo;

public class ErrorResponse {
    String errorCode;
    String errorMessage;
    String path;

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

messages_en_US.properties

ERROR01=Employee Not Found with ID :{0,number,#}

Response



tags: 

how to read error messages from properties file in spring boot, Getting message from property file in Spring boot, How To Handle Multiple Message Properties In Spring Boot, Custom Validation MessageSource in Spring Boot, Custom Error Messages How to read the values from properties file in Spring Boot?., Adding Message Properties Into The Spring Boot Project





















Post a Comment

Previous Post Next Post