使用嵌套数组路径的spring boot jsr 303验证失败

时间:2015-08-28 06:21:49

标签: spring-boot spring-data bean-validation

相关依赖版本

Spring Boot 1.2.5.RELEASE 
spring-data-releasetrain.version - Fowler-RELEASE
hibernate-validator - 5.1.3.Final
spring-context - 4.1.7.RELEASE


class EmployeeDTO {
  @Valid
  List<EducationQualification> educationalQualifications
}

class EmployeeResource {
    public ResponseEntity<EmployeeDTO>
    create(@Valid @RequestBody 
    EmployeeDTO employeeDTO) throws URISyntaxException, ProgramException {

}

对于其中一个EducationalQualifications中的错误,我正在获得IllegalStateException

  

java.lang.IllegalStateException:JSR-303验证属性&#39; educationQualifications [1] .numberOfYears&#39;没有相应的Spring数据绑定访问器 - 检查DataBinder的配置(bean属性与直接字段访问)

查看代码,问题似乎出现在支票!field.contains("[]")中。不应该检查&#39; [&#39;之间的索引的可能性。和&#39;]&#39;。

如何解决这个问题?请帮忙。

package package org.springframework.validation.beanvalidation;
class SpringValidatorAdapter {
    protected void processConstraintViolations(Set<ConstraintViolation<Object>>   violations, Errors errors) {
    ...
    if (!"".equals(field) && (invalidValue == violation.getLeafBean() ||
        (field.contains(".") && !field.contains("[]")))) {
        // Possibly a bean constraint with property path: retrieve the actual property value.
        // However, explicitly avoid this for "address[]" style paths that we can't handle.
        invalidValue = bindingResult.getRawFieldValue(field);
    } 
    ...
}

下面的跟踪:

java.lang.IllegalStateException: JSR-303 validated property 'educationalQualifications[1].numberOfYears' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)
    at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations(SpringValidatorAdapter.java:158) ~[spring-context-4.1.7.RELEASE.jar:na]
    at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:107) ~[spring-context-4.1.7.RELEASE.jar:na]
    at org.springframework.validation.DataBinder.validate(DataBinder.java:782) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at o.s.w.s.m.method.annotation.AbstractMessageConverterMethodArgumentResolver.validateIfApplicable(AbstractMessageConverterMethodArgumentResolver.java:188) ~[spring-webmvc-4.1.7.RELEASE.jar:na]
    at o.s.w.s.m.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:106) ~[spring-webmvc-4.1.7.RELEASE.jar:na]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) ~[spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129) ~[spring-web-4.1.7.RELEASE.jar:na]
    at o.s.w.s.m.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.1.7.RELEASE.jar:na]
    at o.s.w.s.m.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776) ~[spring-webmvc-4.1.7.RELEASE.jar:na]
    at o.s.w.s.m.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705) ~[spring-webmvc-4.1.7.RELEASE.jar:na]
    at o.s.w.s.m.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.1.7.RELEASE.jar:na]
    at o.s.w.s.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at o.s.w.s.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at o.s.w.s.FrameworkServlet.processRequest(FrameworkServlet.java:967) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at o.s.w.s.FrameworkServlet.doPost(FrameworkServlet.java:869) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) ~[servlet-api.jar:na]
    at o.s.w.s.FrameworkServlet.service(FrameworkServlet.java:843) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[servlet-api.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:104) [metrics-servlet-3.1.2.jar:3.1.2]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:295) [spring-boot-actuator-1.2.5.RELEASE.jar:1.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176) [spring-security-oauth2-2.0.7.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) [spring-security-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) [spring-security-web-4.0.1.RELEASE.jar:na]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) [spring-security-web-4.0.1.RELEASE.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102) [spring-boot-actuator-1.2.5.RELEASE.jar:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85) [spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:116) [spring-boot-1.2.5.RELEASE.jar:na]
    at org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:60) [spring-boot-1.2.5.RELEASE.jar:na]
    at org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:91) [spring-boot-1.2.5.RELEASE.jar:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:na]
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:109) [spring-boot-1.2.5.RELEASE.jar:na]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at com.hazelcast.web.WebFilter.doFilter(WebFilter.java:353) [hazelcast-wm-3.5.1.jar:3.5.1]
    at o.a.c.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.24]
    at o.a.c.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.24]
    at o.a.c.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.24]
    at o.a.c.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.24]
    at o.a.c.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.24]
    at o.a.c.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.24]
    at o.a.c.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.24]
    at o.a.c.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617) [catalina.jar:8.0.24]
    at o.a.c.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.24]
    at o.a.c.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [catalina.jar:8.0.24]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-coyote.jar:8.0.24]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) [tomcat-coyote.jar:8.0.24]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1527) [tomcat-coyote.jar:8.0.24]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1484) [tomcat-coyote.jar:8.0.24]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.24]
    at java.lang.Thread.run(Thread.java:744) [na:1.8.0]
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'educationalQualifications[1]' of bean class [com.sensei.ignition.web.rest.dto.EmployeeDTO]: Bean property 'educationalQualifications[1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:731) ~[spring-beans-4.1.7.RELEASE.jar:na]
    at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:572) ~[spring-beans-4.1.7.RELEASE.jar:na]
    at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:549) ~[spring-beans-4.1.7.RELEASE.jar:na]
    at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:720) ~[spring-beans-4.1.7.RELEASE.jar:na]
    at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:99) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.validation.AbstractBindingResult.getRawFieldValue(AbstractBindingResult.java:283) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations(SpringValidatorAdapter.java:143) ~[spring-context-4.1.7.RELEASE.jar:na]

1 个答案:

答案 0 :(得分:1)

根据您共享的代码片段判断,看起来Spring MVC的DataBinder配置为使用bean属性(getter和setter),而educationQualifications只能通过直接字段访问获得。你有几个选择:

  1. 使用直接字段访问的DataBinder配置Spring MVC
  2. 为educationQualifications添加getter