自定义存储库在自定义约束验证器中为空 [英] Autowired Repository is Null in Custom Constraint Validator

查看:89
本文介绍了自定义存储库在自定义约束验证器中为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于Spring的webapp。我在控制器中使用了多个存储库类,注释@Repository,@Transactional。这部分工作正常。



我创建了一个必须访问存储库的自定义约束验证器。现在我无法理解为什么存储库是空的。我试着用@Component注释来注释验证器。包含所有这些类的基本包位于xml的一部分中。那么我还应该做些什么来确保存储库依赖注入的工作。这是我的约束验证器的样子。

  public class DonorTypeExistsConstraintValidator implements 
ConstraintValidator< DonorTypeExists,DonorType> {

@Autowired
私人DonorTypeRepository donorTypeRepository;

@Override
public void initialize(DonorTypeExists constraint){
$ b}

public boolean isValid(DonorType target,ConstraintValidatorContext context){

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

尝试{
if(donorTypeRepository.isDonorTypeValid(target.getDonorType()))
return true;
} catch(Exception e){
e.printStackTrace();
}
返回false;
}

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


更新



打包扫描配置:

 < context:annotation-config /> 

<! - 配置@Controller编程模型 - >
< 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/>

该类位于model.donortype包中。
存储库位于软件包存储库中。



更新

更令人费解的是,删除所有preinsert侦听器(在本例中只有BeanValidationEventListener)修复了自动装配问题。这使得问题更加复杂。



我甚至没有插入BeanValidationEventListener,如下面的答案中所述。这实际上与这里的建议相反:
依赖注入和Hibernate的JSR-303依赖注入和hibernate的hibernate / jsr-303-dependency-injection-and-hibernate\">

  @Override 
public void integrate(配置配置,SessionFactoryImplementor实现者,
SessionFactoryServiceRegistry注册表){
logger.info(注册事件监听器);
System.out.println(here);
//您可以为重复注册添加重复策略

final EventListenerRegistry eventRegistry = registry.getService(EventListenerRegistry.class);
// prepend在注册之前注册或追加注册
之后//此示例将注册持久性事件侦听器

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监听器=(BeanValidationEventListener)el;
System.out.println(listener);
iter.remove();


更新



我正在使用JPA。我有JPA实体的支持表格。在控制器中,我使用InitBinder来实例化一个自定义验证器 binder.setValidator(new EntityBackingFormValidator(binder.getValidator()));
以下是此代码:
https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/controller/CollectedSampleController.java



这个自定义验证器调用验证默认验证程序并保留范围以执行一些自定义验证。
https://github.com/ C4G / V2V / blob / 87dc266043f6d623c101d947a88fa0b0ad536355 / src / model / collectedsample / CollectedSampleBackingFormValidator.java



我使用实体内的注释来创建约束。除了默认约束之外,我需要定义约束来检查多对一映射另一端的实体是否存在。
这是自定义约束验证器。
https://github.com/ C4G / V2V / blob / 87dc266043f6d623c101d947a88fa0b0ad536355 / src / model / donor / DonorExistsConstraintValidator.java


现在,此自定义约束验证程序中的自动装载存储库为空。我正在尝试在我的CustomIntegrator中自定义代码,这里存在
https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/interceptor/CustomIntegrator.java



和xml配置文件目前在这里
https:// github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/war/WEB-INF/v2v-servlet.xml



希望实际的代码能帮助你回答我的问题。
谢谢!

解决方案

您正在使用哪个 ValidatorFactory 。或者换一种说法,对你的bootstrap Bean Validation感兴趣?默认的Bean Validation(和Hibernate Validator作为参考实现)不会将依赖注入到 ConstraintValidator 实例中。至少在Bean Validation 1.0中。

要启用依赖注入,您必须配置一个自定义的 ConstraintValidatorFactory 。 Spring提供 SpringConstraintValidatorFactory ,这是使用 LocalValidatorFactoryBean 时的默认值 - 请参阅 http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch05s07.html



另外,您是否使用JPA?我认为是这样,在这种情况下自动对生命周期事件进行自动验证。您可以使用属性 javax.persistence.validation.mode 并将其设置为NONE,而不是尝试删除事件侦听器。我想知道是否在基于生命周期的验证中使用了正确的验证器。



这将取决于您的整体Spring配置和使用情况。

I have a Spring based webapp. I am using several repository classes with annotations @Repository, @Transactional in my Controllers. That part works fine.

I created a Custom Constraint Validator which has to access the repository. Now I am not able to understand why the Repository is null. I tried annotating the validator with @Component annotation. My base package containing all these classes is in the part of the xml. So what else should I do to ensure the repository dependency injection works. This is how my Constraint validator looks like.

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. The repository is in the package repository.

Update

Something more puzzling, removing all preinsert listeners (in this case only BeanValidationEventListener) fixes the autowiring issue. This has complicated the matter even more.

I am not even inserting the BeanValidationEventListener as described in the answer below. This is infact contrary to the suggestion here: JSR-303 dependency injection and 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. I have a backing form for the JPA entities. In the controller I use InitBinder to instantiate a custom validator binder.setValidator(new EntityBackingFormValidator(binder.getValidator()));. Here is the code for this: 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

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

Now the autowired repository in this custom constraint validator is 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

and the xml configuration file present here 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. Or to put it another way, hot to you bootstrap Bean Validation? Per default Bean Validation (and Hibernate Validator as reference implentation) does not inject dependencies into ConstraintValidator instances. At least in Bean Validation 1.0.

To enable dependency injection you have to configure a custom 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

Also, are you using 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. 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.

这篇关于自定义存储库在自定义约束验证器中为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