Make sure Web infrastructure uses qualified beans

This commit is a follow-up of a change in Spring Framework[1] to make
sure injection points that are expecting a specific bean by name use
a qualifier.

As a result of this change, MVC uses the dedicated MVC validator again
rather than the general one auto-configured by Spring Boot.

[1] https://github.com/spring-projects/spring-framework/issues/23887

Closes gh-18672
pull/18826/head
Stephane Nicoll 5 years ago
parent 3236dfd7d9
commit 7f509bf84e

@ -33,6 +33,7 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -362,10 +363,11 @@ public class WebMvcAutoConfiguration {
@Bean @Bean
@Override @Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter( public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
ContentNegotiationManager mvcContentNegotiationManager, @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
FormattingConversionService mvcConversionService, Validator mvcValidator) { @Qualifier("mvcConversionService") FormattingConversionService conversionService,
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(mvcContentNegotiationManager, @Qualifier("mvcValidator") Validator validator) {
mvcConversionService, mvcValidator); RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager,
conversionService, validator);
adapter.setIgnoreDefaultModelOnRedirect( adapter.setIgnoreDefaultModelOnRedirect(
this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect()); this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
return adapter; return adapter;
@ -383,11 +385,12 @@ public class WebMvcAutoConfiguration {
@Primary @Primary
@Override @Override
public RequestMappingHandlerMapping requestMappingHandlerMapping( public RequestMappingHandlerMapping requestMappingHandlerMapping(
ContentNegotiationManager mvcContentNegotiationManager, @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) { @Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
// Must be @Primary for MvcUriComponentsBuilder to work // Must be @Primary for MvcUriComponentsBuilder to work
return super.requestMappingHandlerMapping(mvcContentNegotiationManager, mvcConversionService, return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,
mvcResourceUrlProvider); resourceUrlProvider);
} }
@Bean @Bean

@ -564,15 +564,31 @@ class WebMvcAutoConfigurationTests {
} }
@Test @Test
void validatorWithConfigurerShouldUseSpringValidator() { void validatorWithConfigurerAloneShouldUseSpringValidator() {
this.contextRunner.withUserConfiguration(MvcValidator.class).run((context) -> { this.contextRunner.withUserConfiguration(MvcValidator.class).run((context) -> {
assertThat(context).doesNotHaveBean(ValidatorFactory.class); assertThat(context).doesNotHaveBean(ValidatorFactory.class);
assertThat(context).doesNotHaveBean(javax.validation.Validator.class); assertThat(context).doesNotHaveBean(javax.validation.Validator.class);
assertThat(context).getBeanNames(Validator.class).containsOnly("mvcValidator"); assertThat(context).getBeanNames(Validator.class).containsOnly("mvcValidator");
assertThat(context.getBean("mvcValidator")).isSameAs(context.getBean(MvcValidator.class).validator); Validator expectedValidator = context.getBean(MvcValidator.class).validator;
assertThat(context.getBean("mvcValidator")).isSameAs(expectedValidator);
assertThat(context.getBean(RequestMappingHandlerAdapter.class).getWebBindingInitializer())
.hasFieldOrPropertyWithValue("validator", expectedValidator);
}); });
} }
@Test
void validatorWithConfigurerShouldUseSpringValidator() {
this.contextRunner.withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class))
.withUserConfiguration(MvcValidator.class).run((context) -> {
assertThat(context).getBeanNames(javax.validation.Validator.class).containsOnly("defaultValidator");
assertThat(context).getBeanNames(Validator.class).containsOnly("defaultValidator", "mvcValidator");
Validator expectedValidator = context.getBean(MvcValidator.class).validator;
assertThat(context.getBean("mvcValidator")).isSameAs(expectedValidator);
assertThat(context.getBean(RequestMappingHandlerAdapter.class).getWebBindingInitializer())
.hasFieldOrPropertyWithValue("validator", expectedValidator);
});
}
@Test @Test
void validatorWithConfigurerDoesNotExposeJsr303() { void validatorWithConfigurerDoesNotExposeJsr303() {
this.contextRunner.withUserConfiguration(MvcJsr303Validator.class).run((context) -> { this.contextRunner.withUserConfiguration(MvcJsr303Validator.class).run((context) -> {

Loading…
Cancel
Save