Java – Is Logging an Exception Message and Throwing a Different Exception an Antipattern?

anti-patternsjava

Our webapplication is using an ExceptionMapper to map some exceptions to Response. We log the exception messages before throwing a new exception as follows:

catch (SomeException ex) {
  LOG.error(ex.getMessage());
  throw new MyException(ex.getMessage());
}

We are not re-throwing the same exception, so my question is if this would be considered a Log and Throw antipattern. And thus, would it be better to remove the logging in similar places and move them to the several ExceptionMapper classes as follows:

@Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {

  // bla bla 

  @Override
  public Response toResponse(final MyException ex) {
    LOG.error(ex.getMessage());
    return Response.status(400).entity("something").build();
  }
}

Best Answer

Your code actually sports not one, but three antipatterns:

  1. log and rethrow;
  2. rethrow without wrapping the original cause;
  3. log only the message and not the stacktrace (this is the worst one).

If you followed the best practice to:

  1. not catch at all (let the exception propagate on its own);
  2. if forced to catch a checked exception, wrap into unchecked and rethrow;
  3. never log anything except at the top level;
  4. log the entire exception stacktrace with log.error("Error occurred", e);

then you would not face any dilemmas, including your current one, because the logged stacktrace would include all the wrapped exceptions as well.