4

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?

dabadaba
  • 9,064
  • 21
  • 85
  • 155
  • I think the message can be put into the constructor, right? And If an exceptionMapper is used, it actually returns a Response. – Cuero Jun 29 '16 at 15:52
  • I am passing the message to the constructor, but the response is not including it. – dabadaba Jun 29 '16 at 16:00
  • 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(ExceptionUtils.getStackTrace(e)).build();} – Cuero Jun 29 '16 at 16:28
  • This worked for me: https://stackoverflow.com/q/30712454/3806701 – cs_pupil Feb 05 '21 at 23:04

4 Answers4

5

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.

TMtech
  • 1,076
  • 10
  • 14
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.

0

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

Community
  • 1
  • 1
Hooch
  • 487
  • 3
  • 11
0

You can do it using the BadRequestException(Response response)constructor.

For example:

String msg = e.getMessage();
throw new BadRequestException(Response.status(BAD_REQUEST)
                .entity(msg).build());
user454322
  • 7,300
  • 5
  • 41
  • 52