404—>Not Found–>NoSuchRequestHandlingMethodException etc.
400—>Bad Request–>BindException, HttpMessageNotReadableException etc.
406—>Not Acceptable–>HttpMediaTypeNotAcceptableException
415—>Unsuppported Media Type–>HttpMediaTypeNotSupportedException
405—>Method Not Allowed–>HttpRequestMethodNotSupportedException
500—>Internal Server Error–>HttpMessageNotWritableException
These above are usually thrown by Spring framework itself as the result of something went wrong in DispatcherServlet and failed any validations. For Example you want access any method in the controller which not mapped with any request then DispatcherServet through NoSuchRequestHandlingMethodException means 404 so resulting in a response with a status code of 404 (Not Found).
In Case of Custom Exception and Error Pages
1. Mapping Exception to HTTP Status Code
So above handling provided by spring is helpful but not more useful whenever we are taking about Custom Exception or Custom Error Pages so in this case we have to do something more better but don’t worry Spring offers a way to map exceptions to HTTP status codes via the @ResponseStatus annotation.
Suppose we are working with an application about Student Management for that we have an student controller with mapping to find student record from StudentRepository as follows
.
@Controller public class StudentController { @RequestMapping("/doj-student-{rollNumber}") public String dojStudentByRollNumber(ModelMap model, @PathVariable(value="rollNumber") String rollNumber){ Student student = StudentRepository.findStudentByRollNumber(rollNumber); String name = student.getFname()+" "+student.getLname()+" "+student.getAddress()+" "+student.getCourse(); model.put("name", name); return "home"; } }
As see in the above code when we are passing rollNumber to find a student from StudentRepository if for any rollNumber we got student then everything is fine in the application user get student detail as response. What happens when StudentRepository return null value for any rollNumber in this case user may got Internal Server Error i.e. 500 status code error.
For handling this scenario we have our custom exception StudentNotFoundException as follows.
package com.doj.spring.web.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Student Not Found") public class StudentNotFoundException extends RuntimeException{ /** * */ private static final long serialVersionUID = -2581975292273282583L; }
Here, a Student is retrieved by its rollNumber from the StudentRepository. If findStudentByRollNumber() returns a Student object, that Student is put into the model, and the view whose name is student is tasked with rendering it in the response. But if findStudentByRollNumber() returns null, then a StudentNotFoundException is thrown. For now, StudentController with StudentNotFoundException looks like this:
@Controller public class StudentController { @RequestMapping("/doj-student-{rollNumber}") public String dojStudentByRollNumber(ModelMap model, @PathVariable(value="rollNumber") String rollNumber){ Student student = StudentRepository.findStudentByRollNumber(rollNumber); if (student == null) { throw new StudentNotFoundException(); } String name = student.getFname()+" "+student.getLname()+" "+student.getAddress()+" "+student.getCourse(); model.put("name", name); return "home"; } }
After introducing this @ResponseStatus annotation, if a StudentNotFoundException were to be thrown from a controller method, the response would have a status code of 404 and a reason of Student Not Found.
2. ExceptionHandling methods
Mapping exceptions to status codes is simple and sufficient for many cases. But what if you want the response to carry more than just a status code that represents the error that occurred? Rather than treat the exception generically as some HTTP error, maybe you’d like to handle the exception the same way you might handle the request itself.
@Controller public class StudentController { @RequestMapping("/doj-student-{rollNumber}") public String dojStudentByRollNumber(ModelMap model, @PathVariable(value="rollNumber") String rollNumber){ Student student = StudentRepository.findStudentByRollNumber(rollNumber); if (student == null) { throw new StudentNotFoundException(); } String name = student.getFname()+" "+student.getLname()+" "+student.getAddress()+" "+student.getCourse(); model.put("name", name); return "home"; } @ExceptionHandler(StudentNotFoundException.class) public ModelAndView handleStudentNotFoundException(StudentNotFoundException ex) { Map<String, String> model = new HashMap<String, String>(); model.put("exception", ex.toString()); return new ModelAndView("student.error", model); } }
The @ExceptionHandler annotation has been applied to the handleStudentNotFoundException() method, designating it as the go-to method when a StudentNotFoundException is thrown. It returns a ModelAndView object, which, just as with the request-handling method, specifies with the logical name of the view to render, telling the user that student not found for this rollNumber.
If @ExceptionHandler methods can handle exceptions thrown from any handler method in the same controller class, you might be wondering if there’s a way they can handle exceptions thrown from handler methods in any controller.
Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…
Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…
Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…
Technology has emerged a lot in the last decade, and now we have artificial intelligence;…
Managing a database is becoming increasingly complex now due to the vast amount of data…
Overview In this article, we will explore Spring Scheduler how we could use it by…