Question

Hi, I have a doubt how to catch a ConstraintViolationException during merge. I have my JPALogic class and I want to catch the exception to write down more informations, this code works perfectly, throwing the GenericSaveException:

try {
  em.persist(o);
} catch (ConstraintViolationException e) {
  System.out.println("*** CONSTRAINT VIOLATIONS");
  Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
  for (ConstraintViolation<?> violation : violations) {
    System.err.println("*** VIOLATION: " + violation.getRootBeanClass().getSimpleName() + "::" + violation.getPropertyPath().toString() + " " + violation.getMessage());
  }
  throw new GenericSaveException();
}

but this does not throw the exception, resulting in a javax.ejb.EJBException: Transaction aborted, Caused by: javax.transaction.RollbackException: Transaction marked for rollback, Caused by: javax.validation.ConstraintViolationException:

try {
  managed = (T) em.merge(o);
} catch (ConstraintViolationException e) {
  System.out.println("*** JPALogic::merge --> CONSTRAINT VIOLATIONS");
  Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
  for (ConstraintViolation<?> violation : violations) {
    System.err.println("*** VIOLATION: " + violation.getRootBeanClass().getSimpleName() + "::" + violation.getPropertyPath().toString() + " " + violation.getMessage());
  }
  throw new GenericSaveException();
}

why merge doesn't throw the ConstraintViolationException? What can I do to catch the exception?

Thank you.

Was it helpful?

Solution

Might be too late, but me also faced the same problem.

Actually this is somehow in the implementation of Hibernate, see: https://issues.jboss.org/browse/AS7-4576, and https://hibernate.atlassian.net/browse/HHH-7288 says it won't fix. Might be this feature (validation upon first call) will work on EclipseLink, but I haven't tried it.

In order to workaround this, I used a bit changed logic, in my service layer before calling merge or persist I run the following:

Set<ConstraintViolation<Contact>> validations = validator.validate(data);
if (validations.size() > 0) {
    Map<String, String> messages = new HashMap<>();
    for (ConstraintViolation v : validations) {
        messages.put(v.getPropertyPath().toString(), v.getMessage());
    }

    return Response.status(Response.Status.BAD_REQUEST).entity(messages).build();
}

Where validator is simple injection in my bean:

@Inject
Validator validator;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top