Wildfly:未使用 RestEasy JSR-303 Bean 验证触发 ExceptionMapper
Wildfly: ExceptionMapper not triggered with RestEasy JSR-303 Bean Validation
我在 Wildfly 8.2 中将 Bean 验证与 RestEasy 结合使用。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();
}
}
这基本上有效。现在我想得到 JSON 对象的响应,但我无法让它工作。我所有的 "application" 异常都由我的异常映射器处理,这有效:
@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
因此我可以通过在子类中实现 filter 方法来编写一些解决方法,但这不是干净的解决方案。目标是处理异常映射器中的异常。
您的 ExceptionMapper<Exception>
并不总是会捕获 Exception
层次结构下的所有异常。如果有另一个更具体的映射器,比如 RuntimeException
, 那个 映射器将用于 RuntimeException
及其子类型的所有异常。
也就是说(假设您使用的是 resteasy-validation-provider-11
),已经有一个 ResteasyViolationExceptionMapper
可以处理 ValidationException
。
@Provider
public class ResteasyViolationExceptionMapper
implements ExceptionMapper<ValidationException>
此映射器已自动注册。它 returns 的结果是 ViolationReport
的形式。客户端需要将 Accept
header 设置为 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 8.2 中将 Bean 验证与 RestEasy 结合使用。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();
}
}
这基本上有效。现在我想得到 JSON 对象的响应,但我无法让它工作。我所有的 "application" 异常都由我的异常映射器处理,这有效:
@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
因此我可以通过在子类中实现 filter 方法来编写一些解决方法,但这不是干净的解决方案。目标是处理异常映射器中的异常。
您的 ExceptionMapper<Exception>
并不总是会捕获 Exception
层次结构下的所有异常。如果有另一个更具体的映射器,比如 RuntimeException
, 那个 映射器将用于 RuntimeException
及其子类型的所有异常。
也就是说(假设您使用的是 resteasy-validation-provider-11
),已经有一个 ResteasyViolationExceptionMapper
可以处理 ValidationException
。
@Provider
public class ResteasyViolationExceptionMapper
implements ExceptionMapper<ValidationException>
此映射器已自动注册。它 returns 的结果是 ViolationReport
的形式。客户端需要将 Accept
header 设置为 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) {
}
}