Skip to content

Commit

Permalink
Require bean name match for Locale(Context)Resolver to back off
Browse files Browse the repository at this point in the history
Web MVC and WebFlux look up by name the Locale(Context)Resolver beans
that they use. Previously, the auto-configured resolvers for MVC and
WebFlux would back off when any bean of the required type was defined,
irrespective of its name. If the name of the user's bean didn't match
the name used by MVC and WebFlux to find the custom resolver, the
custom resolver would be ignored and MVC and WebFlux would use their
defaults. There was no indication of this happening in the condition
evaluation report as all it would show is that the auto-configured
resolver had backed off in favour of the custom resolver. It wouldn't
show anything to explain why the custom resolver had not been used.

This commit updates the auto-configured resolvers to be conditional
on a missing bean of the name required by MVC and WebFlux. If the
user then defines a custom resolver with a different name, the
condition evaluation report will show that the auto-configured
resolver remained as the bean name didn't match.

Fixes gh-24209
  • Loading branch information
wilkinsona committed Nov 20, 2020
1 parent e342d7d commit 4a7bc3d
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 11 deletions.
Expand Up @@ -70,6 +70,7 @@
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
import org.springframework.web.server.i18n.FixedLocaleContextResolver;
import org.springframework.web.server.i18n.LocaleContextResolver;
Expand Down Expand Up @@ -289,7 +290,7 @@ protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {

@Bean
@Override
@ConditionalOnMissingBean
@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
public LocaleContextResolver localeContextResolver() {
if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
return new FixedLocaleContextResolver(this.webProperties.getLocale());
Expand Down
Expand Up @@ -441,7 +441,7 @@ public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext ap

@Override
@Bean
@ConditionalOnMissingBean
@ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)
@SuppressWarnings("deprecation")
public LocaleResolver localeResolver() {
if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
Expand Down
Expand Up @@ -79,6 +79,7 @@
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
import org.springframework.web.server.i18n.FixedLocaleContextResolver;
import org.springframework.web.server.i18n.LocaleContextResolver;
Expand Down Expand Up @@ -531,10 +532,25 @@ void whenAcceptHeaderLocaleContextResolverIsUsedAndHeaderIsAbsentThenConfiguredL
}

@Test
void customLocaleContextResolver() {
this.contextRunner.withUserConfiguration(LocaleContextResolverConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(LocaleContextResolver.class)
.hasBean("customLocaleContextResolver"));
void customLocaleContextResolverWithMatchingNameReplacedAutoConfiguredLocaleContextResolver() {
this.contextRunner
.withBean("localeContextResolver", CustomLocaleContextResolver.class, CustomLocaleContextResolver::new)
.run((context) -> {
assertThat(context).hasSingleBean(LocaleContextResolver.class);
assertThat(context.getBean("localeContextResolver"))
.isInstanceOf(CustomLocaleContextResolver.class);
});
}

@Test
void customLocaleContextResolverWithDifferentNameDoesNotReplaceAutoConfiguredLocaleContextResolver() {
this.contextRunner.withBean("customLocaleContextResolver", CustomLocaleContextResolver.class,
CustomLocaleContextResolver::new).run((context) -> {
assertThat(context.getBean("customLocaleContextResolver"))
.isInstanceOf(CustomLocaleContextResolver.class);
assertThat(context.getBean("localeContextResolver"))
.isInstanceOf(AcceptHeaderLocaleContextResolver.class);
});
}

private Map<PathPattern, Object> getHandlerMap(ApplicationContext context) {
Expand Down Expand Up @@ -767,12 +783,15 @@ public Example parse(String source, Locale locale) {

}

@Configuration(proxyBeanMethods = false)
static class LocaleContextResolverConfiguration {
static class CustomLocaleContextResolver implements LocaleContextResolver {

@Bean
LocaleContextResolver customLocaleContextResolver() {
return new AcceptHeaderLocaleContextResolver();
@Override
public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
return () -> Locale.ENGLISH;
}

@Override
public void setLocaleContext(ServerWebExchange exchange, LocaleContext localeContext) {
}

}
Expand Down
Expand Up @@ -344,6 +344,24 @@ void useDefaultLocaleIfAcceptHeaderNoSet(String mvcOrWeb) {
});
}

@Test
void customLocaleResolverWithMatchingNameReplacesAutoConfiguredLocaleResolver() {
this.contextRunner.withBean("localeResolver", CustomLocaleResolver.class, CustomLocaleResolver::new)
.run((context) -> {
assertThat(context).hasSingleBean(LocaleResolver.class);
assertThat(context.getBean("localeResolver")).isInstanceOf(CustomLocaleResolver.class);
});
}

@Test
void customLocaleResolverWithDifferentNameDoesNotReplaceAutoConfiguredLocaleResolver() {
this.contextRunner.withBean("customLocaleResolver", CustomLocaleResolver.class, CustomLocaleResolver::new)
.run((context) -> {
assertThat(context.getBean("customLocaleResolver")).isInstanceOf(CustomLocaleResolver.class);
assertThat(context.getBean("localeResolver")).isInstanceOf(AcceptHeaderLocaleResolver.class);
});
}

@Test
void defaultDateFormat() {
this.contextRunner.run((context) -> {
Expand Down Expand Up @@ -1376,4 +1394,17 @@ ServletRegistrationBean<?> additionalDispatcherServlet() {

}

static class CustomLocaleResolver implements LocaleResolver {

@Override
public Locale resolveLocale(HttpServletRequest request) {
return Locale.ENGLISH;
}

@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}

}

}

0 comments on commit 4a7bc3d

Please sign in to comment.