views:

240

answers:

2

When our application throws errors that we catch, we put the message and stacktrace in a log file created specifically for our application (myapp.log). For example:

public class SomeClass {
    OurLogger log = OurLogger.getLogger ("myapp", SomeClass.class);
    public void someMethod {
     try {
     //code
     }
     catch (DataAccessException e)
     {
      log.error(e.getMessage(), e);
     }
    }
}

We do this because since we are in a environment where multiple apps reside on an application server...ours and every other applications logs should be seperate from the server.log.

However, for some cases where we are not catching the error...the stack trace is being written on server.log In these cases also we would like to send stack errors to myapp.log. I know we can define an exception in web.xml and forward to a jsp page but is there a way, in this case, to not send the stack trace to server.log but instead to myapp.log? Other than catching the exception by code change of course.

A: 

The answer is appserver/webcontainer dependent. This goes beyond the Java EE specification. You need to consult the 'Logging' chapter of its documentation for details. Some may support the construct as you want, but others may not.

Best solution is to have a global exception handler, such as the <error-page> which you mentioned yourself. Let it listen on java.lang.Exception or maybe Throwable. Alternatively you can have (or reuse) a Filter which listens on /* and just put the chain.doFilter(request, response) inside a try-catch block on Exception or maybe Throwable.

Edit: here are some code examples as requested in the comments. First the Filter which listens on /*. The way I explained it before almost writes code itself:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    try {
        chain.doFilter(request, response);
    } catch (Exception e) {
        logger.error("Caught an uncaught exception.", e);
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        req.getRequestDispatcher("error.jsp").forward(req, res);
    }
}

Note that I would more recommend to put it in the "front controller" Servlet of your webapplication. I don't know if you're using any (it would have been too obvious to put it there, though) and I also don't know if you're using some existing framework which might already provide out-of-the-box solutions for this.

And the error-page, well, you can't go around an ugly scriptlet to log the exception.

<% logger.error("Caught an uncaught exception", exception); %>

Note that this still logs the exception to the server.log. At this point it's already too late to turn.

BalusC
If I add <error-page> in web.xml then logs get written to server.log. I am using GlassFish v2 by the way.
Omnipresent
I should have added, in the particular error page you have the possibility to log the exception yourselves. It is available in JSP page scope as implicit variable named `exception`.
BalusC
And, if you do **not** want to log to the `server.log`, then I would go ahead with the filter approach and call a forward to the error page in the catch block.
BalusC
thanks. I do not fully understand your filter approach. Could you point me to a link or show an example?
Omnipresent
in reply to your first comment. Yes exception variable would be available in the error.jsp page. You mean I should use that exception variable to log stacktrace to myapp.log?
Omnipresent
+1  A: 

However, for some cases where we are not catching the error...the stack trace is being written on server.log

To me, this is a normal behavior. Some exceptions, for example RuntimeException, are caught by the application server and logged in the app server log file (which is global to a domain with GlassFish). And you don't watch to catch them all, you want the container to do its job in such situation, for example rollbacking a transaction, or you'll get nasty bugs.

In these cases also we would like to send stack errors to myapp.log. I know we can define an exception in web.xml and forward to a jsp page but is there a way, in this case, to not send the stack trace to server.log but instead to myapp.log?

To my knowledge, this is not possible. And even if you add an <error-page>, it's still the app server that will catch the exception so this won't solve your "issue". And even if you use a servlet filter to catch Throwable (I wouldn't do that) and log it at the application level, you'll have to rethrow it to let the container do its job as I mentioned above. So it won't solve your "issue" entirely neither.

Other than catching the exception by code change of course.

Don't do that, you do not want to catch them all!

Pascal Thivent