How to include a message in a BadRequestException?

15,433

Solution 1

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.

Solution 2

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.

Share:
15,433

Related videos on Youtube

dabadaba
Author by

dabadaba

Updated on June 04, 2022

Comments

  • dabadaba
    dabadaba almost 2 years

    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?

    • Cuero
      Cuero almost 8 years
      I think the message can be put into the constructor, right? And If an exceptionMapper is used, it actually returns a Response.
    • dabadaba
      dabadaba almost 8 years
      I am passing the message to the constructor, but the response is not including it.
    • Cuero
      Cuero almost 8 years
      If an exceptionMapper is used, the message passed to the constructor is displayed. Just make the mapper like this: public Response toResponse(BadRequestException e) { return Response.status(Response.Status.BAD_REQUEST).type(MediaType.‌​TEXT_PLAIN).entity(E‌​xceptionUtils.getSta‌​ckTrace(e)).build();‌​}
    • cs_pupil
      cs_pupil about 3 years