I'm writing a REST application using WildFly 8 (JAX-RS 2.0, EJB 3.2 and JPA 2.1).
I have a JAX-RS resource which is also an EJB (stateless session bean with implicit container-managed transactions):
@Path("myresources")
@Stateless
public class MyResource {
@PersistenceContext(name = "MyDataSource")
private EntityManager em;
@POST
public Response create() {
MyEntity invalidBean = new MyEntity();
em.persit(invalidBean);
...
}
}
MyEntity is decorated with bean validation annotations:
@Entity
public class MyEntity {
@NotNull
private String field;
...
}
Finally, I have defined an ExceptionMapper for ConstraintViolationException:
@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
@Override
public Response toResponse(ConstraintViolationException exception) {
...
}
}
When MyResource.create is called, I expect the following behavior:
ConstraintViolationException is thrownConstraintViolationExceptionMapperHowever, this does not work properly: the ConstraintViolationException is actually thrown, but deeply wrapped inside an EJBTransactionRolledbackException. So, my ExceptionMapper does not catch it.
I already configured ConstraintViolationException to be an ApplicationException (following this guide). Thus, I'm now able to catch ConstraintViolationException when thrown from my own code, but still not when thrown by JTA.
This thread seems related, but I would prefer to avoid:
Any idea to solve this problem?
Thanks!
I think the problem is what your expectation is. There are potentially two points where validation can occur. Your example triggers Bean Validation as part of JPA life cycle events (persist in this case). Since we are at this stage already talking to a database it is wrapped in a rollback exception.
The other approach is to use the JAX-RS validation of the input. For example I would have expected your example to look like:
@Path("myresources")
@Stateless
public class MyResource {
@PersistenceContext(name = "MyDataSource")
private EntityManager em;
@POST
@ValidateOnExecution
public Response create(@Valid MyEntity entity) {
em.persit(entity);
...
}
}
Now your posted parameters are converted into a MyEntity instance and validated as part of the request processing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With