8

I am using Spring Boot 1.3.X and have the following:

@RestController
@RequestMapping(path = "/foo")
public class FooController {

    @RequestMapping(method = RequestMethod.GET, params = { "fooBar" })
    public Collection<Entry> firstFoo() {
        //Do something
    }

    @RequestMapping(method = RequestMethod.GET, params = { "anotherFooBar" })
    public Collection<Entry> secondFoo() {
        //Do something other
    }

}

Which works as expected. When passing a wrong param, the following exception is raised:

{
    "error": "Bad Request", 
    "exception": "org.springframework.web.bind.UnsatisfiedServletRequestParameterException", 
    "message": "Parameter conditions \"fooBar\" OR \"anotherFooBar\" not met for actual request parameters: elementalFormulae={C11}", 
    "path": "/foo", 
    "status": 400, 
    "timestamp": 1455287433961
}

I then created an ExceptionHandler as seen below:

@ControllerAdvice
public class ExcptionController {

    @ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Invalid parameter")
    @ExceptionHandler(UnsatisfiedServletRequestParameterException.class)
    private void foo() {
        //Log exception
    }
}

Which raises the following Exception:

{
    "error": "Bad Request", 
    "exception": "org.springframework.web.bind.UnsatisfiedServletRequestParameterException", 
    "message": "Invalid parameter", 
    "path": "/api/foo", 
    "status": 400, 
    "timestamp": 1455287904886
}

Is it possible to exclude the exception field from the JSON representation?

1
  • Would @JSONIgnore do the trick? Commented Feb 12, 2016 at 15:30

3 Answers 3

8

You can get the Error Attributes in your controller advice and then, only keep the Exposable Fields. Something like following:

@ControllerAdvice
public class ExcptionController {
    private static final List<String> EXPOSABLE_FIELDS = asList("timestamp", "status", "error", "message", "path");

    @Autowired private ErrorAttributes errorAttributes;

    @ExceptionHandler(UnsatisfiedServletRequestParameterException.class)
    private ResponseEntity foo(HttpServletRequest request) {
        Map<String, Object> errors = getErrorAttributes(request);
        errors.put("message", "Invalid parameter");

        return ResponseEntity.badRequest().body(errors);
    }

    private Map<String, Object> getErrorAttributes(HttpServletRequest request) {
        ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
        final boolean WITHOUT_STACK_TRACE = false;
        Map<String, Object> attributes = errorAttributes.getErrorAttributes(requestAttributes, WITHOUT_STACK_TRACE);

        // log exception before removing it
        attributes.keySet().removeIf(key -> !EXPOSABLE_FIELDS.contains(key));

        return attributes;
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

This kind of works, meaning the fields not listed inside EXPOSABLE_FIELDS, are removed from the error attributes, but the returned JSON still looks as above
exception field is still there?
Yes, it is still shown, although errors does not contain the field anymore.
I will give it a try in the next few hours, and reply back to you
6

For those who use spring boot 2.x.
Since version 2.0.0 default implemetation of ErrorAttrubutes is DefaultErrorAttributes.
When possible DefaultErrorAttributes provides exception stack trace. Deleting this field from the response is possible by setting:

server.error.include-stacktrace: never

2 Comments

Yep, this work with Spring Boot 2.1.x and probably with spring 1.x, can you tell us where is the doc about this parameter ? Also from what I can find, "never" is supposed to be the default value, but it's clearly not.
Very late answer, but I hope it will be useful. Link to error properties
5

I have solved this bean-style. Adding the following bean definition to REST layer configuration replacing ErrorAttributes used solved issue in my case without any runtime code on exception processing.

@Bean
public ErrorAttributes errorAttributes() {
    return new DefaultErrorAttributes() {

        @Override
        public Map<String, Object> getErrorAttributes(
                RequestAttributes requestAttributes,
                boolean includeStackTrace) {

            Map<String, Object> errorAttributes
                = super.getErrorAttributes(requestAttributes, includeStackTrace);
            errorAttributes.remove("exception");
            return errorAttributes;
        }

    };
}

3 Comments

simple and best solution
Instead, a simple property in application.properties would do the trick: - server.error.include-exception=false
If you do not want to configure anything else and you are OK to have appropriate configuration in all deployments - seems like really better option. But I personally dislike properties configuration for such a fundamental thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.