Furthermore, there is BaseControllerAdvice, which is annotated with @ControllerAdvice as follows. ControllerAdvice is a specialized component that can handle the @ExceptionHandler, @InitBinder, and @ModelAttribute methods:
@ControllerAdvice
public class BaseControllerAdvice {
private final UserService userService;
public BaseControllerAdvice(UserService userService) {
this.userService = userService;
}
@ExceptionHandler(NotFoundException.class)
public String handledNotFoundException(NotFoundException e, Model
model) {
model.addAttribute("status", 400);
model.addAttribute("exception", e);
return "common/error";
}
The BaseControllerAdvice.handleNotFoundException method that is annotated with @ExceptionHandler will catch NotFoundException, which is as follows:
public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
public NotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
It will set the model properties status, exception and will eventually forward to the common/error.ftl page:
@ExceptionHandler(Exception.class)
public String handleException(Exception e, Model model) {
model.addAttribute("status", 500);
model.addAttribute("exception", e);
return "common/error";
}
Also, it has the handleException method to catch and handle all other Exception types, and to forward to common/error.ftl:
@ModelAttribute
public void addCommonAttributes(@AuthenticationPrincipal
UserDetails userDetails, Model model) {
if (userDetails != null) {
User user =
userService.getByUsername(userDetails.getUsername());
model.addAttribute("user", user);
}
}
}
Additionally, it has the addCommonAttributes method to add any common Model attributes, which needs to be sent as part of all controller returns. In this case, we send an @Model attribute user so that the logged-in username can be shown in the header. @ModelAttribute is invoked whenever there is a GET request to a controller.