Пользовательский валидатор вызывает StackOverflowException - PullRequest
1 голос
/ 29 июня 2019

Я хочу внедрить 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);
        }
    }
}

1 Ответ

0 голосов
/ 30 июня 2019

Поскольку вы не определили никаких событий, для всех событий будет вызываться валидатор.

События (см. здесь ):

  • BeforeCreateEvent
  • AfterCreateEvent
  • BeforeSaveEvent
  • AfterSaveEvent
  • BeforeLinkSaveEvent
  • AfterLinkSaveEvent
  • BeforeDeleteEvent
  • AfterDeleteEvent

И так как вы собираетесь получить проверочный метод из db, вы попали в бесконечный цикл.

Вам просто нужно аннотировать валидатор конвективным именем.

@Component("beforeCreateCompteValidator")
public UniqueCompteEmailValidator implements Validator<Compte>{
}

и удаление других аннотаций.

Spring распознает этот валидатор и прикрепляется к правому крючку.

Для получения дополнительной информации см. Проверка пружины

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...