ilce ilce - 6 months ago 65
JSON Question

JAX-RS / Jersey : Change response body from Jackson JSON errors

I have a rest end point using jersey, and I "drop" the payload in a DTO with a field which is ENUM type.

public enum AdminStatus {
ACTIVE, NONACTIVE;
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class AdminUpdateDTO {

@XmlElement(nillable = false, required = true)
private AdminStatus status;

public AdminStatus getStatus() {
return status;
}

public void setStatus(AdminStatus status) {
this.status = status;
}

@Override
public String toString() {
return "[status=" + this.getStatus() + "]";
}
}


When I give this field a value that not match with the existing ENUM values and make a request I get this:


Can not construct instance of com.utility.AdminStatus from String value 'ACTIVEE':
value not one of declared Enum instance names: [NONACTIVE, ACTIVE]

at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@2848cd9d; line: 1, column: 328] (through reference chain: com.dto.AdminUpdateDTO["status"])


Does Jersey has ability to handle this somehow, i mean, i don't want to get this as a response but some custom error response.

Answer

This is the default behavior of the Jackson provider exception mappers: to return the exception message as the response. If you want a different response, create your own mappers for JsonMappingException and JsonParseException, as mentioned here.

UPDATE

here are a couple examples

@Provider
public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> {
    @Override
    public Response toResponse(JsonMappingException exception) {
        return Response.status(Response.Status.BAD_REQUEST)
                .entity("Boo..").type("text/plain").build();
    }
}

@Provider
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
    @Override
    public Response toResponse(JsonParseException exception) {
        return Response.status(Response.Status.BAD_REQUEST)
                .entity("Boo...").type("text/plain").build();
    }
}

Here the response will simply be Boo.... You need to make sure these mappers are registered. If you are using scanning, the class should be picked up from the @Provider annotation. Otherwise you will need to manually register, whichever way you register your resources and providers.

Comments