简体   繁体   English

Autowired Repository在自定义约束验证器中为空

[英]Autowired Repository is Null in Custom Constraint Validator

I have a Spring based webapp. 我有一个基于Spring的webapp。 I am using several repository classes with annotations @Repository, @Transactional in my Controllers. 我在控制器中使用了几个带注释@Repository,@ Transaction的存储库类。 That part works fine. 那部分工作正常。

I created a Custom Constraint Validator which has to access the repository. 我创建了一个Custom Constraint Validator,它必须访问存储库。 Now I am not able to understand why the Repository is null. 现在我无法理解为什么Repository为null。 I tried annotating the validator with @Component annotation. 我尝试使用@Component注释来注释验证器。 My base package containing all these classes is in the part of the xml. 我的基本包包含所有这些类是在xml的一部分。 So what else should I do to ensure the repository dependency injection works. 那么我还应该做些什么来确保存储库依赖注入工作。 This is how my Constraint validator looks like. 这就是我的Constraint验证器的样子。

public class DonorTypeExistsConstraintValidator implements
    ConstraintValidator<DonorTypeExists, DonorType> {

  @Autowired
  private DonorTypeRepository donorTypeRepository;

  @Override
  public void initialize(DonorTypeExists constraint) {

  }

  public boolean isValid(DonorType target, ConstraintValidatorContext context) {

   System.out.println("donorType: " + target);
   if (target == null)
     return true;

   try {
    if (donorTypeRepository.isDonorTypeValid(target.getDonorType()))
     return true;
   } catch (Exception e) {
    e.printStackTrace();
   }
   return false;
  }

  public void setDonorRepository(DonorTypeRepository donorTypeRepository) {
    this.donorTypeRepository = donorTypeRepository;
  }
}

Update 更新

Package scan configuration: 包扫描配置:

<context:annotation-config />

<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />

<context:component-scan base-package="controller" />
<context:component-scan base-package="repository" />
<context:component-scan base-package="model" />
<context:component-scan base-package="viewmodel" />

This class is in the package model.donortype. 此类在包model.donortype中。 The repository is in the package repository. 存储库位于包存储库中。

Update 更新

Something more puzzling, removing all preinsert listeners (in this case only BeanValidationEventListener) fixes the autowiring issue. 更令人费解的是,删除所有preinsert侦听器(在这种情况下只有BeanValidationEventListener)修复了自动装配问题。 This has complicated the matter even more. 这使事情变得更加复杂。

I am not even inserting the BeanValidationEventListener as described in the answer below. 我甚至没有插入BeanValidationEventListener,如下面的答案所述。 This is infact contrary to the suggestion here: JSR-303 dependency injection and Hibernate 这与此处的建议相反: JSR-303依赖注入和Hibernate

  @Override
  public void integrate(Configuration configuration, SessionFactoryImplementor implementor,
                        SessionFactoryServiceRegistry registry) {
      logger.info("Registering event listeners");
      System.out.println("here");
      // you can add duplication strategory for duplicate registrations

      final EventListenerRegistry eventRegistry = registry.getService(EventListenerRegistry.class);
      // prepend to register before or append to register after
      // this example will register a persist event listener

      eventRegistry.prependListeners(EventType.PERSIST, EntitySaveListener.class);
      eventRegistry.appendListeners(EventType.MERGE, EntitySaveListener.class);
      Iterator<PreInsertEventListener> iter = eventRegistry.getEventListenerGroup(EventType.PRE_INSERT).listeners().iterator();
      while (iter.hasNext()) {
        PreInsertEventListener el = iter.next();
        System.out.println(el.getClass());
        BeanValidationEventListener listener = (BeanValidationEventListener) el;
        System.out.println(listener);
        iter.remove();
      }
  }

Update 更新

I am using JPA. 我正在使用JPA。 I have a backing form for the JPA entities. 我有JPA实体的支持表格。 In the controller I use InitBinder to instantiate a custom validator binder.setValidator(new EntityBackingFormValidator(binder.getValidator())); 在控制器中,我使用InitBinder实例化自定义验证器binder.setValidator(new EntityBackingFormValidator(binder.getValidator())); . Here is the code for this: https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/controller/CollectedSampleController.java 以下是此代码: https//github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/controller/CollectedSampleController.java

