~~ Spring Boot ~~

 1. Introduction

    1.1 Spring Boot-Intorduction
    1.2 Spring Boot-Architecture
    1.2 Spring Boot-Quick Start

 2. Project Creation

    2.1 Spring Initializer
    2.2 Spring Boot CLI
    2.3 STS IDE
    2.4 Eclipse IDE
    2.5 First Program
    2.6 Spring Boot-Code Structure

 3. Spring Boot – Beans & DI
 4. Spring Boot – Runners
 5. Spring Boot – Properties File
 6. Spring Boot – Looging
 7. Spring Boot – Rest WebServices
 8. Spring Boot – Exception Handling
 9. Spring Boot – Interceptor
 10. Spring Boot – Servlet Filter
 11. Spring Boot – Rest Template
 12. Spring Boot – File HANDLING
 13. Spring Boot – Thymeleaf
 14. Spring Boot – Internationalization
 15. Spring Boot – Scheduling
 16. Spring Boot – Actuator
 17. Spring Boot – Email Handling
 18. Spring Boot – Database Handling
 19. Spring Boot – Caching

Spring Boot | Exception Handling :

Whenever we are developing some project, it is very important in case of any error we are sending proper response to client. So that Client will know what was exact problem. So here we will discuss about how to implement these Errors and Exceptions in our Spring Boot Application. In Spring Boot, we can divide Exception Handling in 2 parts.
  1. Default Exception Handling
  2. Custom Exception Handling
We will see, both of them but before we Start we will know some important annotations. It will help us to handle Exceptions in Spring application.

@ControllerAdvice :

The @ControllerAdvice annotation help us to handle exceptions globally. Below is sample where we need to use this annotation.
@ControllerAdvice
public class CustomGlobalExceptionHandler{
}

@ExceptionHandler :

