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

@ControllerAdvice throws java.lang.IllegalStateException: DataBinder is already initialized - call setAutoGrowNestedPaths before other configuration methods [SPR-9818] #14451

Closed
spring-projects-issues opened this issue Sep 21, 2012 · 9 comments
Assignees
Labels
in: web status: declined

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Sep 21, 2012

Marcel Overdijk opened SPR-9818 and commented

I'm trying to change the 'AutoGrowNestedPaths' globally using a @ControllerAdvice as:

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

@ControllerAdvice
public class DisableAutoGrowNestedPaths {

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.setAutoGrowNestedPaths(false);
	}
}

but I get this exception:

ava.lang.IllegalStateException: DataBinder is already initialized - call setAutoGrowNestedPaths before other configuration methods at org.springframework.util.Assert.state(Assert.java:384) at org.springframework.validation.DataBinder.setAutoGrowNestedPaths(DataBinder.java:196) at org.mycom.web.DisableAutoGrowNestedPaths.initBinder(GlobalTest.java:13) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) at org.springframework.web.method.annotation.InitBinderDataBinderFactory.initBinder(InitBinderDataBinderFactory.java:62) at org.springframework.web.bind.support.DefaultDataBinderFactory.createBinder(DefaultDataBinderFactory.java:52) at org.springframework.web.method.annotation.ModelFactory.updateBindingResult(ModelFactory.java:222) at org.springframework.web.method.annotation.ModelFactory.updateModel(ModelFactory.java:206) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.getModelAndView(RequestMappingHandlerAdapter.java:814) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:723) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:660) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:804) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:789) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:170) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:90) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:90) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:90) 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:191) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 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:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:680) 500.jsp

Note that when I move this @InitBinder to a controller I get the same exception.

I'm using a Java config setup using WebMvcConfigurerAdapter with only basic configurations.

On a related note I wonder if there is a better way to set the 'AutoGrowNestedPaths' globally, e.g. in my WebConfig.java WebMvcConfigurerAdapter?


Affects: 3.2 M2, 4.0 RC2

Referenced from: commits spring-attic/spring-framework-issues@7b8508d

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 24, 2012

Marcel Overdijk commented

Note that I'm not using @ControllerAdvise at the moment/anymore.
I went for this approach in my WebConfig:

@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
    RequestMappingHandlerAdapter bean = super.requestMappingHandlerAdapter();
    ConfigurableWebBindingInitializer webBindingInitializer = (ConfigurableWebBindingInitializer) bean.getWebBindingInitializer();
    webBindingInitializer.setAutoGrowNestedPaths(false); // Unfortunately it's currently not supported to configure the WebBindingInitializer directly (SPR-8984)
    return bean;
}

Although this does the job it's not the most beautiful solution imo.
As suggested in #13624 it would make sense to provide something like:

public void configureWebBindingInitializer(ConfigurableWebBindingInitializer initializer) { .. }

in WebMvcConfigurationSupport.

This would be in line with other confgureX methods in WebMvcConfigurationSupport. I'm reopening #13624 to start discussion again.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 29, 2012

Rossen Stoyanchev commented

I've created a sample projectthat sets the autoGrowthNestedPath property from an @ControllerAdvice class and it succeeds. Can you compare this to your code and help with reproducing the issue?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 5, 2013

Rossen Stoyanchev commented

Resolving until further information is provided.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 14, 2013

David Melia commented

Hi,

I have just started using the new @ControllerAdvice annotation and I get the above error. I have cloned this from the above GIT repo and recreated in:

https://github.com/mzz6wh/spring-framework-issues/tree/master/SPR-9818

Seems to be a combination of using @ControllerAdvice with @InitBinder and registering a customer editor + having another controller specific @InitBinder which sets the setAutoGrowNestedPaths property. This error also occurs after the controller method has finished.

Any ideas?

Thanks

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 15, 2013

Rossen Stoyanchev commented

Thanks for the repro project, will have a look.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Mar 28, 2014

Sébastien Deleuze commented

Hi,

I have tested your repo project, thanks for providing it.

Since the same WebDataBinder instance is injected in both @InitBinder annotated method, the setAutoGrowNestedPaths() must be called before any other configuration method. But @ControllerAdvice + @InitBinder annotated method define a general behavior and so is ran before your controller specific @InitBinder, I think this is the expected behavior.

In order to avoid the IllegalStateException, you need to call setAutoGrowNestedPaths() before registerCustomEditor(), for example by moving setAutoGrowNestedPaths() call in the @ControllerAdvice annotated class.

Is this proposed approach fine for you ?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Mar 28, 2014

David Melia commented

Hi Sebastien,

So I want to use @ControllerAdvice for my global init binder config but at a controller level setAutoGrowNestedPaths() i.e. I don't always want to setAutoGrowNestedPaths(). If I set setAutoGrowNestedPaths() globally across all my existing controllers I start to get unexpected behaviour (e.g. s java.lang.IndexOutOfBoundsException).

Obviously it's up to you whether this is working as spec but just doesn't seem correct as my use case now means I cannot use a global init binder via @ControllerAdvice.

Thanks

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Mar 28, 2014

Rossen Stoyanchev commented

The order of invocation is quite clear with @ControllerAdvice getting invoked first so setting autoGrow locally just isn't going to work. In 4.0 we enhanced @ControllerAdvice to be able to apply it to a subset of controllers in a variety of ways. So consider having two @ControllerAdvice types. There is really nothing I can see that we can do here.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Mar 28, 2014

David Melia commented

OK no problem. I didn't realise that Spring 4.0 allowed for a subset of controllers which will actually solve my issue.

Thanks

@spring-projects-issues spring-projects-issues added type: bug status: declined in: web labels Jan 11, 2019
@spring-projects-issues spring-projects-issues removed the type: bug label Jan 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web status: declined
Projects
None yet
Development

No branches or pull requests

2 participants