我正在使用 WildFly 8(JAX-RS 2.0、EJB 3.2 和 JPA 2.1)编写 REST 应用程序。
我有一个 JAX-RS 资源,它也是一个 EJB(具有隐式容器管理事务的无状态 session bean):
@Path("myresources")
@Stateless
public class MyResource {
@PersistenceContext(name = "MyDataSource")
private EntityManager em;
@POST
public Response create() {
MyEntity invalidBean = new MyEntity();
em.persit(invalidBean);
...
}
}
MyEntity
装饰有 bean validation注释:
@Entity
public class MyEntity {
@NotNull
private String field;
...
}
最后,我为 ConstraintViolationException
定义了一个 ExceptionMapper
:
@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
@Override
public Response toResponse(ConstraintViolationException exception) {
...
}
}
当 MyResource.create
被调用时,我预计会出现以下行为:
- 无效bean使用JPA保存
- 我的服务实现无一异常(exception)地结束了
- 提交由容器触发(容器管理的事务)
- JTA 启动 bean 验证以检查保存的 bean 上的约束
- 抛出一个
ConstraintViolationException
- JAX-RS 将其分派(dispatch)到我的
ConstraintViolationExceptionMapper
但是,这不能正常工作:实际上抛出了 ConstraintViolationException
,但深深地包裹在 EJBTransactionRolledbackException
中。所以,我的 ExceptionMapper
没有捕捉到它。
我已经将 ConstraintViolationException
配置为 ApplicationException
(在 this guide 之后)。因此,我现在能够在我自己的代码抛出时捕获 ConstraintViolationException
,但在 JTA 抛出时仍然无法捕获。
This thread似乎相关,但我宁愿避免:
- 显式事务处理
- 特定于供应商的解决方案
有解决这个问题的想法吗?
谢谢!
最佳答案
我认为问题在于您的期望是什么。可能有两点可以进行验证。您的示例触发 Bean 验证作为 JPA 生命周期事件的一部分(在本例中持续存在)。由于我们在这个阶段已经与数据库对话,因此它被包裹在回滚异常中。
另一种方法是使用输入的 JAX-RS 验证。例如,我希望您的示例看起来像:
@Path("myresources")
@Stateless
public class MyResource {
@PersistenceContext(name = "MyDataSource")
private EntityManager em;
@POST
@ValidateOnExecution
public Response create(@Valid MyEntity entity) {
em.persit(entity);
...
}
}
现在,您发布的参数已转换为 MyEntity
实例,并作为请求处理的一部分进行验证。
关于jakarta-ee - 无法从 ExceptionMapper 捕获 ConstaintValidationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24436046/