The @ExceptionHandle annotation help us to handle some specific type of exceptions and also it helps us to customize our exceptions. Below is sample where we need to use this annotation.
@ControllerAdvice
public class CustomGlobalExceptionHandler {
  @ExceptionHandler(value = BookNotFoundException.class) public ResponseEntity customHandleNotFound(Exception ex, WebRequest request) { // Here our coustome exception logic } }

Project Structure :

Below will be our Project Folder Structure.

1. Default Exception Handling :

In Spring Boot, we can see it automatically by-default handling some exceptions. All these default exceptions are handled by ErrorController.

For example, Suppose we are calling url – http://localhost:8081/getLibraryDetails

To get details about library. But our service is able to return only Book details not Library details. So, lets see what will happen.

NoLibraryAvailable_Exception

Here we can clearly see, by-default it’s handing that error and throwing some known Error. Where it’s saying “Not Found” with Status code “404”. But here we can handle this type of error and throw some more description error like “Library Details are not available”. We will see in next section how we can handle this type of error and thrown our own custom error.

2. Custom Exception Handling :

Now here we will create an application which will return Book details and if that book is not available then it will throw our own error message like “Book Not Found”.

package com.study4online;

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

@SpringBootApplication
public class ExceptionHandlingApplication {

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

}
package com.study4online.model;

public class Book {

private String bookId;
private String bookName;
private String bookDescription;

Book() {

}
public Book(String bookId, String bookName, String bookDescription) {
super();
this.bookId = bookId;
this.bookName = bookName;
this.bookDescription = bookDescription;
}

public String getBookId() {
return bookId;
}

public void setBookId(String bookId) {
this.bookId = bookId;
}

public String getBookName() {
return bookName;
}

public void setBookName(String bookName) {
this.bookName = bookName;
}

public String getBookDescription() {
return bookDescription;
}

public void setBookDescription(String bookDescription) {
this.bookDescription = bookDescription;
}

@Override
public String toString() {
return "Book [bookId=" + bookId + ", bookName=" + bookName + ", bookDescription=" + bookDescription + "]";
}

}
package com.study4online.controller;

import java.util.List;

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

import com.study4online.exception.BookNotFoundException;
import com.study4online.model.Book;
import com.study4online.service.BookService;

@RestController
public class BookController {

@Autowired
BookService bookService;

@RequestMapping(path = "/getBookDetails/{id}", method = RequestMethod.GET)
public List<Book> getBookDetails(@PathVariable String id) {

if (bookService.getBookDetails(id).isEmpty()) {
throw new BookNotFoundException(id);
} else {
return bookService.getBookDetails(id);
}
}

}
package com.study4online.service;

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

import org.springframework.stereotype.Service;
import com.study4online.model.Book;

@Service
public class BookService {

static List<Book> blist = new ArrayList<Book>();

static {
blist.add(new Book("Java", "Javabook", "Java Description"));
blist.add(new Book("Tibco", "Tibcobook", "Tibco Description"));
blist.add(new Book("Spring", "Springbook", "Spring Description"));
}

public List<Book> getBookDetails(String id) {
List<Book> ublist = new ArrayList<Book>();
for (Book b : blist) {
if (b.getBookId().equalsIgnoreCase(id)) {
ublist.add(b);
}
}

return ublist;
}

}
package com.study4online.exception;

public class BookNotFoundException extends RuntimeException {

private static final long serialVersionUID = 1L;

public BookNotFoundException(String id) {
super("Book id not found :" + id);
}

}

Here we can see in above screenshot, when we are searching for Hibernate book (which is not available). We are getting message as “Book id not found : Hibernet”.

If Book id is not available , it should return a 404 error code instead of 500. Now we will create an application which will override that Status and it will return 404. Here we will add “CustomGlobalExceptionHandler.java

package com.study4online;

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

@SpringBootApplication
public class ExceptionHandlingApplication {

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

}
package com.study4online.model;

public class Book {

private String bookId;
private String bookName;
private String bookDescription;

Book() {

}
public Book(String bookId, String bookName, String bookDescription) {
super();
this.bookId = bookId;
this.bookName = bookName;
this.bookDescription = bookDescription;
}

public String getBookId() {
return bookId;
}

public void setBookId(String bookId) {
this.bookId = bookId;
}

public String getBookName() {
return bookName;
}

public void setBookName(String bookName) {
this.bookName = bookName;
}

public String getBookDescription() {
return bookDescription;
}

public void setBookDescription(String bookDescription) {
this.bookDescription = bookDescription;
}

@Override
public String toString() {
return "Book [bookId=" + bookId + ", bookName=" + bookName + ", bookDescription=" + bookDescription + "]";
}

}
package com.study4online.controller;

import java.util.List;

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

import com.study4online.exception.BookNotFoundException;
import com.study4online.model.Book;
import com.study4online.service.BookService;

@RestController
public class BookController {

@Autowired
BookService bookService;

@RequestMapping(path = "/getBookDetails/{id}", method = RequestMethod.GET)
public List<Book> getBookDetails(@PathVariable String id) {

if (bookService.getBookDetails(id).isEmpty()) {
throw new BookNotFoundException(id);
} else {
return bookService.getBookDetails(id);
}
}

}
package com.study4online.service;

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

import org.springframework.stereotype.Service;
import com.study4online.model.Book;

@Service
public class BookService {

static List<Book> blist = new ArrayList<Book>();

static {
blist.add(new Book("Java", "Javabook", "Java Description"));
blist.add(new Book("Tibco", "Tibcobook", "Tibco Description"));
blist.add(new Book("Spring", "Springbook", "Spring Description"));
}

public List<Book> getBookDetails(String id) {
List<Book> ublist = new ArrayList<Book>();
for (Book b : blist) {
if (b.getBookId().equalsIgnoreCase(id)) {
ublist.add(b);
}
}

return ublist;
}

}
package com.study4online.exception;

public class BookNotFoundException extends RuntimeException {

private static final long serialVersionUID = 1L;

public BookNotFoundException(String id) {
super("Book id not found :" + id);
}

}
package com.study4online.exception;

import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

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

@ControllerAdvice
public class CustomGlobalExceptionHandler {

// Let Spring BasicErrorController handle the exception, we just override the status code
@ExceptionHandler(value = BookNotFoundException.class)
public void springHandleNotFound(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.NOT_FOUND.value());
}

}
Custom_ExceptionMsg2

Here we can see in above screenshot, if book is not available then it’s returing Status as 400 and our customize ErrorMessage also “Book id not found : Hibernate”.

Here we can customize the entire JSON Error message. We will see in below application. Here we will add “CustomErrorResponse.java” and update our exiting “CustomGlobalExceptionHandler.java”

package com.study4online;

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

@SpringBootApplication
public class ExceptionHandlingApplication {

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

}
package com.study4online.model;

public class Book {

private String bookId;
private String bookName;
private String bookDescription;

Book() {

}
public Book(String bookId, String bookName, String bookDescription) {
super();
this.bookId = bookId;
this.bookName = bookName;
this.bookDescription = bookDescription;
}

public String getBookId() {
return bookId;
}

public void setBookId(String bookId) {
this.bookId = bookId;
}

public String getBookName() {
return bookName;
}

public void setBookName(String bookName) {
this.bookName = bookName;
}

public String getBookDescription() {
return bookDescription;
}

public void setBookDescription(String bookDescription) {
this.bookDescription = bookDescription;
}

@Override
public String toString() {
return "Book [bookId=" + bookId + ", bookName=" + bookName + ", bookDescription=" + bookDescription + "]";
}

}
package com.study4online.controller;

import java.util.List;

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

import com.study4online.exception.BookNotFoundException;
import com.study4online.model.Book;
import com.study4online.service.BookService;

@RestController
public class BookController {

@Autowired
BookService bookService;

@RequestMapping(path = "/getBookDetails/{id}", method = RequestMethod.GET)
public List<Book> getBookDetails(@PathVariable String id) {

if (bookService.getBookDetails(id).isEmpty()) {
throw new BookNotFoundException(id);
} else {
return bookService.getBookDetails(id);
}
}

}
package com.study4online.service;

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

import org.springframework.stereotype.Service;
import com.study4online.model.Book;

@Service
public class BookService {

static List<Book> blist = new ArrayList<Book>();

static {
blist.add(new Book("Java", "Javabook", "Java Description"));
blist.add(new Book("Tibco", "Tibcobook", "Tibco Description"));
blist.add(new Book("Spring", "Springbook", "Spring Description"));
}

public List<Book> getBookDetails(String id) {
List<Book> ublist = new ArrayList<Book>();
for (Book b : blist) {
if (b.getBookId().equalsIgnoreCase(id)) {
ublist.add(b);
}
}

return ublist;
}

}
package com.study4online.exception;

public class BookNotFoundException extends RuntimeException {

private static final long serialVersionUID = 1L;

public BookNotFoundException(String id) {
super("Book id not found :" + id);
}

}
package com.study4online.exception;

import java.time.LocalDateTime;

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 org.springframework.web.context.request.WebRequest;

import com.study4online.model.CustomErrorResponse;

@ControllerAdvice
public class CustomGlobalExceptionHandler {

//Cutomize Entire json Error Response
@ExceptionHandler(value = BookNotFoundException.class)
public ResponseEntity<CustomErrorResponse> customHandleNotFound(Exception ex, WebRequest request) {
CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.NOT_FOUND.value());

return new ResponseEntity<>(errors, HttpStatus.NOT_FOUND);
}

}
package com.study4online.model;

import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonFormat;

public class CustomErrorResponse {

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
private int status;
private String error;

public LocalDateTime getTimestamp() {
return timestamp;
}

public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}

public int getStatus() {
return status;
}

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

public String getError() {
return error;
}

public void setError(String error) {
this.error = error;
}

}
Custome_ExceptionMsg3

Here we can see in above screenshot, we Customized whole JSON Error Response.