views:

494

answers:

4

Hi, I am currently building an application using Tomcat, Spring, JAVA. I am using Log4J as my logging library. I currently am logging everything to a text file. One of the issues I'm having is that RuntimeExceptions are not being logged to any files. I was wondering if there was a way to log all RuntimeExceptions that maybe thrown to my application log file. If not is it possible to have it log to another log file? Is there a standard way to do this? If so is there a standard way to do this when running your application within Tomcat?

Thank you in advance for your help!

A: 

You can try redirecting the StdErr to use your logger. This should output the result of anything being written to your std err (which should include unhandled exceptions)

This blog post gives a good rundown on how to do the redirection into a FileHandler that is apart of your logger.

http://blogs.sun.com/nickstephen/entry/java_redirecting_system_out_and

Jason D.
A: 

It is possible,

All your exception must be caught like this. Catch Exception if you want to catch RuntimeException.

// Logger instantiation
private static final Logger logger = Logger.getLogger(MyClass.class); 
try {


} catch (Exception e) {
  //Log all exceptions
  logger.error("My exception message", e);
}

Why? Because RuntimeException extends Exception.

Full reason:

Types of Exception

Exception come is several flavours: RuntimeExceptions, Errors, Checked and Unchecked.

If you catch RuntimeException you will catch all manner of run time exceptions (type R).
If you catch Error you will catch all manner of errors (type E).
If you catch Exception you will catch all manner of checked exceptions and run time exceptions (type R+C).
If you catch Throwable, you will catch everything, (Type R+E+C );

In essence, if you want to catch and log everything do catch(Throwable t) {logger.error("my throwable" , t);}

Source: http://mindprod.com/jgloss/exception.html#TYPES

The Elite Gentleman
This is nonsense. If you only want / need to catch RuntimeExceptions, you can `catch(RuntimeException ex) { ... }`
Stephen C
@Stephen C, check my edited post....
The Elite Gentleman
+3  A: 

One way to log uncaught RuntimeExceptions (or any uncaught Throwables for that matter) is to create a class that implements Thread.UncaughtExceptionHandler. This class's uncaughtException() method would simply write the exception details to the log. You can make the JVM call this exception handler whenever an uncaught RuntimeException terminates a thread by adding the line

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());

to your code.

Pourquoi Litytestdata
+3  A: 

I'm not sure if this is what you are looking for, but there is a handler for exceptions that terminate threads. It is a handler for any exception that is not caught explicitly by the target of the thread.

The default "uncaught exception handler" simply calls printStackTrace() on the Throwable to print the stack trace to System.err. However, you could replace this with your own UncaughtExceptionHandler that logs the exception to log4j instead:

class Log4jBackstop implements Thread.UncaughtExceptionHandler {

  private static Logger log = Logger.getLogger(Log4jBackstop.class);

  public void uncaughtException(Thread t, Throwable ex) {
    log.error("Uncaught exception in thread: " + t.getName(), ex);
  }

}

If you are using an executor framework to which you pass a Runnable object, its threads probably have their own catch block that prevent exceptions from reaching the uncaught exception handler. If you want to catch Runtime exceptions there, one way to do it is to wrap each task in a logging wrapper, like this:

class Log4jWrapper {

  private static final Logger log = Logger.getLogger(Log4jWrapper.class);

  private final Runnable target;

  Log4jWrapper(Runnable target) { this.target = target; }

  public void run() {
    try {
      target.run();
    } catch(RuntimeException ex) {
      log.error("Uncaught exception.", ex);
      throw ex;
    }
  }

}

...

Runnable realTask = ...;
executor.submit(new Log4jWrapper(realTask));
erickson
Is this normally how this RuntimeExceptions are handled in applications? I guess I'm wondering if this is a standard way of dealing with this.
DkS
Also I'm using ThreadPoolTaskExecutor from the Spring API, is this still something that can be done using this class?
DkS
This works great if there is a RuntimeException on the Runnable, however what if there is an Exception with the ThreadPoolTaskExecutor? Say it throws a RunTimeException because the Pool was configured in correct....this will still print to the console and not be logged....any suggestions?
DkS
You might need both, the `UncaughtExceptionHandler` and the `Runnable` wrapper. The uncaught exception handler would be set on the application thread that is creating and initializing the executor, and submitting the task for execution. The wrapper is used on the tasks that are submitted. Spring has stupidly confused runtime exceptions with checked exceptions, so a solution that helps it out of that mess may not be pretty.
erickson