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

LocaleResolver (MVC) and LocaleContextResolver (WebFlux) beans will back off if a user provides a bean of the same type and a custom name but Framework will then use its own default #24209

Closed
wilkinsona opened this issue Nov 19, 2020 · 6 comments
Assignees
Milestone

Comments

@wilkinsona
Copy link
Member

@wilkinsona wilkinsona commented Nov 19, 2020

While looking at #24207, I noticed that our overrides of the localeResolver() (MVC) and localeContextResolver() (WebFlux) methods will back off if any LocaleResolver or LocaleContextResolver bean is present (they're annotated with a plain @ConditionalOnMissingBean) but Framework consumes these beans using a specific name. This means that a user may provide a custom bean with a non-standard name and our auto-configuration will back off, but Framework will then use its default rather than the user's bean. If you're trying to figure out what's happened, the condition evaluation report won't help much as it'll show that the auto-configured resolver backed off in favour of the user-provided resolver but won't explain why the user-provided resolver wasn't used.

I am wondering if our auto-configured beans should only back off when a bean of the name that Framework looks for is defined:

@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)

This would make the condition evaluation report more useful as it will show that the auto-configured bean was configured as no bean with a specific name was found in the context.

@wilkinsona wilkinsona changed the title LocaleResolver (MVC) and LocaleContextResolver (WebFlux) beans will back off if a user provides a bean of the same type but Framework will then use its own default LocaleResolver (MVC) and LocaleContextResolver (WebFlux) beans will back off if a user provides a bean of the same type and a custom name but Framework will then use its own default Nov 19, 2020
@philwebb
Copy link
Member

@philwebb philwebb commented Nov 19, 2020

I think we probably should. I'd even say this is a bug and should perhaps be fixed in 2.2.x

@wilkinsona wilkinsona changed the title LocaleResolver (MVC) and LocaleContextResolver (WebFlux) beans will back off if a user provides a bean of the same type and a custom name but Framework will then use its own default LocaleResolver bean will back off if a user provides a bean of the same type and a custom name but Framework will then use its own default Nov 20, 2020
@wilkinsona
Copy link
Member Author

@wilkinsona wilkinsona commented Nov 20, 2020

The LocaleContextResolver problem is specific to 2.4.0. I'll fix the MVC side of things in 2.2.x and 2.3.x and both in 2.4.x.

@wilkinsona wilkinsona added this to the 2.2.x milestone Nov 20, 2020
@wilkinsona
Copy link
Member Author

@wilkinsona wilkinsona commented Nov 20, 2020

In 2.2 and 2.3 the auto-configured LocaleResolver is @ConditionalOnProperty(prefix = "spring.mvc", name = "locale"). For the problem described above to occur, you'd have to set the spring.mvc.locale property and provide a custom LocaleResolver bean that isn't named localeResolver(). I think that's sufficiently unlikely to happen that the risk of the fix isn't worth the marginal improvement.

In 2.4.0 things are different as both the LocaleResolver and LocaleContextResolver beans are not @ConditionalOnProperty.

@wilkinsona wilkinsona changed the title LocaleResolver bean will back off if a user provides a bean of the same type and a custom name but Framework will then use its own default LocaleResolver (MVC) and LocaleContextResolver (WebFlux) beans will back off if a user provides a bean of the same type and a custom name but Framework will then use its own default Nov 20, 2020
@wilkinsona wilkinsona modified the milestones: 2.2.x, 2.4.x Nov 20, 2020
@wilkinsona wilkinsona self-assigned this Nov 20, 2020
@wilkinsona wilkinsona modified the milestones: 2.4.x, 2.4.1 Nov 20, 2020
@theHilikus
Copy link

@theHilikus theHilikus commented Jan 11, 2021

@wilkinsona we are having a regression related to localeResolver and i'm wondering if it's related to this ticket or an actual regression in Spring

We are using mvc and we localize our ui using thymeleaf. Since updating to 2.4.1 (tested with 2.4.0 and the problem is there. but it is NOT there in 2.3.7) our application doesn't start and gives the error

20:07.617  WARN 93032 --- [  restartedMain] gServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'localeResolver' defined in class path resource [com/foo/ui/config/UiConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=uiConfig; factoryMethodName=localeResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/foo/ui/config/UiConfig.class]] for bean 'localeResolver': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration; factoryMethodName=localeResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]] bound.

The error is misleading. I was able to find the conflicting bean in org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport, not in DelegatingWebMvcConfiguration like the error says. But in any case, shouldn't that bean back off when i register my own LocaleResolver?

I haven't been able to find official documentation to configure a localizationResolver. I just followed this article which instructs to create the bean like this

@Bean
public LocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(Locale.US);
    return slr;
}

But again, such a bean collides with the one in WebMvcConfigurationSupport and if renamed it is not used by org.springframework.web.servlet.DispatcherServlet#initLocaleResolver, which does

this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);

I see that 2.3.X WebMvcConfigurationSupport doesn't create a localeResolver bean

Should I open a new ticket or am I missing something?

@philwebb
Copy link
Member

@philwebb philwebb commented Jan 12, 2021

@theHilikus That sounds like a bug. The localeResolver in our EnableWebMvcConfiguration class is @ConditionalOnMissingBean so it should back off.

Could you check that you've not got an @EnableWebMvc annotation in your app? If you haven't, could we please have a new issue with a sample that shows the error.

@theHilikus
Copy link

@theHilikus theHilikus commented Jan 12, 2021

ah. i did have @EnableWebMvc. Once i removed that, the problem was gone

Thank you for the info @philwebb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants