Может кто-нибудь помочь мне, почему я не могу сохранить объект, имеющий поле с настраиваемым валидатором, в весенних сапогах?
Сценарий: сначала я должен проверить поле с помощью настраиваемого валидатора (который работает нормально), затемсохранить сущность в базу данных (которая ломается).Я использую Spring Boot Framework на IntelliJ IDE.Код есть на github.https://github.com/mhussainshah1/customvalidation
У меня есть сущность Customer
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ContactInfo //Custom Validator
@NotNull
private String contactInfo;
// standard constructor, getters, setters
}
У меня есть сущность ContactInfoExpression
@Entity
public class ContactInfoExpression {
@Id
@Column(name="expression_type")
private String type;
private String pattern;
//standard constructor, getters, setters
}
У меня есть ContactInfoExpressionRepository
и CustomerRepository
, которая расширяется CrudRepository<T, Id>
Я использую базу данных H2 в памяти со следующей конфигурацией в файле application.properties.Свойству contactInfoType
может быть присвоено одно из значений: электронная почта, телефон или веб-сайт
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.show-sql=true
contactInfoType=email
#contactInfoType=phone
#contactInfoType=website
Пользовательский валидатор
@Component
public class ContactInfoValidator implements ConstraintValidator<ContactInfo, String> {
private static final Logger LOG = LogManager.getLogger(ContactInfoValidator.class);
@Value("${contactInfoType}")
private String expressionType;
private String pattern;
@Autowired
private ContactInfoExpressionRepository contactInfoExpressionRepository;
@Override
public void initialize(ContactInfo contactInfo) {
if (StringUtils.isEmptyOrWhitespace(expressionType)) {
LOG.error("Contact info type missing!");
} else {
pattern = contactInfoExpressionRepository.findById(expressionType)
.map(ContactInfoExpression::getPattern).get();
}
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (!StringUtils.isEmptyOrWhitespace(pattern)) {
return Pattern.matches(pattern, value);
}
LOG.error("Contact info pattern missing!");
return false;
}
}
Пользовательская аннотация ограничения
@Constraint(validatedBy = { ContactInfoValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ContactInfo {
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Я использую класс DataLoader для загрузки данных
@Component
public class DataLoader implements CommandLineRunner {
@Autowired
ContactInfoExpressionRepository contactInfoExpressionRepository;
@Autowired
CustomerRepository customerRepository;
@Override
public void run(String... args) throws Exception {
String pattern = "[a-z0-9!#$%&*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
ContactInfoExpression email = new ContactInfoExpression("email", pattern);
contactInfoExpressionRepository.save(email);
pattern = "^([0-9]( |-)?)?(\\(?[0-9]{3}\\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$";
ContactInfoExpression phone = new ContactInfoExpression("phone", pattern);
contactInfoExpressionRepository.save(phone);
pattern = "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$";
ContactInfoExpression website = new ContactInfoExpression("website", pattern);
contactInfoExpressionRepository.save(website);
Customer customer1 = new Customer("mhussainshah79@gmail.com");
customerRepository.save(customer1);// Error: can`t save
}
}
Я не могу сохранить объект клиента, имеющий поле с пользовательским валидатором.Я получаю следующую ошибку во время выполнения
java.lang.IllegalStateException: Failed to execute CommandLineRunner
Caused by: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
Caused by: javax.persistence.RollbackException: Error while committing the transaction
Caused by: javax.validation.ValidationException: HV000032: Unable to initialize com.example.customvalidation.ContactInfoValidator.
Caused by: java.lang.NullPointerException: null
at com.example.customvalidation.ContactInfoValidator.initialize(ContactInfoValidator.java:41) ~[classes/:na]
at com.example.customvalidation.ContactInfoValidator.initialize(ContactInfoValidator.java:18) ~[classes/:na]