0

I am validating an incoming POST request which will create a database entity after validating the request data. I am trying to gather multiple errors in a single request and respond as error response following JSON API spec:

https://jsonapi.org/examples/#error-objects-multiple-errors

HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json

{
  "errors": [
    {
      "status": "403",
      "source": { "pointer": "/data/attributes/secretPowers" },
      "detail": "Editing secret powers is not authorized on Sundays."
    },
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/volume" },
      "detail": "Volume does not, in fact, go to 11."
    },
    {
      "status": "500",
      "source": { "pointer": "/data/attributes/reputation" },
      "title": "The backend responded with an error",
      "detail": "Reputation service not responding after three requests."
    }
  ]
}

Is it possible to do this by @ControllerAdvice. When Global exception handling is enabled by @ControllerAdvice and throws an exception, the next exception won't be caught.

iamcrypticcoder
  • 2,609
  • 4
  • 27
  • 50

1 Answers1

2

Not directly, no. Not sure what is your business case/logic, therefore I don't know how you handling these exceptions in service layer, but in general, if you want to pass multiple errors in your @ExceptionHanlder - you could create a custom POJO:

public class MyError {
    private String status;
    private String source;
    private String title;
    private String detail;

    getters/setters...
}

and then create a custom RuntimeException which would accept list of these POJOs:

public class MyRuntimeException extends RuntimeException {
    private final List<MyError> errors;

    public MyRuntimeException(List<MyError> errors) {
        super();
        this.errors = errors;
    }

    public List<MyError> getErrors() {
        return errors;
    }
}

And in your service layer you could create list of these POJOs, wrap then in your exception and throw it. Then in @ControllerAdvice you simply catch your exception and call accessor method to iterate against your list of POJOs to construct a payload you want. Something like:

@ExceptionHandler (MyRuntimeException.class)
@ResponseStatus (BAD_REQUEST)
@ResponseBody
public Map<String, Object> handleMyRuntimeException(MyRuntimeException e) {
    return singletonMap("errors", e.getErrors());
}
mgaigalas
  • 21
  • 2