Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wildfly: ExceptionMapper not triggered with RestEasy JSR-303 Bean Validation

I'm using Bean Validation with RestEasy in Wildfly 8.2.0.Final:

@Path("/user")
@Produces(MediaType.APPLICATION_JSON)
public class UserEndpoint
{
    //more code

    @GET
    @Path("/encrypt/{email}")
    public Response fetchEncryptedId(@PathParam("email") @NotNull String email)
    {
        String encryptedUserId = userService.getEncryptedUserId(email);

        return Response.ok().entity(new UserBo(encryptedUserId)).build();
    }
}

This basically works. Now I'd like to get the response as JSON object but I can't get it working. All my "application" exceptions are handled by my Exception Mapper, this works:

@Provider
public class DefaultExceptionMapper implements ExceptionMapper<Exception>
{
    private static final String MEDIA_TYPE = "application/json";

    private LoggingService loggingService;

    @EJB
    public void setLoggingService(LoggingService loggingService)
    {
        this.loggingService = loggingService;
    }

    @Override
    public Response toResponse(Exception exception)
    {
        ResponseObject responseObject = new ResponseObject();
        responseObject.registerExceptionMessage(exception.getMessage());

        if (exception instanceof ForbiddenException)
        {
            loggingService.log(LogLevel.ERROR, ((ForbiddenException)exception).getUserId(), ExceptionToStringMapper.map(exception));
            return Response.status(Status.FORBIDDEN).type(MEDIA_TYPE).entity(responseObject).build();
        }

        //more handling

        loggingService.log(LogLevel.ERROR, "", ExceptionToStringMapper.map(exception));
        return Response.status(Status.INTERNAL_SERVER_ERROR).type(MEDIA_TYPE).entity(responseObject).build();
    }
}

But bean validation somehow bypasses it. Then I thought about using Throwable instead of Exception but it didn't help either. I guess the ExceptionMapper is not triggered because there is some life cycle problem with JAX-RS and JSR303. But how can I syncronize them to handle bean validation exceptions? Additional information: The exception passes the javax.ws.rs.container.ContainerResponseFilter so I could write some workaround by implementing the filter method in a subclass, but this is not clean solution. The target is to handle the exceptions in the Exception mapper.

like image 778
Bevor Avatar asked Sep 22 '15 19:09

Bevor


1 Answers

It's not always the case that your ExceptionMapper<Exception> will catch all exception under the Exception hierarchy. If there is another more specific mapper, say one for RuntimeException, that mapper will be used for all exception of RuntimeException and its subtypes.

That being said (assuming you're using resteasy-validation-provider-11), there is already a ResteasyViolationExceptionMapper that handles ValidationException.

@Provider
public class ResteasyViolationExceptionMapper 
        implements ExceptionMapper<ValidationException>

This mapper is automatically registered. It returns results in the form of a ViolationReport. The client needs to set the Accept header to application/json in order to see a response similar to

{
  "exception":null,
  "fieldViolations":[],
  "propertyViolations":[],
  "classViolations":[],
  "parameterViolations":[
    {
      "constraintType":"PARAMETER",
      "path":"get.arg0",
      "message":"size must be between 2 and 2147483647",
      "value":"1"}
  ],
  "returnValueViolations":[]
}

You can see more at Violation reporting.

If you want to completely override this behavior, you can create a more specific mapper for ResteasyViolationException, which is the exception thrown by the RESTeasy validator

@Provider
public class MyValidationMapper
        implements ExceptionMapper<ResteasyViolationException> {

    @Override
    public Response toResponse(ResteasyViolationException e) {

    }
}
like image 66
Paul Samsotha Avatar answered Oct 30 '22 00:10

Paul Samsotha