views:

40

answers:

4

I have been thinking, how is it possible for me to send an email when a particular HTTP Error code happens in my Spring MVC Web app. Please take a look at my web.xml configuration. It works fine and redirects me to the particular error page.

<web-app ...>
  <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
  </servlet-mapping>

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

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

</web-app>

But what I want is, I want to send email or logged the occurence of this particular error. I was told in my earlier question that this type of error does not get handled by my controller hierarchy.

Any thoughts please?

A: 

For 4nn (client side) errors, your best bet is to configure the access logs at servletcontainer level. In case of Tomcat, you can do this in flavor of a Valve. It's more or less a kind of Filter which is to be plugged at servletcontainer level rather than at webapp level. You can find more detail in the Apache Tomcat Configuration Reference. You'll need to turn on and configure the Access Log Valve. This will only write to a logfile, but you can just extend org.apache.catalina.valves.AccessLogValve and add some code which sends a mail in case of a 404. To get it to run, just put that class in Tomcat's classpath and specify it as className in Valve configuration.

For 5nn (server side) errors, you can create and put a Filter on an url-pattern of /* which does basically the following in doFilter() method.

try {
    chain.doFilter(request, response);
} catch (ServletException e) {
    mail(e);
    throw e;
} catch (IOException e) {
    mail(e);
    throw e;
}
BalusC
A: 

Sending email on Http Error Code might be too late in the process to find why the error happened. A better thing to do for us was sending emails on exceptions. We might not want to do that for every exception, as that would be overwhelming.

To do this we extend SimpleMappingExceptionResolver. This Resolver is then required to be initialized with the context.

MyExceptionResolver extends SimpleMappingExceptionResolver
{
    @Autowire
    MailService mailService;

    protected ModelAndView getModelAndView(String viewName, Exception ex, HttpServletRequest request)
    {
       //Depending on exception resolve to view name, either 404 or server crash report

       //Also send emails for specific exception types.
    } 
}

 Spring wiring:
 <bean class="x.y.z.MyExceptionResolver"/>

Also, we can do exception handling with aspects. You can look up the aspects documentation for this.

Spring Monkey
A: 

When using the web.xml, Spring will not be first in line for a request (also depending on your <url-pattern>s).

What you can do is write a custom servlet that extends HTTPServlet.

In that servlet you can write the code for sending the email in the doGet() method that you over-ride from HttpServlet.

Edit your web.xml <url-pattern> to go to that servlet when the error occurs.

If its a error code 404, you know already that the problem relates to a page not found.

Cool.

Koekiebox
A: 

Hi,

For some reason, I did something like this. It works as for my case. Can you comment on what I did? In my web.xml, I edited my location tag to forward it to my controller.

 <!-- Error Pages -->
    <error-page>
        <error-code>404</error-code>
        <location>/errorEncountered.htm</location>
    </error-page>

    <error-page>
        <error-code>500</error-code>
        <location>/errorEncountered.htm</location>
    </error-page>

In My controller, this is where I send an email.

@Controller
@RequestMapping("/errorEncountered.htm")
public class ErrorHandlerController {
    private MailService mailService;

    @RequestMapping(method = RequestMethod.GET)
    public String handleGet(HttpServletRequest request) {
            // The Servlet spec guarantees this attribute will be available
            Throwable exception = (Throwable) request
                    .getAttribute("javax.servlet.error.exception");

            .
            .
            .
            mailService.sendMail();
        }
    }
}

Any criticism?

Mark Estrada