22

I've set up web.xml as below. I also have an annotation-based controller, which takes in any URL pattern and then goes to the corresponding jsp (I've set that up in the -servlet.xml). However, If I go to a page that ends in .html (and whose jsp doesn't exist), I don't see the custom 404 page (and see the below error in the log). Any page that doesn't end in .html, I can see the custom 404 page.

How can I configure to have a custom 404 page for any page that goes through the DispatcherServlet?

Also want to add that if I set my error page to a static page (ie. error.htm) it works, but if I change it to a jsp (ie. error.jsp), I get the IllegalStateException. Any help would be appreciated.

log error

Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:606)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:195)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:124)

controller

@RequestMapping(value = {"/**"})

public ModelAndView test() {

    ModelAndView modelAndView = new ModelAndView();

    return modelAndView;
}

web.xml

<servlet>
 <servlet-name>my_servlet</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

...

<servlet-mapping>
    <servlet-name>my_servlet</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>

...

<error-page>
    <error-code>404</error-code>
    <location>/error.html</location>
</error-page>
njdeveloper
  • 1,465
  • 3
  • 13
  • 16

1 Answers1

34

One option is to map all your error pages through your dispatcher servlet.

Create a new HTTP error controller:


@Controller
public class HTTPErrorController {

    @RequestMapping(value="/errors/404.html")
    public String handle404() {
        return "errorPageTemplate";
    }

    @RequestMapping(value="/errors/403.html")
    ...

}

Map the error pages in web.xml

<error-page>
    <error-code>404</error-code>
    <location>/errors/404.html</location>
</error-page>
Rob Beardow
  • 871
  • 5
  • 6
  • @Stefan Haberl, why change @Rob's post rather than just post your simplified version as a new answer? – sarnold Apr 02 '11 at 09:08
  • 1
    Can anyone verify that this solution works? It doesn't for me (Spring 3.0.5) – Jason Jun 16 '11 at 06:08
  • This code example is almost verbatim from some of our applications and works as expected. What problem are you having? I can help debug. – Rob Beardow Jun 16 '11 at 23:51
  • Isn't it missing something? Why would the request to go /error/404.html? I get how the controller would fetch such a request, just not why the request would go there. – Andreas Wederbrand Nov 02 '11 at 10:03
  • 2
    @Andreas the request would go there because you are mapping it in web.xml at the servlet layer. The servlet will map your 404 to /errors/404.html and then the Spring Controller will be able to catch it up. The Controller knows nothing about it is a 404, only will get a matching request mapping, the servlet don't know it's pulling the error to Spring, just will redirect to a web address that happens to be mapped to a Spring controller. – iagorubio Nov 04 '12 at 21:06
  • 2
    I implemented this solution but it's resulting in errors in our log saying "No mapping found for URI..." – Larry Gerndt Dec 17 '12 at 22:41
  • Yeah, I have not been able to get this to work. I am implementing this in Broadleaf, an ecom stack built ontop of Spring MVC. Will post if I ever find the answer! – M.W. Felker Dec 08 '14 at 22:22