2013-08-24 67 views
0

我使用Spring MVC与Hibernate开发Web应用程序。起初我只使用标准的JSR303注释。然后,我决定使用一些自定义注释来验证新用户的用户名和电子邮件的唯一性,他们希望创建一个帐户。Spring MVC自定义验证注释与服务@Autowired

所以我创建了两个注解像这样的(一个FR的电子邮件和其他的用户名):

@Documented 
@Constraint(validatedBy = UniqueUsernameConstraintValidator.class) 
@Target({ ElementType.METHOD, ElementType.FIELD }) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface UniqueUsername { 

String message() default "{UniqueUsername}"; 

Class<?>[] groups() default {}; 

Class<? extends Payload>[] payload() default {}; 

} 

和两个验证像这样的:

public class UniqueUsernameConstraintValidator implements ConstraintValidator<UniqueUsername, String> { 

@SuppressWarnings("unused") 
private static final Logger logger = LoggerFactory.getLogger(UniqueUsernameConstraintValidator.class); 

@Autowired 
private UserService userService; 

@Override 
public void initialize(UniqueUsername uu) { } 

@Override 
public boolean isValid(String username, ConstraintValidatorContext cxt) { 
    if(username == null) { 
     return false; 
    } 
    return userService.findByUsername(username) == null; 
} 

}

我只发布了一个,因为这两个真的很相似。

注释@UniqueUsername和@UniqueEmail在电子邮件或用户名不唯一时发挥作用,并发送正确的验证错误消息。但是,当我给一个用户名和一个尚未使用的电子邮件时,那么我在userService上有一个空指针错误。

我不明白为什么我会对@Autowired注释产生一些空问题。但真正令人感兴趣的是为什么IsValid()方法(它给了我空的异常)会被第二次调用,或者至少看起来会发生什么,因为验证步骤似乎有效。

以下是错误:

java.lang.NullPointerException 
com.sam.website.custom.validators.UniqueUsernameConstraintValidator.isValid(UniqueUsernameConstraintValidator.java:30) 
com.sam.website.custom.validators.UniqueUsernameConstraintValidator.isValid(UniqueUsernameConstraintValidator.java:1) 
org.hibernate.validator.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:153) 
org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:140) 
org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:121) 
org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:327) 
org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:273) 
org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:256) 
org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:210) 
org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119) 
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:136) 
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:94) 
org.hibernate.action.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:160) 
org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:65) 
org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273) 
org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:320) 
org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203) 
org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129) 
org.hibernate.ejb.event.EJB3MergeEventListener.saveWithGeneratedId(EJB3MergeEventListener.java:62) 
org.hibernate.event.def.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:415) 
org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:341) 
org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:303) 
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:258) 
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) 
org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:867) 
org.hibernate.impl.SessionImpl.merge(SessionImpl.java:851) 
org.hibernate.impl.SessionImpl.merge(SessionImpl.java:855) 
org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:686) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:601) 
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
$Proxy39.merge(Unknown Source) 
org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:360) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:601) 
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333) 
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
$Proxy41.save(Unknown Source) 
com.sam.website.services.jpa.UserServiceJpa.save(UserServiceJpa.java:53) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:601) 
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
$Proxy46.save(Unknown Source) 
com.sam.website.controllers.SecurityController.register(SecurityController.java:63) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:601) 
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213) 
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126) 
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96) 
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617) 
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578) 
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923) 
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852) 
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) 
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:647) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) 
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) 
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) 
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 

这里是我的自定义注解

@UniqueUsername 
@NotEmpty 
@Size(min=3) 
@Column(name="username",unique=true) 
public String getUsername() { 
    return username; 
} 

在这里,我的配置使用情况

<!-- Validator settings --> 
<annotation-driven validator="validator"/> 

<beans:bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
    <beans:property name="validationMessageSource" ref="messageSource"/> 
</beans:bean> 
+0

如何创建'UniqueUsernameConstraintValidator'? –

+0

我不创建它,我只是将我的注释添加到用户对象中的用户名属性。我刚刚编辑了我的问题,并使用了UniqueUsername – sam

+0

我的意思是你在哪里声明它?在一些春天的情况下?实例来自哪里? –

回答

2

的解决方案终于禁用JPA验证,因为它被用来代替Hibernate验证,所以Spring注入是无效的。所以我只是添加在我的JPA配置中:

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    ... 
    <property name="jpaPropertyMap"> 
     <map> 
      <entry 
       key="javax.persistence.validation.mode" value="NONE"/> 
     </map> 
    </property> 
</bean>