Announcement Announcement Module
Collapse
No announcement yet.
one 404 error page per dispatcherservlet Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • one 404 error page per dispatcherservlet

    hi,

    i'm facing the following issue : i have several dispatcher servlets in the same web application, and i would like to deliver a specific 404 error page for each dispatcher servlet

    Let's say i have the following dispatcher servlets defined inside my web.xml configuration file :


    HTML Code:
    <servlet>
    	<servlet-name>dispatcher1</servlet-name>
    	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    	<init-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/configuration/dispatcher1.xml</param-value>
    	</init-param>
    	<load-on-startup>1</load-on-startup>
    </servlet>
    	
    <servlet>
    	<servlet-name>dispatcher2</servlet-name>
    	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    	<init-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/configuration/dispatcher2.xml</param-value>
    	</init-param>
    	<load-on-startup>1</load-on-startup>
    </servlet>
    	
    <servlet-mapping>
    	<servlet-name>dispatcher1</servlet-name>
    	<url-pattern>/dispatcher1/*</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
    	<servlet-name>dispatcher2</servlet-name>
    	<url-pattern>/dispatcher2/*</url-pattern>
    </servlet-mapping>
    Now, suppose i try to access the following url :
    http://.../dispatcher1/pathNotMappedByAController

    dispatcher1 would return his own 404 error page (let's call it 404-dispatcher1.jsp), whereas if i try to access this url:
    http://.../dispatcher2/pathNotMappedByAController

    dispatcher2 would return 404-dispatcher2.jsp


    Usually, when it comes to error mapping by code, one would have to do it inside the web.xml, this way:

    HTML Code:
    <error-page>
    	<error-code>404</error-code>
    	<location>/WEB-INF/jsp/errors/404.jsp</location>
    </error-page>

    The problem is that i can only define one 404 error page inside that tag, when i need at least 2 different pages depending on the "context" (dispatcher1 / dispatcher2) requested.

    I tried to extend DispatcherServlet and override its "noHandlerFound" method to deliver the appropriate 404 page based on the dispatcher servlet handling the request, which worked to some extent. But i'm not really satisfied with this approach since i would also like to map several other error codes like 302, 303,404, 405, 406, and i don't know how to do that with the class extension approach...

    According to me, the solution would be to be able to map the 404 <location> path once inside every dispatcher servlet (through one of its controllers) but i couldn't manage to do that : i only succeeded in mapping it to a single dispatcher servlet, like this:

    HTML Code:
    <error-page>
    	<error-code>404</error-code>
    	<location>/dispatcher1/404</location>
    </error-page>
    Code:
    // controller managed by spring dispatcher1's context
    @Controller
    public class HTTPErrorController {
    
        @RequestMapping(value="/404")
        public String handle404() {
            return "404-dispatcher1.jsp";
        }
    
    }
    anyone can help me on this one? thanks a lot!
    Last edited by calvino_ind; Apr 5th, 2012, 06:08 AM.

  • #2
    You woldnt define a 404 in web.xml for what you are trying to achieve. the 404 is the global, dispatcher independent.

    To do what you want, that is override the default 404 when one of your dispatcher servlets are hit, you need to add a SimpleMappingHandlerExceptionResolver in your dispatcher config file...

    See:
    http://stackoverflow.com/questions/1...11868#10011868

    Instead of xml you could also use the annotation:

    @ExceptionHandler(Throwable.class)
    public ModelAndView exceptionOccurred(Throwable exception, HttpServletResponse response, HttpServletRequest request) {
    ModelAndView mv = new ModelAndView();
    mv.setViewName ( exceptionOccurredView );
    mv.addObject ( "requestedUrl", Core.getCurrentUrlWithParams() );
    mv.addObject ( "exception", exception );

    System.out.println( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + Core.getCurrentUrlWithParams() );
    return mv;
    }

    Comment


    • #3
      hi, Hamidam, and thanks for your answer

      i looked into the exception resolver solution but i'm not sure it fits my requirements. It allows to have a specific exception resolver per dispatcher servlet which is a nice thing but the problem is : how can i match an error code to its related exception ? how do i know the exception thrown when the error is 403, 404, 405, and so on?

      For example, if i want to tell my exception resolver "when the error code is 404, show 404.jsp", how can i do that ? From what i understand, there is simply no exception when a 404 error occurs, this case is handled by the "noHandlerFound" method of the dispatcher servlet

      the problem with the exception resolver is that it's "exception based", not "error code based", when i specifically need an "error code based" view resolution
      Last edited by calvino_ind; Apr 5th, 2012, 09:20 AM.

      Comment


      • #4
        You can configure one for each exception type for that code:


        Exception HTTP Status Code
        ConversionNotSupportedException 500 (Internal Server Error)
        HttpMediaTypeNotAcceptableException 406 (Not Acceptable)
        HttpMediaTypeNotSupportedException 415 (Unsupported Media Type)
        HttpMessageNotReadableException 400 (Bad Request)
        HttpMessageNotWritableException 500 (Internal Server Error)
        HttpRequestMethodNotSupportedException 405 (Method Not Allowed)
        MissingServletRequestParameterException 400 (Bad Request)
        NoSuchRequestHandlingMethodException 404 (Not Found)
        TypeMismatchException 400 (Bad Request)


        See 16.11 Handling exceptions:

        http://static.springsource.org/sprin.../html/mvc.html

        Comment


        • #5
          that was exactly the kind of table i was looking for and the DefaultHandlerExceptionResolver class makes possible to do what i want

          the only problem left is that it seems this class appeared in spring 3. I'm using spring 2.5.6 and i can't do much about that (customer requirement). Do you know about a similar way to do it in spring 2.5.6 ?

          I tried to do create my own implementation of SimpleMappingExceptionResolver and to override the following methods:

          Code:
          public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
          	System.out.println("hi! " + ex.getClass().getSimpleName());
          	return super.resolveException(request, response, handler, ex);
          }
          i then declared a bean for that class in my application context and call a path that isn't mapped

          if i understand correctly the logic behind the exception resolution process, i should receive a print like this in the console:

          hi! NoSuchRequestHandlingMethodException
          unfortunately, i didn't receive any and i gotthe standard 404 page defined inside web.xml :\

          Comment


          • #6
            if anyone faces the same problem and wants to know the solution i opted for, i finally ended up doing the following:

            web.xml

            HTML Code:
            <error-page>
            	<error-code>404</error-code>
            	<location>/WEB-INF/jsp/errors/404.jsp</location>
            </error-page>
            404.jsp

            Code:
            <%
            	String path = ((String) request.getAttribute("javax.servlet.forward.servlet_path")).substring(1);
            	String applicationContextId = path.contains("/") ? path.substring(0, path.indexOf("/")) : path;
            	String applicationContextSpecific404Path = "/" + applicationContextId + "/404";	
            	String applicationContextSpecific404Url = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + applicationContextSpecific404Path;
                    if (/* applicationContextSpecific404Url is reachable */)
            		pageContext.forward(applicationContextSpecific404Path);
            %>
            
            <!-- Default 404 content, when the application context doesn't define its own 404 error page -->

            though it's certainly not the most elegant and performant solution, its benefit is that i can easily extend the same logic to the other error codes (400, 405, 406, ...) by adding the appropriate tags inside web.xml and mapping to jsp similar to the one above

            thanks again Hamidam, your answer was still useful, especially for spring 3 users
            Last edited by calvino_ind; Apr 5th, 2012, 04:06 PM.

            Comment

            Working...
            X