Как добавить Spring bean в ConstraintValidator - PullRequest
0 голосов
/ 06 мая 2019

Мне нужно выполнить проверку объекта, используя репозиторий Spring.Я пытаюсь внедрить компонент репо Spring в ConstraintValidator.Когда проверка происходит в контроллере, валидатор внедряется, как и ожидалось, с компонентом Spring.Но когда проверка выполняется (менеджером постоянства) перед сохранением сущности, зависимость репо становится нулевой, и я получаю NPE.

Я прочитал много постов об этой проблеме, но, похоже, они касаются более ранних версий Spring.Я использую Spring Boot 2.1 (Spring Framework 5.1).

Вот мой код:

public class OrderItemDeleteValidator 
    implements ConstraintValidator<OrderItemDelete, Order> {

    @Autowired
    public OrderItemRepository orderItemRepo;

    @Override
    public void initialize(OrderMandatesDelete o) {
        //Tried this line to no avail based on one of many posts
       //SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    /**
      Invalid if items have been deleted from the order. Otherwise valid
    **/
    @Override
    public boolean isValid(Order order, ConstraintValidatorContext context) {           
        if (order.getId() == null) {
            // An order is new so all line items are new.
            return true;
        }

     List<OrderItems> originalOrderItems = orderItemRepo.findByOrderId(order.getId());

     // code to compare original order items to current order items
     // return false if current order is missing items from 
     // original order items. Otherwise return true
  }
}

Я добавил ведение журнала и вижу, что третий вызов валидатора сообщает об отсутствии значения для orderItemRepo.Не знаете, почему есть три вызова?

На основе нескольких сообщений, таких как https://stackoverflow.com/a/30715908/1706691 и https://stackoverflow.com/a/47246376/1706691, Я попытался настроить свою конфигурацию БД следующим образом:

@Autowired
Validator v;

@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, Validator v) {
    Map<String, Object> properties = new HashMap<String, Object>();    

    properties.put("javax.persistence.validation.factory", v);

    LocalContainerEntityManagerFactoryBean l = builder
            .dataSource(dataSource())
            .packages("com.example.domain")
            .persistenceUnit("main")       
            .properties(properties)   
            .build();
    return l;
}

Но это приводит к бесконечной проверке, вызывающей переполнение стека:

java.lang.StackOverflowError: null
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_192]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_192]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_192]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[na:1.8.0_192]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[na:1.8.0_192]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[na:1.8.0_192]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[na:1.8.0_192]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_192]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_192]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_192]
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_192]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_192]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_192]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[na:1.8.0_192]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[na:1.8.0_192]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[na:1.8.0_192]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[na:1.8.0_192]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_192]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_192]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_192]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.query.Query.getResultList(Query.java:135) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:129) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:136) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:117) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE] 
.....
...