Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@RequestParam fails when ConfigurableWebBindingInitializer has both messageCodesResolver and conversionService [SPR-7590] #12246

Closed
spring-projects-issues opened this issue Sep 24, 2010 · 4 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Oliver Stacey opened SPR-7590 and commented

I'm seeing an issue that I think is a result of a bug.

I have an AnnotationMethodHandlerAdapter configured thus:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"
p:messageCodesResolver-ref="messageCodesResolver"
p:conversionService-ref="conversionService" />
</property>
</bean>

I also have a controller method with the following signature:

@RequestMapping(value="/account/name", method = RequestMethod.POST)
public String setName(@RequestParam("name") String name, ModelMap model) {

When this method is invoked, I see a stack trace that looks like:

java.lang.IllegalStateException: Cannot access properties on null bean instance 'name'!
org.springframework.util.Assert.state(Assert.java:384)
org.springframework.validation.BeanPropertyBindingResult.createBeanWrapper(BeanPropertyBindingResult.java:99)
org.springframework.validation.BeanPropertyBindingResult.getPropertyAccessor(BeanPropertyBindingResult.java:87)
org.springframework.validation.AbstractPropertyBindingResult.initConversion(AbstractPropertyBindingResult.java:60)
org.springframework.validation.DataBinder.setConversionService(DataBinder.java:501)
org.springframework.web.bind.support.ConfigurableWebBindingInitializer.initBinder(ConfigurableWebBindingInitializer.java:167)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.initBinder(HandlerMethodInvoker.java:376)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestParam(HandlerMethodInvoker.java:505)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:339)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:170)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:421)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:409)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

What I believe is happening here is as follows:

  • The handler adapter delegates to HandlerMethodInvoker, which attempts to resolve the @RequestParam argument.
  • HandlerMethodInvoker creates a WebRequestDataBinder with a null target.
  • HandlerMethodInvoker then delegates to ConfigurableWebBindingInitializer.initBinder() to initialize the new binder
    • this method in turn calls DataBinder.setMessageCodesResolver(). As a side effect of setting the message code resolver, a BeanPropertyBindingResult is created inside the DataBinder; this also has a null target.
    • then DataBinder.setConversionService() is called, which in turn calls BeanPropertyBindingResult.initConversionService(), which fails with the above exception because the target of the binding result is null.

It seems that the intention here is to support the "null target" case inside WebRequestDataBinder by making sure that bindingResult is never created. However, in this case the binder is accidentally created anyway.

I've attached a patch that overrides setMessageCodesResolver() in WebRequestDataBinder and changes it into a no-op when target is null. This seems like the cleanest simple fix. This should be applied to /trunk/org.springframework.web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java

However, I think there's an inherent contradiction between the approaches taken by DataBinder and WebRequestDataBinder that is likely to generate more bugs in the future. DataBinder seems to be written with the idea that its bindingResult is "lazy loaded"; WebRequestDataBinder supports a case where the bindingResult should never be created. It seems like great care will need to be taken to ensure that no stray calls into DataBinder result in the creation of an unwanted bindingResult.


Affects: 3.0 GA, 3.0.1, 3.0.2, 3.0.3, 3.0.4

Attachments:

@spring-projects-issues
Copy link
Collaborator Author

Oliver Stacey commented

Patch should be applied to:
/trunk/org.springframework.web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java

Was created against Revision 3691.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This should be fixed in 3.0.4 already, actually, through a change in AbstractPropertyBindingResult's initConversion method. If you can indeed reproduce this against 3.0.4 (I couldn't), then please reopen this issue...

Juergen

@spring-projects-issues
Copy link
Collaborator Author

liu commented

java.lang.IllegalStateException: Cannot access properties on null bean instance 'command'! at org.springframework.util.Assert.state(Assert.java:384) at org.springframework.validation.BeanPropertyBindingResult.createBeanWrapper(BeanPropertyBindingResult.java:104) at org.springframework.validation.BeanPropertyBindingResult.getPropertyAccessor(BeanPropertyBindingResult.java:91) at org.springframework.validation.DataBinder.getPropertyAccessor(DataBinder.java:267) at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:692) at org.springframework.validation.DataBinder.doBind(DataBinder.java:588) at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:191) at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:111) at org.springframework.web.servlet.mvc.multiaction.MultiActionController.bind(MultiActionController.java:532) at bc.engine.common.web.AbstractAppController.bindForm(AbstractAppController.java:53) at bc.engine.common.web.AbstractSessionBasedAppController.index(AbstractSessionBasedAppController.java:50) at sun.reflect.GeneratedMethodAccessor737.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:471) at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:408) at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153) at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574) at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:159) at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153) at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574) at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.extremecomponents.table.filter.AbstractExportFilter.doFilter(Unknown Source) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at bc.engine.common.filter.SetRequestEncodingFilter.doFilter(SetRequestEncodingFilter.java:39) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:119) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:595)

很抱歉,我英文很烂,谁能帮我翻译一下呢?我在Springframework3.0.7发现了同样的问题

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Re-resolving for now. Please open a new issue complete with reproduction steps (and preferably a self-contained reproduction project) if this is still a problem for you against the latest 3.0.x release (3.0.6) and/or Spring 3.1.0.

@spring-projects-issues spring-projects-issues added type: bug A general bug in: core Issues in core modules (aop, beans, core, context, expression) in: web Issues in web modules (web, webmvc, webflux, websocket) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 3.0.4 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants