Springs MVC. I am trying to catch 404 page errors but code is not getting coded - spring

Springs MVC. I am trying to catch 404 page errors but code is not getting coded. Am I missing something?
#ControllerAdvice
public class GeneralHandler
{
private static final Logger LOGGER = getLogger(GeneralHandler.class);
#ExceptionHandler
public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
LOGGER.warn(ex.toString());
return new ModelAndView("404");
}
}

It seems that it can't be done using #ExceptionHandler: https://stackoverflow.com/a/3230559/322166
Instead of that, you'll need to configure that behaviour in your web.xml:
<error-page>
<error-code>404</error-code>
<location>/your-error-page.html</location>
</error-page>

Related

How to configure Spring errror page in JSON format with web.xml and an error controller

With Spring 5, I am currently able to configure an error page in src/main/webapp/web.xml, i.e. the following configuration is added:
<error-page>
<location>/WEB-INF/error.html</location>
</error-page>
In this way, the error.html will be rendered when there is Exception in the controller. However, this error.html is in html format other than the expected JSON format.
I tried to make an error controller with some code like this:
#RestController
#RequestMapping(value = "/handler")
public class ErrorController {
#RequestMapping(value = "/errors")
public String renderErrorPage(HttpServletRequest httpRequest) {
System.out.println("DEBUG::come to error page");
return "test error";
}
}
In the same time configured error-page as such:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<error-page>
<location>/handler/errors</location>
</error-page>
But the ErrorController cannot be invoked.
Question: How to configure Spring error page in JSON format with web.xml and an error controller?
I eventually realized that the servlats are filtered with /rest/* through the servlet-mapping tag, so the location of the error-page has to be prefixed with /rest, meaning the error-page tag should be configured as such:
<error-page>
<location>/rest/errors</location>
</error-page>
Correspondingly the controller can be configured like:
#RestController
//#RequestMapping(value = "/handler")
public class ErrorController {
#RequestMapping(value = "/errors")
public String renderErrorPage(HttpServletRequest httpRequest) {
System.out.println("DEBUG::come to error page");
return "test error";
}
}

How exactly work the HandlerExceptionResolver interface in Spring? Can I show an error page when the user try to access to a not mapped resource?

I am studying how to handle custom exception in Spring on a tutorial that show me this class named ExceptionHandler that implement the HandlerExceptionResolver Spring interface:
#Component
public class ExceptionHandler implements HandlerExceptionResolver {
private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);
#Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) {
System.out.println("Spring MVC Exception Handling");
logger.error("Error: ", exception);
return new ModelAndView("error/exception","exception","ExceptionHandler message: " + exception.toString());
}
}
And then, into a controller class of the example, it throws this exception in this way:
#RequestMapping(value="/throwRunTimeException", method=RequestMethod.GET)
public void throwException() {
throw new RuntimeException();
}
So I have some doubts about how exactly do this class.
I can't understand if implementing the HandlerExceptionResolver interface I am declaring a new specific exception type or if simply specify a specific behavior that happens when a generic runtime exception is thrown.
It seems me the second situation...I think that, in the previous example, when a generic RuntimeException is thrown it return an exception.jsp page (and the related message that have to be shown into the model object).
So, if the previous assertion is true, can I use this method for the following pourpose?
I think that when a user try to open an URL that is it not mapped to any controller method a RuntimeException is thrown.
So, into the **resolveException()** method, can I extract the required URL from the HttpServletRequest request input parameter and use it to show a specific error message (that indicate that this URL not exist) into the returned view?
I don't think that is possible. When the DispatcherServlet can't find the url mapped in one of your controllers, it will throw a NoHandlerFoundException. This will then be forwarded to your servlet container like Tomcat which handles the error and shows the 404 page for example. You can change this behaviour by adding the following to your web.xml:
`
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/404error.jsp</location>
</error-page>
`
Note that it's not possible yet to configure this in JavaConfig.
For other Exceptions that are thrown you can use the HandlerExceptionResolver to return the desired view.
You could also use the #ExceptionHandler annotation on a method in your controller to catch the exceptions and handle them appropriately. This can be combined with the #ControllerAdvice annotation to enable this for every controller.

Define customized error pages with Spring

Using Spring with java configuration only, is possible define something similar to
<error-page>
<error-code>404</error-code>
<location>/notfound</location>
</error-page>
fragment of web.xml ?
You'll need to define an error page at servlet container level, which forwards to your custom controller.
#Component
public class CustomizationBean implements EmbeddedServletContainerCustomizer {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error"));
}
}

How does spring handle exceptions in MVC

Spring MVC exception handle
In my opinion there are different kinds of exceptions in a Spring MVC application.
For example, the service or dao layer may throw exceptions once errors occured. Or the spring itself may throw exceptions if it can not find a right handler to handle the request.
And now I try to use the ControllerAdvice to handle the exceptions:
#ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
#ExceptionHandler(Exception.class)
public ModelAndView myError(Exception exception) {
log.error(exception.getMessage());
ModelAndView mav = new ModelAndView();
mav.addObject("exception", exception);
mav.setViewName("error");
return mav;
}
}
However once I visit a wrong page, I will get the 404 error page from tomcat, rather than the error view defined in the ControllerAdvice.
So how did spring handle the exceptions?
I Think you rather put the error page in Web.xml, whenever you will visit the wrong page it will be redirected to this error page. Also this is less cumbersome and easy to manage.
Does this answers your question

How to globally handle 404 exception by returning a customized error page in Spring MVC?

I need to return a customized error page for HTTP 404, but the code does not work. I already read the stackflow 1,2, 3 and different online + articles but my case is quite different with those or at least I can not figure out the issue.
HTTP Status 404 -
type Status report
message
description The requested resource is not available.
For example, it is suggested to use an action name in web.xml to handle the exception, it might work but I think is not a good method of doing it.
I used following combinations:
1)
#Controller //for class
#ResponseStatus(value = HttpStatus.NOT_FOUND) //for method
2)
#Controller //for class
#ResponseStatus(value = HttpStatus.NOT_FOUND) //for method
#ExceptionHandler(ResourceNotFoundException.class) //for method
3)
#ControllerAdvice //for class
#ResponseStatus(value = HttpStatus.NOT_FOUND) //for method
3)
#ControllerAdvice //for class
#ResponseStatus(HttpStatus.NOT_FOUND) //for method
4)
#ControllerAdvice //for class
#ResponseStatus(value = HttpStatus.NOT_FOUND) //for method
#ExceptionHandler(ResourceNotFoundException.class) //for method
Code
#ControllerAdvice
public class GlobalExceptionHandler {
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public String handleBadRequest(Exception exception) {
return "error404";
}
}
DispatcherServlet does not throw an exception by default, if it does not find the handler to process the request. So you need to explicitly activate it as below:
In web.xml:
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
If you are using annotation based configuration:
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
In the controller advice class:
#ExceptionHandler
#ResponseStatus(HttpStatus.NOT_FOUND)
public String handleExceptiond(NoHandlerFoundException ex) {
return "errorPage";
}
You can use the #ResponseStatus annotation at the class level. At least it works for me.
#Controller
#ResponseStatus(value=HttpStatus.NOT_FOUND)
public class GlobalExceptionHandler {
....
}
You can add the following in your web.xml to display an error page on 404. It will display 404.jsp page in views folder inside WEB-INF folder.
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/404.jsp</location>
</error-page>

Resources