0

Here's a JAX-RS end-point:

@Path("logout")
@POST
public void logout(@HeaderParam("X-AuthToken") String apiToken) {
    try {
        authenticationService.logout(apiToken);
    } catch (ExpiredApiTokenException exc) {
        throw new BadRequestException("API token has expired");
    } catch (InvalidApiTokenException exc) {
        throw new BadRequestException("API token is not valid");
    } catch (ApplicationException exc) {
        throw new InternalServerErrorException();
    }
}

When one of these BadRequestExceptions (HTTP 400) are thrown, GlassFish returns its own error page in the response body instead of the error message in my code. The response contains the correct HTTP code. Just the body is replaced.

I have tried creating an ExceptionMapper:

@Provider
public class ExceptionMapperImpl implements ExceptionMapper<Throwable> {

    @Override
    public Response toResponse(Throwable exception) {
        if (exception instanceof WebApplicationException) {
            return ((WebApplicationException) exception).getResponse();
        } else {
            logger.log(Level.SEVERE, "Uncaught exception thrown by REST service", exception);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
        }
    }

    private static final Logger logger = Logger.getLogger(ExceptionMapperImpl.class.getName());
}

And I tried adding the following ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         version="3.2"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd">
    <assembly-descriptor>
        <application-exception>
            <exception-class>javax.ws.rs.WebApplicationException</exception-class>
            <rollback>true</rollback>
        </application-exception>
    </assembly-descriptor>
</ejb-jar>

all to no avail.

What am I missing?

Steve
  • 8,066
  • 11
  • 70
  • 112
  • you're explicitly asking for the WebApplicationException's response (because BadRequestException is a WebApplicationException). – Gus Mar 18 '14 at 15:35
  • Can you please elaborate? Where am I doing this? What should I be doing instead? FYI - I tried all four combinations: With/without the provider and with/without the ejb-jar.xml. Same behaviour in all four cases. – Steve Mar 18 '14 at 15:38
  • In your exception mapper, you have `if (exception instanceof WebApplicationException)` which will be true for a BadRequestException, and then you get the WebApplicationException's Response from there. I'm betting that what you want to do is build your own response (probably by explicitly checking for `BadRequestException`). – Gus Mar 18 '14 at 15:49
  • No. What I want to do is get a response whose body contains only the message string I pass to the exception constructor. FYI - it seems like the provider is being completely ignored. `toResponse` never gets called. – Steve Mar 18 '14 at 15:58
  • `ExceptionMapperImpl` is getting called now (just started working). I changed it to return `Response.ok().build()` instead of `((WebApplicationException) exception).getResponse()` and that works, but when I change it back, GlassFish still returns its own page despite the fact that the exception mapper is returning its own response. – Steve Mar 18 '14 at 23:53

1 Answers1

0

In the toResponse method, I changed this

return exception.getResponse();

to this

return Response.status(exception.getResponse().getStatus())
               .entity(exception.getMessage())
               .build();

The problem is the when I do this:

throw new BadRequestException("Something is wrong!");

it doesn't populate the exception's Response's body with "Something is wrong!". GlassFish sees that the response body is empty and its status code is an error code, so it inserts its own response body. By populating the response body (a.k.a. entity) in the provider, this problem goes away.

Steve
  • 8,066
  • 11
  • 70
  • 112