1

I have created a new exception class in my Dropwizard service that extends BadRequestException.

public class CustomBadRequestException extends BadRequestException {

    private static final long serialVersionUID = 1L;

    private List<ValidationFailureDto> validationFailures;

    public CustomBadRequestException() {
        super();
    }

    public CustomBadRequestException(final List<ValidationFailureDto> validationFailures) {
        super();
        this.validationFailures = validationFailures;
    }

    @ApiModelProperty(value = "List of validationFailures")
    public List<ValidationFailureDto> getValidationFailures() {
        return validationFailures;
    }
}

When I throw that exception at first I was only getting back the deserialised BadRequestException, minus the additional property (validationFailures)

{
code: "400",
message: "Bad request"
}

This is because Dropwizard's internals have a default exception mapper that allows Jetty/Jackson to understand domain exceptions and how to send the appropriate HTTP response.

To overcome this you can implement your own ExceptionMapper class and register it with Dropwizard.

public class CustomBadRequestExceptionMapper implements ExceptionMapper<SamplePackOrderBadRequestException> {

/**
 * Allows jackson to deserialise custom exceptions and its properties to JSON response
 *
 * @param exception exception
 * @return response object
 */
@Override
public Response toResponse(final SamplePackOrderBadRequestException exception) {

    if (exception instanceof SamplePackOrderBadRequestException) {

        SamplePackOrderBadRequestException samplePackOrderBadRequestException
                = (SamplePackOrderBadRequestException) exception;
        return Response
                .status(400)
                .entity(samplePackOrderBadRequestException)
                .build();
    }
    return Response.status(400).build();
}
}

However this issue with this is that it deserializes super (Throwable), so you get every single inherited property added in the response which I do not want.

To combat this I tried adding Jackson annotations like so:

@JsonIgnoreProperties(value = "stackTrace")

This is not an optimal solution as there are several properties other than stackTrace that I will need to ignore.

So to summarise, how can I get Dropwizard to properly deserialize my CustomException class without all the additional clutter that I do not need?

Amit
  • 30,756
  • 6
  • 57
  • 88
tomaytotomato
  • 3,788
  • 16
  • 64
  • 119
  • You can use this: http://stackoverflow.com/questions/26945580/jackson-serialization-how-to-ignore-superclass-properties You'll have to be careful though about how you use that. The Objectmapper provided by DW is shared, so make sure your other objects don't suffer from this :) I think it would be easier to just create a wrapper object that you use instead – pandaadb Apr 05 '17 at 15:09
  • Dropwizard is actually using the approach recommended in the answer below. They use a [custom ErrorMessage Java bean](https://github.com/dropwizard/dropwizard/blob/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/errors/ErrorMessage.java) and added `@JsonInclude(JsonInclude.Include.NON_NULL)` annotation :). And this is how [their ExceptionLoggingMapper}(https://github.com/dropwizard/dropwizard/blob/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/errors/LoggingExceptionMapper.java) is looking. – zloster Apr 06 '17 at 14:23

1 Answers1

1

I think the easier option is to transform exception to a Error bean and return it as shown below.

public class CustomBadRequestExceptionMapper implements ExceptionMapper<SamplePackOrderBadRequestException> {


@Override
public Response toResponse(final SamplePackOrderBadRequestException exception) {

    if (exception instanceof SamplePackOrderBadRequestException) {

        SamplePackOrderBadRequestException ex
            = (SamplePackOrderBadRequestException) exception;
         return Response
            .status(400)
            .entity(new ErrorBean(400,ex.getMessage,ex.getgetValidationFailures()))
            .build();
    }
    return Response.status(400).build();
}
}

And ErrorBean.java

    public static class ErrorBean{
    private int code;
    private String message;
    private List<ValidationFailureDto> failures;
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public List<ValidationFailureDto> getFailures() {
        return failures;
    }
    public void setFailures(List<ValidationFailureDto> failures) {
        this.failures = failures;
    }
}
Justin Jose
  • 2,121
  • 1
  • 16
  • 15
  • You could mention that this is how Dropwizard is doing it itself. See my comment under the question: http://stackoverflow.com/questions/43231802/dropwizard-deserialising-custom-exception-as-json#comment73584583_43231802 – zloster Apr 06 '17 at 14:25