This custom validator invokes the validation on the default validator and leaves scope to do some custom validations. 此自定义验证程序在默认验证程序上调用验证,并使作用域执行一些自定义验证。 https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/model/collectedsample/CollectedSampleBackingFormValidator.java https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/model/collectedsample/CollectedSampleBackingFormValidator.java

I am using annotations within the entity to create constraints. 我在实体中使用注释来创建约束。 Apart from the default constraints, I need to define constraints that check whether a entity at the other side of a many-to-one mapping exists or not. 除了默认约束之外,我还需要定义约束,以检查多对一映射的另一侧是否存在实体。 Here is the custom constraint validator. 这是自定义约束验证器。 https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/model/donor/DonorExistsConstraintValidator.java https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/model/donor/DonorExistsConstraintValidator.java

Now the autowired repository in this custom constraint validator is null. 现在,此自定义约束验证程序中的自动装入的存储库为null。 I am trying to customize code in my CustomIntegrator which is present here https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/interceptor/CustomIntegrator.java 我想在我的CustomIntegrator中自定义代码,这里的代码存在于https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/interceptor/CustomIntegrator.java

and the xml configuration file present here https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/war/WEB-INF/v2v-servlet.xml 这里出现的xml配置文件https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/war/WEB-INF/v2v-servlet.xml

Hopefully the actual code will help you to answer my question. 希望实际的代码可以帮助您回答我的问题。 Thanks! 谢谢!

Which ValidatorFactory are you using. 你使用哪个ValidatorFactory Or to put it another way, hot to you bootstrap Bean Validation? 或者换句话说,热门你引导Bean Validation? Per default Bean Validation (and Hibernate Validator as reference implentation) does not inject dependencies into ConstraintValidator instances. 默认的Bean Validation(和Hibernate Validator作为参考实现)不会将依赖注入ConstraintValidator实例。 At least in Bean Validation 1.0. 至少在Bean Validation 1.0中。

To enable dependency injection you have to configure a custom ConstraintValidatorFactory . 要启用依赖项注入,您必须配置自定义ConstraintValidatorFactory Spring offers SpringConstraintValidatorFactory which is the default when using LocalValidatorFactoryBean - see http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch05s07.html Spring提供了SpringConstraintValidatorFactory ,这是使用LocalValidatorFactoryBean时的默认值 - 请参阅http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch05s07.html

Also, are you using JPA? 另外,你使用JPA吗? I assume so, in which case auto validation on life cycle events automatically. 我假设,在这种情况下自动验证生命周期事件。 Instead of trying to remove event listeners you can just use the property javax.persistence.validation.mode and set it to NONE. 您可以只使用属性javax.persistence.validation.mode并将其设置为NONE,而不是尝试删除事件侦听器。 I am wondering whether the right validator is used on life cycle based validation. 我想知道是否在基于生命周期的验证中使用了正确的验证器。

It would all depend on your overall Spring configuration and use. 这完全取决于您的整体Spring配置和使用情况。

Do you pass the validator factory to be used by JPA when performing validation: 在执行验证时,您是否通过了验证工厂以供JPA使用:

<bean 
    id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaPropertyMap">
        <map>
            <entry 
                key="javax.persistence.validation.factory"
                value-ref="validator"/>
            <!-- ... -->
        </map>
    </property>
    <!-- ... -->
</bean>

That's required since otherwise the default factory (as specified in validation.xml ) would be used by JPA. 这是必需的,否则JPA将使用默认工厂(在validation.xml中指定)。

Do you have an @Component annotation on the DonorTypeExistsConstraintValidator? 你在DonorTypeExistsConstraintValidator上有@Component注释吗?

That has killed me in the past. 这在过去杀了我。

No luck with LocalValidatorFactoryBean. LocalValidatorFactoryBean没有运气。 I have done some hack to solve this problem. 我已经做了一些黑客来解决这个问题。

@Component
public class ServiceUtils
{
    private static ServiceUtils instance;

    @Autowired
    private ListableBeanFactory factory;

    @PostConstruct
    public void init()
    {
        instance = this;
    }

    public static ListableBeanFactory getFactory()
    {
        return instance.factory;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM