Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent stack trace logging for custom exception in Spring Boot application

Is there a way in Spring Boot (MVC) to log a custom exception and throw it without its stack trace being visible in the log file? But for any other exception still see the stack trace.

Long explanation:

I am using spring boot to create a simple rest service. I like that for a custom exceptions there is no stack trace in the logs by default and JSON response is created with the basic exception details (status, error, message).

The problem is that it also creates no log entry at all, therefore I would have to do this manually:

Custom Exception

@ResponseStatus(value = HttpStatus.CONFLICT)
public class DuplicateFoundException extends RuntimeException {
    public DuplicateFoundException(String message) {
        super(message);
    }
}

Exception throwing in service method (in @RestController)

if (!voteDao.findByItemAndUser(item, voteDto.getUserId()).isEmpty()) {
    log.warn("... already voted ...");   //TODO: don't do this for every throw
    throw new DuplicateFoundException("... already voted ...");
}

Having more exceptions leads to placing log statement before each throw, which is a bad approach I think. I've tried removing all the log statements from the service method and created @ControllerAdvice where I would log all the custom exceptions and just re-throw them so I still get the nice JSON as before:

@ControllerAdvice
public class RestExceptionHandler {
    private static final Logger log = Logger.getLogger(RestExceptionHandler.class);

    @ExceptionHandler
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
            log.warn(e.getMessage());
        } else {
            log.error("...");
        }
        throw e;
    }
}

Now the problem is that I see not just the log entry, but also the stack trace for custom exceptions and can't find a way how to prevent this. I think the problem is caused by throwing it again. A possible solution could be to create a custom class for exception which I will return instead, but I dislike the idea since exception marshalling seems to work fine.

Any hints?

like image 328
rhorvath Avatar asked Jul 06 '15 16:07

rhorvath


People also ask

How does spring boot handle custom exceptions?

The @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client. Define a class that extends the RuntimeException class. You can define the @ExceptionHandler method to handle the exceptions as shown.

Should stack traces be logged?

Therefore, you should log a stacktrace if, and only if, and always if, the exception indicates a bug in the program. However, that does not always indicate that a method you write should catch and log the exception.

How do you handle exceptions in spring boot Microservices?

Using Spring Boot @ExceptionHandler Annotation: @ExceptionHandler annotation provided by Spring Boot can be used to handle exceptions in particular Handler classes or Handler methods. Any method annotated with this is automatically recognized by Spring Configuration as an Exception Handler Method.

What is stack trace in exception?

A trace of the method calls is called a stack trace. The stack trace listing provides a way to follow the call stack to the line number in the method where the exception occurs. The StackTrace property returns the frames of the call stack that originate at the location where the exception was thrown.


3 Answers

I'm using Spring Boot 2+ just add this line to your application.properties:

server.error.include-stacktrace=never

https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/web/ErrorProperties.IncludeStacktrace.html

like image 96
Carlos Negron Avatar answered Sep 18 '22 14:09

Carlos Negron


Be wary of Spring Boot DevTools.

Despite NEVER being the default for server.error.include-stacktrace, if you include Spring Boot DevTools it overides to ALWAYS.

If you're interested in more detail, see this commit, which became part of Spring Boot 2.1.0+ enter image description here

like image 32
muttonUp Avatar answered Sep 22 '22 14:09

muttonUp


If you don't need the stack trace you can suppress the stack trace by overriding fillInStackTrace in your exception class.

public class DuplicateFoundException extends RuntimeException {
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}

When you invoke e.printStackTrace() then no stack trace will be printed.

See also this blog post.

like image 40
Roland Weisleder Avatar answered Sep 22 '22 14:09

Roland Weisleder