[ 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.