Better logging of Hibernate JPA bean validation
I must be missing something 开发者_如何学JAVAbut its very hard to figure out what actually failed JPA validation for hibernate.
When validation fail for JPA annotations in hibernate you get an exception like:
javax.validation.ConstraintViolationException: validation failed for classes [com.evocatus.domain.Sauce] during persist time for groups [javax.validation.groups.Default, ]
Which is extremely unhelpful.
You can turn on logging for the for what the actually validation failure is through log4j:
<logger name="org.hibernate.cfg.beanvalidation.BeanValidationEventListener">
<level value="TRACE" />
</logger>
YES that is TRACE.
I must be missing something. Is there a better way to get better error messages on validation failures logged? This is for a REST service.
You need to get the set of actual ConstraintViolations. ConstraintViolationException has a getConstraintViolations() method which will return a Set>. Arguably the logged exception message could be better ;-)
I assume you are not using any framework which deals directly with BeanValidation (like JSF 2), and that's the reason you are not seeing any detail. If you are using plain Hibernate with BeanValidation, you'll need to perform the validation by yourself (usually just before trying to persist). Then, you'd have access to a Validator
object, from which you can retrieve the actual message. See this example from Hibernate Validator documentation:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Car car = new Car(null);
Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car);
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
Following code will print the validation errors in your code from which you can find whee the problem lies
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Notice>> constraintViolations = validator.validate(notice);
for (ConstraintViolation cv : constraintViolations) {
System.out.println("ValidatationConstraint: " + cv.getConstraintDescriptor().getAnnotation());
System.out.println("ValidatationConstraint: " + cv.getConstraintDescriptor());
System.out.println("ValidatationConstraint: " + cv.getMessageTemplate());
System.out.println("ValidatationConstraint: " + cv.getInvalidValue());
System.out.println("ValidatationConstraint: " + cv.getLeafBean());
System.out.println("ValidatationConstraint: " + cv.getRootBeanClass());
System.out.println("ValidatationConstraint: " + cv.getPropertyPath().toString());
System.out.println("ValidatationConstraint: " + cv.getMessage());
}
精彩评论