Wildfly:ExceptionMapper 未通过 RestEasy JSR-303 Bean 验证触发

Posted

技术标签:

【中文标题】Wildfly:ExceptionMapper 未通过 RestEasy JSR-303 Bean 验证触发【英文标题】:Wildfly: ExceptionMapper not triggered with RestEasy JSR-303 Bean Validation 【发布时间】:2015-12-19 22:23:56 【问题描述】:

我在 Wildfly 8.2.0.Final 中使用带有 RestEasy 的 Bean 验证:

@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();
    

这基本上有效。现在我想以 JSON 对象的形式获取响应,但我无法让它工作。我所有的“应用程序”异常都由我的异常映射器处理,这很有效:

@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();
    

但 bean 验证以某种方式绕过它。然后我考虑使用 Throwable 而不是 Exception 但它也没有帮助。我猜 ExceptionMapper 没有被触发,因为 JAX-RS 和 JSR303 存在一些生命周期问题。但是我怎样才能同步它们来处理 bean 验证异常呢? 附加信息:异常通过了javax.ws.rs.container.ContainerResponseFilter,所以我可以通过在子类中实现过滤器方法来编写一些解决方法,但这不是干净的解决方案。目标是处理异常映射器中的异常。

【问题讨论】:

我认为异常映射器是要走的路。另见***.com/questions/10516516/…。不知道为什么这在这种情况下不起作用。您是否尝试过按照其他帖子的建议注册专用映射器? @Hardy 我也不是,这就是我问的原因。帖子中的映射器与我的相同,因此我的更宽容,因为我基本上捕捉到任何异常,而不仅仅是 ConstraintViolationException。 (我在调试器中,但它没有被调用) 【参考方案1】:

您的ExceptionMapper&lt;Exception&gt; 并不总是会捕获Exception 层次结构下的所有异常。如果有另一个更具体的映射器,比如RuntimeException那个 映射器将用于RuntimeException 及其子类型的所有异常。

话虽如此(假设您使用的是resteasy-validation-provider-11),已经有一个ResteasyViolationExceptionMapper 处理ValidationException

@Provider
public class ResteasyViolationExceptionMapper 
        implements ExceptionMapper<ValidationException>

这个映射器是自动注册的。它以ViolationReport 的形式返回结果。客户端需要将 Accept 标头设置为 application/json 才能看到类似于

的响应

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

你可以在Violation reporting看到更多。

如果你想完全覆盖这个行为,你可以为ResteasyViolationException创建一个更具体的映射器,也就是RESTeasy验证器抛出的异常

@Provider
public class MyValidationMapper
        implements ExceptionMapper<ResteasyViolationException> 

    @Override
    public Response toResponse(ResteasyViolationException e) 

    

【讨论】:

谢谢,两种解决方案都有效。当我可以奖励赏金时,我会接受它。

以上是关于Wildfly:ExceptionMapper 未通过 RestEasy JSR-303 Bean 验证触发的主要内容,如果未能解决你的问题,请参考以下文章

Docker 容器中的 Wildfly 未启动

错误 404 - 未找到 Wildfly

Wildfly 10.1.0 - 未找到 Mysql 数据源

Wildfly:应用程序已部署但未运行

Spring Boot 应用程序未部署在 Wildfly 上

战争未部署到Wildfly 10.1中