Reputation: 379
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"}]}<pre>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)
</pre>
Upvotes: 10
Views: 10309
Reputation: 393
Another simpler way to do it
public static void main(String[] args) {
System.setProperty("server.error.include-message", "never");
System.setProperty("server.error.include-stacktrace", "never");
//You can also change other important properties with this method, for example:
// System.setProperty("server.port", "8081");
// System.setProperty("server.servlet.context-path", "/api");
SpringApplication.run(YourApplication.class, args);
}
The response will look like this;
{
"timestamp": "2021-12-30T19:23:24.002+00:00",
"status": 400,
"error": "Bad Request",
"path": "/test"
}
Upvotes: 0
Reputation: 17
@Order(Ordered.HIGHEST_PRECEDENCE)
Use @Order(Ordered.HIGHEST_PRECEDENCE) on your method it will work
Upvotes: 1
Reputation: 21
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.
Upvotes: 1
Reputation: 576
You can just add the application property server.error.include-stacktrace=never
which responds for including stack trace into 400 responses.
Upvotes: 9
Reputation: 21
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();
}
Upvotes: 2
Reputation: 120781
It is uncommon to use both: @ResponseBody
and ResponseEntity
. I think you should clearly decide what you want to do. - And then you should check your internal framework class com.ebay.raptor.kernel.dispatcher.HttpDispatchCommand
, because this is the one that throws the exception.
Upvotes: 0
Reputation: 29
You can use Aspectj for these purposes. Example http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/
You should write an aspect, which will catch your exception.
Example:
@Aspect
public class AroundExample {
@Around
pointcut = "execution(* your.package.Class.processValidationError(..))",
throwing= "error")
public Object doSomeStuff(ProceedingJoinPoint pjp, Throwable error) throws Throwable {
Object[] args = joinPoint.getArgs(); // change the args if you want to
Object retVal = pjp.proceed(args); // run the actual method (or don't)
return retVal; // return the return value (or something else)
}
}
Upvotes: -1