Сценарий состоит в том, что перед сохранением класса сущности Log
необходимо проверить его свойство String description
, содержит ли оно хотя бы слово, найденное в классе сущности IllegalWord
. Вот сопоставление двух классов сущностей:
// Log.java
@Entity
public class Log {
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Id
private Long id;
@NotContainingIllegalWords
private String description;
}
// IllegalWord.java
@Entity
public class IllegalWord {
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Id
private Long id;
private String word;
}
Поскольку я буду выполнять select *
с классом сущности IllegalWord
, я создал для него класс репозитория:
// IllegalWordRepository.java
@Repository
public interface IllegalWordRepository extends CrudRepository<IllegalWord, Long> {}
Затем был создан класс валидатора ConstraintValidator
, который будет использоваться аннотацией NotContainingIllegalWords
, которая, в свою очередь, будет использоваться для аннотирования поля String description
класса сущности Log
:
// NotContainingIllegalWordsValidator.java
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
private static final Logger log = LoggerFactory.getLogger(NotContainingIllegalWordsValidator.class);
@Autowired
private IllegalWordRepository illegalWordRepository;
public void initialize(NotContainingIllegalWords constraintAnnotation) {}
public boolean isValid(String value, ConstraintValidatorContext cxt) {
log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
// Returns "illegalWordRepository is null? true"
// It is not injected even with the @Autowired annotation.
boolean valid = true;
Collection<IllegalWord> illegalWords = illegalWordRepository.findAll();
// Encounters a NullPointerException here.
// valid = ...loop through illegalWords collection and match regex (or whatever optimal approach)
// with @param value to check if it contains the illegal word.
return valid;
}
Я думал, это будет так просто. Но инструкция illegalWordRepository.findAll()
выдает ошибку, потому что переменная illegalWordRepository
имеет значение NULL. Обратите внимание, что я попытался проверить, соответствует ли он null
в предыдущем утверждении.
Я предположил, что у меня что-то неправильно закодировано в классе репозитория, поэтому я попытался использовать @Autowired private IllegalWordRepository illegalWordRepository
внутри аннотированного класса @Service
и, как ни странно, он там правильно введен (например, не null
):
// IllegalWordService.java
@Service
public class IllegalWordService {
private static final Logger log = LoggerFactory.getLogger(IllegalWordService.class);
@Autowired
private IllegalWordRepository illegalWordRepository;
public IllegalWord generate(String word) {
log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
// Returns "illegalWordRepository is null? false"
IllegalWord illegalWord = new IllegalWord();
illegalWord.setWord(word);
illegalWordRepository.save(illegalWord);
// Didn't encounter a NullPointerException here.
return illegalWord;
}
}
Поэтому я думаю, что с классом репозитория IllegalWordRepository
все в порядке. Просто он не внедряется в класс валидатора NotContainingIllegalWordsValidator
, как я предполагал, с аннотацией @Autowired
(если это то, как аннотация @Autowired
должна была работать даже, извините, я новичок в Spring Framework. ).
Если существует правильный подход к тому, как выполнить запрос @Entity внутри экземпляра ConstraintValidator
, сообщите мне.
Связанный без ответа вопрос SO: Ввести репозиторий внутри ConstraintValidator с Spring 4 и конфигурацией интерполяции сообщений
Неудачная попытка:
Я пытался аннотировать класс NotContainingIllegalWordsValidator
с помощью аннотации @Configurable
, например:
@Configurable(autowire=Autowire.BY_NAME, preConstruction=true)
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
но illegalWordRepository
остается имущество null
.