Java – @ Autowired bean used with @ valid on the controller but failed in the crud repository

I am using the user registration form to process the spring MVC hibernate JPA application. I decided to use the jsr-303 authenticator to check whether the user name already exists in the DB:

public class UniqueUsernameValidator implements ConstraintValidator<VerifyUniqueUsername,String> {

    @Autowired
    UserService userService;

    @Override
    public void initialize(VerifyUniqueUsername constraintAnnotation) {     
    }

    @Override
    public boolean isValid(String username,ConstraintValidatorContext context) {                       

        return  username!=null &&  userService.findByUsername(username) == null;        
    }
}

It is very simple to verify that it works well on my controller:

....
    public String signup(@Valid @modelattribute("newUser") User user,BindingResult newUserBeanResult)
.....

The current problem I face is that after I verify the user object, I call:

userService.save(user);

Which implements crudrepository, I get a NullPointerException For some reason, userservice is injected during validation on the controller, but when calling crudrepository Not when save()

I see similar posts as follows: @ Autowired bean null in constraintvalidator when invoked by sessionfactory getCurrentSession. Merge also has this: Hibernate validator without using autowire, but I want to know if anyone has encountered this before I think it is quite common to inject beans to access the database on the validator

As a solution, I added a null check on userservice, but it didn't feel right

>Is this expected behavior? When calling crudrepository Will these validations be activated before save() Would I like to handle "manual" hibernation events? In this case, pre insert

Solution

I finally solved this problem by instructing spring's entitymanagerfactorybean to use my validator bean (more precisely, hibernate will now use spring's validator):

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>        
        <property name="packagesToScan" value="some.packages"/>
        <property name="jpaPropertyMap">
            <map>
                <entry key="javax.persistence.validation.factory" value-ref="validator"  />           
            </map>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MysqLDialect</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.jdbc.fetch_size">50</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
                <prop key="hibernate.show_sql">true</prop>              
            </props>        
        </property>
    </bean>

However, this raises a stackoverflow error:)

Obviously, the reason for this problem is that my verifier uses the finder method (findbyusername), which triggers hibernate flush, which in turn triggers authentication This infinite loop until you get the most famous exception

So... I solved this problem by changing the verifier to use entitymanager directly (instead of crud repository) and temporarily changing the flushmodetype to commit Here is an example:

public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername,String> {

    @PersistenceContext
    private EntityManager em;

    @Autowired
    UserService userService;

    @Override
    public void initialize(UniqueUsername constraintAnnotation) {       
    }

    @Override
    public boolean isValid(String username,ConstraintValidatorContext context) {
        try { 
            em.setFlushMode(FlushModeType.COMMIT);          
            return userService.findByUsername(username) == null;

            } finally { 
           em.setFlushMode(FlushModeType.AUTO);
           }    
    }
}

This solves the problem that the verifier uses the finder function to trigger hibernate flush, which triggers the verifier, resulting in stackoverflowerror

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>