Results 1 to 6 of 6

Thread: one 404 error page per dispatcherservlet

  1. #1
    Join Date
    Jun 2009
    Posts
    25

    Default 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 :



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



    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 at 06:08 AM.

  2. #2
    Join Date
    Mar 2012
    Posts
    25

    Default

    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;
    }

  3. #3
    Join Date
    Jun 2009
    Posts
    25

    Default

    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 at 09:20 AM.

  4. #4
    Join Date
    Mar 2012
    Posts
    25

    Default

    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

  5. #5
    Join Date
    Jun 2009
    Posts
    25

    Default

    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 :\

  6. #6
    Join Date
    Jun 2009
    Posts
    25

    Default

    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 at 04:06 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •