How to make invalid urls ending in .jsp use spring 404 page?

404 pages work correctly on my site for the entire URL, unless it ends in .jsp. In this case, I get a generic jboss 404 page instead of my styled Spring 404 page.

I have the following in my web.xml:

<error-page> <error-code>404</error-code> <location>/WEB-INF/error/404.jsp</location> </error-page> 

Edited with full web.xml:

 <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>mainServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mainServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/root-context.xml, /WEB-INF/spring-security.xml </param-value> </context-param> <welcome-file-list> <welcome-file></welcome-file> </welcome-file-list> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class> org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <error-page> <error-code>400</error-code> <location>/WEB-INF/error/400.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/WEB-INF/error/403.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/WEB-INF/error/404.jsp</location> </error-page> <error-page> <error-code>405</error-code> <location>/WEB-INF/error/405.jsp</location> </error-page> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/WEB-INF/error/error.jsp</location> </error-page> <context-param> <param-name>defaultHtmlEscape</param-name> <param-value>true</param-value> </context-param> </web-app> 
+6
source share
1 answer

Probably the problem is that your web.xml points directly to your jsp pages instead of pointing to the spring controller, which can then point to the corresponding view.

I would be curious to also see your rootContext.xml to find out how you configured your resolver. The reason may be that spring is getting confused ... There are only a few ways that the App Container (JBoss) will end the error handling, which means that either the request does not even match the spring servlet, or if there is no error handler for the type of error generated (possibly Is it that trying to process "asdlfasdf.jsp" leads to the fact that another type of exception is not logged, and then it is thrown to JBoss and processed as 404?).

But you have something that can be compared with - Here, as I have my setup:

I have one error.jsp page in my views directory and set up a view viewer similar to the following:

 <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean> 

Then I have the base class PageController, which I distribute to all my other user management classes. This class has a method that processes error page templates "/ error / 404", "/ error / 403":

 @RequestMapping(value = "/error/{code}") public String errorPage(Principal principal, Model model, @PathVariable("code") int code) { model.addAttribute("code", code); return "error"; } 

Then I set up a web.xml similar to yours, only redirecting the endpoints of the spring controller along with the corresponding code:

 <error-page> <error-code>404</error-code> <location>/error/404</location> </error-page> <error-page> <error-code>403</error-code> <location>/error/403</location> </error-page> 

Now I do not know if this is the best, but for me it is very good. The web container directs these types of errors to the / error / code page, which simply calls the controller method, and then the controller method creates the error.jsp page (returning the view name "error").

Since it puts the error code in the model, I have one jsp that handles several types of errors, I just put a condition that displays a different user message depending on the error code. In other words, "Page not found :(" "You are not authorized to view this page!"

And then I do this in my spring security configuration to make sure that an unverified user can see the error page (you probably already got this part, since you can see jsp pages):

 <http pattern="/error/**" security="none" /> 

I combine this with annotation-style exception handlers to do all of my server exception handling (handling data requests using json error response and html / view requests with html error pages) because you can just comment on the controller method to handle Exception or RuntimeException . I would recommend that you check this method because it is very powerful and greatly facilitates logging and exception handling gracefully:

 @ExceptionHandler(Exception.class) public ModelAndView exceptionHandler(Exception e){ ModelAndView modelAndView = new ModelAndView(); modelAndView.getModelMap().addAttribute("code", HttpStatus.INTERNAL_SERVER_ERROR); modelAndView.setViewName("error"); logger.error("Error handling page request.", e); return modelAndView; } 

This is also a good way to make sure that you have the ability to log exceptions passing through your controllers without having to insert exception handling into each individual.

I made two base classes: one for my page controllers and one for my quiescent data controllers. The base page controller returns a jsp view that displays a good error page for the user. The base remainder data controller returns a json message with information about errors in the model, and then jsp will print a full stack or just a general error, depending on whether the server is in development or production mode.

+3
source

Source: https://habr.com/ru/post/958676/


All Articles