2013-08-24 58 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>