Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Prevent Stack Trace from Spring Rest API Exception Handler returning HTTP status 400

I am trying to handle Validation exception in Spring Rest service like code given below:

@Produces("application/json")
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public @ResponseBody ResponseEntity<ValidationErrorDTO> processValidationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();
        ResponseEntity<ValidationErrorDTO> re = new ResponseEntity<>(processFieldErrors(fieldErrors), HttpStatus.BAD_REQUEST);   
        return re;
    }

However when this code executes, it returns stack trace appended to the JSON response. I want to get rid of this stack trace and only return JSON error response. Is this possible with Spring 3.1?

{"fieldErrors":    
[{"field":"type","message":"Pattern.shippingAddress.type"}]}&lt;pre&gt;javax.servlet.ServletException: 400 Bad Request null
        at com.ebay.raptor.kernel.dispatcher.HttpDispatchCommand.execute(HttpDispatchCommand.java:142)
        at com.ebay.ebox.pres.cmd.preshandler.CommandDispatchHandler.handleRequest(CommandDispatchHandler.java:59)
        at com.ebay.ebox.pres.cmd.preshandler.CommandDispatchHandler.handleRequest(CommandDispatchHandler.java:13)
        at com.ebay.ebox.pres.cmd.preshandler.CommandHandlerFactory$CalHandler.handleRequest(CommandHandlerFactory.java:114)
        at com.ebay.ebox.pres.cmd.preshandler.CommandHandlerFactory$CalHandler.handleRequest(CommandHandlerFactory.java:75)
        at com.ebay.kernel.pipeline.RequestPipeline.invoke(RequestPipeline.java:18)
        at com.ebay.kernel.pipeline.RequestPipeline.invoke(RequestPipeline.java:12)
        at com.ebay.kernel.pipeline.BasePipeline.callHandler(BasePipeline.java:75)
        at com.ebay.kernel.pipeline.BasePipeline.execute(BasePipeline.java:53)
        at com.ebay.ebox.pres.stage.BaseCommandRequestStageImpl.doWork(BaseCommandRequestStageImpl.java:64)
        at com.ebay.kernel.stage.StageDriver.execute(StageDriver.java:55)
        at com.ebay.ebox.pres.cmd.WebCommandImpl.execute(WebCommandImpl.java:30)
        at com.ebay.raptor.web.RaptorFrontController.process(RaptorFrontController.java:338)
        at com.ebay.raptor.web.RaptorFrontController.doPost(RaptorFrontController.java:554)
        at com.ebay.raptor.web.RaptorGenericController.service(RaptorGenericController.java:64)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
        at com.ebay.raptor.kernel.filter.RaptorDispatchFilter.doFilter(RaptorDispatchFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:195)
        at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:266)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)
    &lt;/pre&gt;
like image 518
user1919346 Avatar asked Jul 14 '14 07:07

user1919346


People also ask

How do you handle exceptions in spring boot REST API?

Altogether, the most common way is to use @ExceptionHandler on methods of @ControllerAdvice classes so that the exception handling will be applied globally or to a subset of controllers. ControllerAdvice is an annotation introduced in Spring 3.2, and as the name suggests, is “Advice” for multiple controllers.

How do you handle exceptions in REST services?

To deal with exceptions, the recommended practice is to follow the sequence outlined below: Determine whether the REST API request succeeded or failed, based on the HTTP status response code returned. If the REST API request failed and the response is application/json, serialize the model.


3 Answers

You can just add the application property server.error.include-stacktrace=never which responds for including stack trace into 400 responses.

like image 195
nikiforovpizza Avatar answered Sep 24 '22 00:09

nikiforovpizza


You can do like this:

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ModelAndView methodArgumentError(HttpServletRequest req, Exception exception) {
    return new JsonError(exception.getMessage()).asModelAndView();
}
like image 33
Phelipe Maia Avatar answered Sep 20 '22 00:09

Phelipe Maia


You could in your MethodArgumentNotValidException set the stack trace to null if the error is only being returned to the user and not be used for debugging.

Or alternatively, you could just override the getStackTrace() with a @JsonIgnore annotation

@JsonIgnore
@Override
public StackTraceElement[] getStackTrace() {
    return super.getStackTrace();
}

EDIT: I tried all the other solutions but none worked for me.

like image 31
Sean Cunniffe Avatar answered Sep 20 '22 00:09

Sean Cunniffe