I try to create my validate annotation.
When validation fails it's work good. I get a message about. But when validation passes I get RollbackException.
What I do in my validate annotation?
I want to check a unique email in the user table. Therefore, I have created @annotation:
package ru.project.domain.validation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Constraint(validatedBy = UniqueEmailValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UniqueEmail {
public String message() default "e-mail exist!";
public Class<?>[] groups() default {};
public Class<? extends Payload>[] payload() default{};
}
I have created Validator:
package ru.project.domain.validation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import ru.project.service.UserService;
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Autowired
private UserService userService;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && !userService.isEmailAlredyUse(value);
}
}
When I enter not-unique email I get message "e-mail exist!"
But when I enter unique email I get error:
2019-07-07 13:14:09.770 ERROR 11680 --- [io-8080-exec-10] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [HV000028: Unexpected exception during isValid call.] 2019-07-07 13:14:09.777 ERROR 11680 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction] with root cause
java.lang.NullPointerException: null at ru.project.domain.validation.UniqueEmailValidator.isValid(UniqueEmailValidator.java:17) ~[classes/:na] at ru.project.domain.validation.UniqueEmailValidator.isValid(UniqueEmailValidator.java:1) ~[classes/:na] at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:171) ~[hibernate-validator-6.0.17.Final.jar:6.0.17.Final] at org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:68) ~[hibernate-validator-6.0.17.Final.jar:6.0.17.Final] at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:73) ...
The function isValid is called twice. When validated after push button on the form and when userRepository try to save new User.
I will show what debugger shows me every time.
When push button on the form(unique email):
When userRepository try to save new User:
UPDATE: isEmailAlreadyUse:
public boolean isEmailAlredyUse(String value) {
User user = userRepository.findByEmail(value);
if(user != null) {
return true;
}
return false;
}