- Certain Spring exceptions are automatically mapped to specific HTTP status codes.
- An exception can be annotated with @ResponseStatus to map it to an HTTP status code.
- A method can be annotated with @ExceptionHandler to handle the exception.
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.
- Spring MVC Web Tutorial
- Spring MVC Interview Questions
- MVC Design Pattern
- Spring MVC DispatcherServlet
- Spring MVC WebApplicationContext and Root Application Context
- Spring MVC @Controller Annotation
- Spring MVC @RequestMapping Annotation
- Spring MVC @RequestParam Annotation
- Spring MVC @ModelAttribute Annotation
- Spring MVC ContextLoaderListener
- Spring MVC @RequestParam and @PathVariable annotations
- Spring MVC InternalResourceViewResolver
- Spring MVC Hello World Example
- Spring MVC with Hibernate CRUD Example
- Spring MVC Tiles Plugin with Example
- Spring MVC Interceptor with example
- Spring MVC with MongoDB CRUD Example
- Spring MVC Internationalization & Localization with Example