James Raitsev
James Raitsev

Reputation: 96471

Throwing and logging Exceptions, a better way

Ultimately, i'd like to

if (badThingsHappen) {
 log the issue
 throw exception with description
}

The obvious redundancy here is that often exception description and the message to be logged is (often) the same.

This looks needlessly verbose

if (badThingsHappen) {
 logger.error("oh no! not again!");
 throw new AppException("oh no! not again!");
}

Declaring temporary String feels wrong

if (badThingsHappen) {
 String m = "oh no! not again!";
 logger.error(m);
 throw new AppException(m);
}

Is it ok to have Exception's constructor handle the logging? Is there a better (cleaner) way?

Upvotes: 8

Views: 5240

Answers (4)

Jouni Aro
Jouni Aro

Reputation: 2139

I just wrote an error-logging method myself, today (this is used to log errors if they occur in a listener method, so it's also logging the method in which the error occurred and the object in which the listener is implemented to help tracking):

protected void listenerError(String listenerMethodName, Object listener,
        RuntimeException e) {
    logger.error("Exception while calling " + listenerMethodName
            + " on object " + listener, e);
    throw e;

}

I wrote it in the class in question (or the base class, to be exact), because you probably want to use the logger in that class (and all subclasses). Another option would be to create a utility method in a utility class (I would not write an Exception class for it), and provide the logger as parameter:

class ExceptionUtil {

  public static error(Exception e, Logger logger) {
     logger.error(e);
     throw e;
  }
}

You can, of course, provide the method and object as params for this method (or an overloaded version of it), as necessary.

Upvotes: 1

Thomas Mueller
Thomas Mueller

Reputation: 50127

You could use a utility method:

public class AppException extends Exception {
    public static AppException logAndThrow(Logger logger, String message) throws AppException {
        AppException e = new AppException(message);
        // log the stack trace as well
        logger.error(message, e);
        throw e;
    }
}

and the use it:

if (badThingsHappen) {
    AppException.logAndThrow(logger, "oh no! not again!");
}

Upvotes: 3

lukecampbell
lukecampbell

Reputation: 15256

Typically when working with Exceptions and logging requirements I include logging support in the Exceptions.

Exceptions typically inherit from a Base Exception class in our project and it has hooks for logging log4j or other logging utilities.

class Problem extends java.lang.Exception {
  private boolean debug=false;
  public Problem(String message) {
    if(debug) {
      logging.exception(message);
      /* Maybe a stack trace? */
    }
  }
}

Upvotes: 1

pcalcao
pcalcao

Reputation: 15990

I usually prefer to log exceptions when I catch them, rather then when I throw them.

This cleans up the logs quite a bit more, and also lets the "client" code handle the exception and information output much more precisely, since the information you want to associate with the exception when logging can be dependent of context.

If you do want to log as soon as it happens, I would build the exception and log it before throwing, something like:

if(badthingshappen){
    Exception e = new Exception("holy $%##");
    logger.log(e);
    throw e;
}

A bit verbose yes... but this is java.

Upvotes: 2

Related Questions