Я хочу внедрить ConstraintsValidator
, который проверяет, доступно ли электронное письмо, перед регистрацией нового пользователя, используя инъекцию depandency Spring @Autowired
, чтобы внедрить репозиторий JPA в валидатор, чтобы выполнить поиск в базе данных.
i такизменил фабрику валидаторов hibernate, так что spring создаст валидатор так, чтобы я мог использовать @Autowired
Все работает нормально, однако это похоже на то, что валидация входит в бесконечный цикл, который вызывает stackoverflowexception
.
Примечание: проверка выполняется автоматически (я не звоню validator.validate()
), так как я использую REST JPA Repository
@Getter
@Setter
@Entity
@UniqueCompteEmail
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Compte implements Serializable, UserDetails {
private static final long serialVersionUID = -5230227676515387462L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@NotBlank
@NotNull
@Column(unique = true)
private String username;
@NotNull
@NotBlank
@Size(min = 6)
private String password;
@Email
@NotNull
@NotBlank
@Column(unique = true)
private String email;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return new HashSet<GrantedAuthority>();
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public abstract CompteType getTypeCompte();
public abstract void setTypeCompte(CompteType typeCompte);
public static enum CompteType {
ETUDIANT, ADMINISTRATEUR
}
}
@Repository
public interface CompteRepository extends JpaRepository<Compte, Integer> {
public Optional<Compte> findByUsername(String username);
public Optional<Compte> findByEmail(String email);
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueCompteEmailValidator.class)
@Target({ ElementType.TYPE })
public @interface UniqueCompteEmail {
String message() default "{com.mssmfactory.bacsimulator.uniquecompteemail.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UniqueCompteEmailValidator implements ConstraintValidator<UniqueCompteEmail, Compte> {
@Autowired
private CompteRepository compteRepository;
@Override
public void initialize(UniqueCompteEmail constraintAnnotation) {
}
@Override
public boolean isValid(Compte value, ConstraintValidatorContext context) {
if (value != null) {
Optional<Compte> compte = this.compteRepository.findByEmail(value.getEmail());
return !compte.isPresent();
} else
return false;
}
}
@Component
public class ValidatorAddingCustomizer implements HibernatePropertiesCustomizer {
@Autowired
private ValidatorFactory validatorFactory;
public void customize(Map<String, Object> hibernateProperties) {
if (validatorFactory != null) {
hibernateProperties.put("javax.persistence.validation.factory", validatorFactory);
}
}
}