<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Syed Shujaat Hussain SHAH</title>
    <description>The latest articles on DEV Community by Syed Shujaat Hussain SHAH (@shujaat34).</description>
    <link>https://dev.to/shujaat34</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1045216%2F09453ef7-4581-4ce5-8c4d-c5f5e61b8b83.jpeg</url>
      <title>DEV Community: Syed Shujaat Hussain SHAH</title>
      <link>https://dev.to/shujaat34</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shujaat34"/>
    <language>en</language>
    <item>
      <title>Exception Handling and Validation in Spring boot</title>
      <dc:creator>Syed Shujaat Hussain SHAH</dc:creator>
      <pubDate>Wed, 15 Mar 2023 10:46:37 +0000</pubDate>
      <link>https://dev.to/shujaat34/exception-handling-and-validation-in-spring-boot-3of9</link>
      <guid>https://dev.to/shujaat34/exception-handling-and-validation-in-spring-boot-3of9</guid>
      <description>&lt;p&gt;It is very important to handle the exceptions, logical errors and provide meaningful message to the client to avoid abnormal termination of the Restful APIs in Springboot.&lt;/p&gt;

&lt;p&gt;Today we will learn how to implement Global Exception Handling as well as Class Level Exception Handling.&lt;/p&gt;

&lt;p&gt;Pre-requisite : You must have knowledge about Springboot and Restful API Creation, Jpa (Java Persistance API) and a bit about Exception Handling in Java core.&lt;/p&gt;

&lt;p&gt;We will be using &lt;strong&gt;java-17&lt;/strong&gt; to create spring boot template project with &lt;strong&gt;&lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Spring Initilizr&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We need the Following dependencies for the Project.&lt;br&gt;
pom.xml&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;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"&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
    &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;3.0.4&amp;lt;/version&amp;gt;
        &amp;lt;relativePath/&amp;gt; &amp;lt;!-- lookup parent from repository --&amp;gt;
    &amp;lt;/parent&amp;gt;
    &amp;lt;groupId&amp;gt;com.bukhari&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;exceptionhandling-validation&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;name&amp;gt;exceptionhandling-validation&amp;lt;/name&amp;gt;
    &amp;lt;description&amp;gt;Demo project for Spring Boot&amp;lt;/description&amp;gt;
    &amp;lt;properties&amp;gt;
        &amp;lt;java.version&amp;gt;17&amp;lt;/java.version&amp;gt;
    &amp;lt;/properties&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-data-jpa&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-validation&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.mysql&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;mysql-connector-j&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;

&amp;lt;/project&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The application.properties File&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

#Dabase Configuration
spring.application.name=Exception-Handling-Application
server.port=8082
spring.datasource.url=jdbc:mysql://localhost:3306/libdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1

spring.jpa.hibernate.naming-strategy=org.hibernate.dialect.MySQL8Dialect
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.formate_sql=true


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Class Level Exception Handling
&lt;/h2&gt;

&lt;p&gt;The Hierarchy of Code&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffh90n33rybrqr13sjgns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffh90n33rybrqr13sjgns.png" alt="The Hierarchy of java files in an IDE"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entity Book&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.entity;


import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String author;
    private Double price;

    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 getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The BookRepository&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure you import the Book from entity.Book package not from java.awt.print&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.repository;

import com.bukhari.exceptionhandlingvalidation.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BookRepository extends JpaRepository&amp;lt;Book, Long&amp;gt; {

}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The Exceptions that we want to handle are&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Book name cannot be empty.&lt;/li&gt;
&lt;li&gt;Book Author name cannot be empty.&lt;/li&gt;
&lt;li&gt;Price of Book must be $10 or greater than $10. (assuming price is always non-empty).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The BookService&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.service;

