TAGS :Viewed: 1 - Published at: a few seconds ago

[ How to include a message in a BadRequestException? ]

Is it possible to include a message in a BadRequestException so when the user sees a response code a 400, he/she can also figure out why?

The scenario would be something like this, simplified:

public Entity getEntityWithOptions(@PathParam("id") String id, @QueryParam("option") String optValue) {
    if (optValue != null) {
        // Option is an enum
        try {
            Option option = Option.valueOf(optValue);
        } catch (IllegalArgumentException e) {
            throw new BadRequestException(e.getMessage());
        }
        return new Entity(option);
    }
    return new Entity();
}

I know this can be done returning a Response object instead, but I wouldn't want that.

Is this possible? Maybe with an ExceptionMapper<BadRequestException>? Or this cannot be done since BadRequestException is already a Jersey-specific exception?

Answer 1


You can throw a CustomException and map it to a CustomExceptionMapper to provide customized response.

public class CustomException extends RuntimeException {    
    public CustomException(Throwable throwable) {
        super(throwable);
    }

    public CustomException(String string, Throwable throwable) {
        super(string, throwable);
    }

    public CustomException(String string) {
        super(string);
    }

    public CustomException() {
        super();
    }
}

@Provider
public class CustomExceptionMapper implements ExceptionMapper<CustomException> {
    private static Logger logger = Logger.getLogger(CustomExceptionMapper.class.getName());
    /**
     * This constructor is invoked when exception is thrown, after
     * resource-method has been invoked. Using @provider.
     */
    public CustomExceptionMapper() {
        super();
    }

    /**
     * When exception is thrown by the jersey container.This method is invoked  
     */
    public Response toResponse(CustomException ex) {
        logger.log(Level.SEVERE, ex.getMessage(), ex);
        Response.ResponseBuilder resp = Response.status(Response.Status.BAD_REQUEST)
                        .entity(ex.getMessage());

        return resp.build();
    }
}

Use the CustomException in your code like this.

public Entity getEntityWithOptions(@PathParam("id") String id, 
                                   @QueryParam("option") String optValue) 
                                   throws CustomException {
    if (optValue != null) {
        // Option is an enum
        try {
            Option option = Option.valueOf(optValue);
        } catch (IllegalArgumentException e) {
            throw new CustomException(e.getMessage(),e);
        }
        return new Entity(option);
    }
    return new Entity();
}

Instead of message, you can also construct an object and pass it to mapper through CustomException.

Answer 2


You should create a custom exception like this

public class CustomBadReq extends WebApplicationException {
     public CustomBadReq(String message) {
         super(Response.status(Response.Status.BAD_REQUEST)
             .entity(message).type(MediaType.TEXT_PLAIN).build());
     }
}

See also this

Answer 3


There is a really simple approach to this as shown below.

Response.ResponseBuilder resp_builder=Response.status(Response.Status.BAD_REQUEST);
resp_builder.entity(e.getMessage());//message you need as the body
throw new WebApplicationException(resp_builder.build());

if you need to add headers, response media type or some other functionality, ResponseBuilder provides them all.