Prevent stack trace logging for custom exception in Spring Boot application
Solution 1
Solution was to leave the exception handling to spring boot, so that custom exception is not logged and any other is logged by default. I removed the @ControllerAdvice and also the logging statements from the rest controller and added logging statement to custom exception constructor.
public DuplicateFoundException(String message) {
super(message);
LOGGER.warn(message);
}
I am not sure if this is the best approach, but now I have custom exception logging only at one place and don't have to repeat the log statement for every exception or see its stack trace or any other error message in the logs.
Solution 2
I'm using Spring Boot 2+ just add this line to your application.properties:
server.error.include-stacktrace=never
Solution 3
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+
Solution 4
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.
Solution 5
Call overloaded super constructor to avoid showing the stacktrace in response.
public class ProductCustomException extends Exception{
private static final long serialVersionUID = -291211739734090347L;
public ProductCustomException(String message) {
super(message,null,false,false);
}
}
Super loaded Constructor from Exception Class
protected Exception(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
rhorvath
Updated on May 22, 2021Comments
-
rhorvath almost 3 years
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 @ControlledAdvice 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? Thanks.
-
rhorvath almost 9 yearsthanks, stack trace is gone but I still see "2015-07-07 11:47:57.188 ERROR 41456 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Failed to invoke @ExceptionHandler method: public org.springframework.web.servlet.ModelAndView". Is there a way to get rid of this as well so I don't see any error in log for custom exception ? I accepted the answer because the stack trace was gone, but now i see that my exception message is twice in the logs (1. log statement and 2. exception message from the failed method)
-
Roland Weisleder almost 9 yearsI think there is no easy way to do this. Maybe you should consider not using exceptions (i.e. a custom status code) as this case is not exceptional but expectable. stackoverflow.com/questions/3213094
-
rhorvath almost 9 yearsmy use case is basically the same as the example from official spring doc (spring.io/blog/2013/11/01/exception-handling-in-spring-mvc), therefore I would not call it expectable. Otherwise we could argue the point of the validationException as well. Creating a custom return object is possible as I also described in the question, but I was trying to find simpler and cleaner solution if possible.
-
Ashu Phaugat over 5 years@RolandWeisleder Thanks for your answer, it really helped me.
-
shark1608 about 5 yearsAs of 1.3.0, 'Never' is by default. Check the release notes
-
Robber almost 5 years@shark1608 While it's true that the release notes say that, using Spring Boot 2.1.7 it was set to 'Always' by default
-
muttonUp over 4 years@Robber See my answer below, which may explain why it is getting set to ALWAYS
-
BitfulByte over 4 yearsThanks, appreciate the thoroughness. Always like to understand the 'why' part of a situation. Yet another case of unaware of the 'spring-boot magic'.
-
delitescere almost 4 yearsIf you update
application.yml
(orapplication.properties
) to specifyNEVER
Spring Boot DevTools will respect it (at least in 2.3) -
hello_earth about 3 yearsum, check that you are not overriding DefaultErrorAttributes too and not calling getErrorAttributes with hardcoded includeStackTrace parameter - as I was doing, duh!