import com.bukhari.exceptionhandlingvalidation.classexception.LibBusinessException;
import com.bukhari.exceptionhandlingvalidation.entity.Book;
import com.bukhari.exceptionhandlingvalidation.repository.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {

    @Autowired
    private BookRepository bookRepository;

    public Book addBook(Book book) {

        //If the Name of the book is Empty
        if (book.getName().isEmpty()) {
            throw new LibBusinessException("801", "The Name of the Book can't be Empty");
        }
        //If the Name of the Author is Empty
        if (book.getAuthor().isEmpty()) {
            throw new LibBusinessException("802", "The Author's Name can't be Empty");
        }

        //If the Price is less than 10
        if (book.getPrice().intValue() &amp;lt; 10) {
            throw new LibBusinessException("803", "The Price of the Book must be $10 or greater than $10");
        }
        return bookRepository.save(book);
    }

}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The LibBusinessException&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.classexception;

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

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class LibBusinessException extends RuntimeException {

    private String errorCode;
    private String errorMessage;

    public LibBusinessException(String errorCode, String errorMessage) {
        super();
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The BookController&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.controller;

import com.bukhari.exceptionhandlingvalidation.classexception.LibBusinessException;
import com.bukhari.exceptionhandlingvalidation.entity.Book;
import com.bukhari.exceptionhandlingvalidation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("digital/lib")
public class LibraryController {
    @Autowired
    private BookService bookService;

    @PostMapping("/book")
    public ResponseEntity&amp;lt;?&amp;gt; saveBook(@RequestBody Book book) {
        try {
            Book savedBook = bookService.addBook(book);
            return new ResponseEntity&amp;lt;Book&amp;gt;(savedBook, HttpStatus.CREATED);
        } catch (LibBusinessException e) {
            LibBusinessException libex = new LibBusinessException(e.getErrorCode(), e.getErrorMessage());
            return new ResponseEntity&amp;lt;LibBusinessException&amp;gt;(libex, HttpStatus.BAD_REQUEST);
        } catch (Exception e) {
            LibBusinessException libex = new LibBusinessException("804", "Something went wrong in controller");
            return new ResponseEntity&amp;lt;LibBusinessException&amp;gt;(libex, HttpStatus.BAD_REQUEST);
        }
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;If the Book Name is Empty&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostMan Request and Response&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk3ujkqfrpjo2sp63brmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk3ujkqfrpjo2sp63brmb.png" alt="Request and Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the Book Author Name is Empty&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostMan Request and Response&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqqvbxw03nsuuddz1ec2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqqvbxw03nsuuddz1ec2.png" alt="Request and Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the Book Price is less than $10&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostMan Request and Response&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckrqz3ykhlt279wxc33l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckrqz3ykhlt279wxc33l.png" alt="Request and Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the Book entity is null&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlaewu7zmxom583rlqf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlaewu7zmxom583rlqf4.png" alt="Request Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation and Global Exception Handling Using ControllerAdvice
&lt;/h2&gt;

&lt;p&gt;Let's Understand now validation and Global Exception Handling&lt;br&gt;
We will take AppUser Entity for this purpose. (pom.xml is same).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AppUser Entity&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class AppUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int userId;
    private String name;
    private String email;
    private String mobile;
    private String gender;
    private int age;
    private String nationality;

    public AppUser() {
    }

    public AppUser(int userId, String name, String email, String mobile, String gender, int age, String nationality) {
        this.userId = userId;
        this.name = name;
        this.email = email;
        this.mobile = mobile;
        this.gender = gender;
        this.age = age;
        this.nationality = nationality;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

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

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getNationality() {
        return nationality;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Request For AppUser&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.request;

import jakarta.validation.constraints.*;

/**
 * Global Exception Handling AppUserRequest
 */
public class AppUserRequest {
    @NotNull(message = "username must not be null")
    private String name;
    @Email(message = "Invalid email address, Please provide a valid email")
    private String email;
    @Pattern(regexp = "^\\d{10}$", message = "Invalid mobile number, Please Provide a Valid Number")
    private String mobile;
    private String gender;
    @Min(value = 18, message = "Age must be 18 or greater")
    @Max(value = 60, message = "Age must be 60 or less")
    private int age;
    @NotBlank
    private String nationality;

    public AppUserRequest(String name, String email, String mobile, String gender, int age, String nationality) {
        this.name = name;
        this.email = email;
        this.mobile = mobile;
        this.gender = gender;
        this.age = age;
        this.nationality = nationality;
    }

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

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getNationality() {
        return nationality;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }
}




&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We are going to validate and handle the following exceptions &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name must not be null.&lt;/li&gt;
&lt;li&gt;Email must be valid.&lt;/li&gt;
&lt;li&gt;Mobile Number must be valid.&lt;/li&gt;
&lt;li&gt;Age must be between 18 and 60.&lt;/li&gt;
&lt;li&gt;Nationality must not be blank (non-empty and non-null).&lt;/li&gt;
&lt;li&gt;Map Custom Class to ExceptionHandler if user is not Found.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this purpose we are using &lt;code&gt;@RestControllerAdvice&lt;/code&gt; as Global Exception handler which is a better approach as compared to the Class Level approach. The &lt;code&gt;@RestControllerAdvice&lt;/code&gt; is mapped to all the Controllers and once the request is triggered the Advice checks for any mapping matches to it and sends the response accordingly. Since Spring Provides us &lt;code&gt;@ExceptionHandler&lt;/code&gt; annotation to intercept any java as well as logical exception so we can implement according to our own requirement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The RestControllerAdvice&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.globalexception;

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

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

/**
 * Global Exception Handling ControllerAdvice
 */

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map&amp;lt;String, String&amp;gt; handleInvalidArgument(MethodArgumentNotValidException ex) {
        Map&amp;lt;String, String&amp;gt; errorMap = new HashMap&amp;lt;&amp;gt;();
        ex.getBindingResult().getFieldErrors().forEach(error -&amp;gt; {
            errorMap.put(error.getField(), error.getDefaultMessage());
        });
        return errorMap;
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(UserNotFoundException.class)
    public Map&amp;lt;String, String&amp;gt; handleBusinessException(UserNotFoundException ex) {
        Map&amp;lt;String, String&amp;gt; errorMap = new HashMap&amp;lt;&amp;gt;();
        errorMap.put("errorMessage", ex.getMessage());
        return errorMap;
    }

}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The Custom Class For UserNotFoundException&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.globalexception;

/**
 * Global Exception Handling UserNotFoundException
 */
public class UserNotFoundException  extends Exception{
    public UserNotFoundException(String message) {
        super(message);
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The AppUserRepository&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.repository;

import com.bukhari.exceptionhandlingvalidation.entity.AppUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
 * Global Exception Handling AppUserRepository
 */
@Repository
public interface AppUserRepository extends JpaRepository&amp;lt;AppUser,Integer&amp;gt; {

}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The AppUserService&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.service;

import com.bukhari.exceptionhandlingvalidation.entity.AppUser;
import com.bukhari.exceptionhandlingvalidation.globalexception.UserNotFoundException;
import com.bukhari.exceptionhandlingvalidation.repository.AppUserRepository;
import com.bukhari.exceptionhandlingvalidation.request.AppUserRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * Global Exception Handling AppUserService
 */
@Service
public class AppUserService {

    @Autowired
    private AppUserRepository appUserRepository;


    public AppUser saveUser(AppUserRequest userRequest) {
        AppUser user = new AppUser(0, userRequest.getName(), userRequest.getEmail(),
                userRequest.getMobile(), userRequest.getGender(), userRequest.getAge(), userRequest.getNationality());
        return appUserRepository.save(user);
    }


    public List&amp;lt;AppUser&amp;gt; getALlUsers() {
        return appUserRepository.findAll();
    }


    public AppUser getUser(int id) throws UserNotFoundException {
        Optional&amp;lt;AppUser&amp;gt; optional = appUserRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        } else {
            throw new UserNotFoundException("user not found with id : " + id);
        }
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The AppUserController&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.bukhari.exceptionhandlingvalidation.controller;


import com.bukhari.exceptionhandlingvalidation.entity.AppUser;
import com.bukhari.exceptionhandlingvalidation.globalexception.UserNotFoundException;
import com.bukhari.exceptionhandlingvalidation.request.AppUserRequest;
import com.bukhari.exceptionhandlingvalidation.service.AppUserService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/users")
public class AppUserController {

    @Autowired
    private AppUserService appUserService;

    @PostMapping("/signup")
    public ResponseEntity&amp;lt;AppUser&amp;gt; saveUser(@RequestBody @Valid AppUserRequest userRequest){
        return new ResponseEntity&amp;lt;&amp;gt;(appUserService.saveUser(userRequest), HttpStatus.CREATED);
    }

    @GetMapping("/fetchAll")
    public ResponseEntity&amp;lt;List&amp;lt;AppUser&amp;gt;&amp;gt; getAllUsers(){
        return ResponseEntity.ok(appUserService.getALlUsers());
    }

    @GetMapping("/{id}")
    public ResponseEntity&amp;lt;AppUser&amp;gt; getUser(@PathVariable int id) throws UserNotFoundException {
        return ResponseEntity.ok(appUserService.getUser(id));
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;@Valid&lt;/code&gt; annotation is used to validate the payload &lt;/p&gt;

&lt;p&gt;PostMan Request and Response are given below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the data is not valid&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9zmaoe3fr9xmqjmtfcy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9zmaoe3fr9xmqjmtfcy.png" alt="Request and Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the User is not Found.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppvkj3d0tc8ik7kzt2s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppvkj3d0tc8ik7kzt2s4.png" alt="Request and Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope the Tutorial was helpful. You learnt something from it. If it was helpful make sure to follow and like.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>exceptionhandling</category>
      <category>validation</category>
      <category>java</category>
    </item>
  </channel>
</rss>
