diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java index 02ca7e2ccff..7a75c4f5d06 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java @@ -51,33 +51,38 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; UserDetailsService.class }) public class AuthenticationManagerConfiguration { - private final Pattern pattern = Pattern.compile("^\\{.+}.*$"); + private static final String NOOP_PASSWORD_PREFIX = "{noop}"; + + private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern + .compile("^\\{.+}.*$"); private static final Log logger = LogFactory .getLog(AuthenticationManagerConfiguration.class); - private static final String NOOP_PREFIX = "{noop}"; - @Bean - public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties, + public InMemoryUserDetailsManager inMemoryUserDetailsManager( + SecurityProperties properties, ObjectProvider passwordEncoder) throws Exception { SecurityProperties.User user = properties.getUser(); - if (user.isPasswordGenerated()) { - logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword())); - } - String password = deducePassword(passwordEncoder, user.getPassword()); List roles = user.getRoles(); return new InMemoryUserDetailsManager( - User.withUsername(user.getName()).password(password) - .roles(roles.toArray(new String[roles.size()])).build()); + User.withUsername(user.getName()) + .password(getOrDeducePassword(user, + passwordEncoder.getIfAvailable())) + .roles(roles.toArray(new String[roles.size()])).build()); } - private String deducePassword(ObjectProvider passwordEncoder, String password) { - if (passwordEncoder.getIfAvailable() == null && - !this.pattern.matcher(password).matches()) { - return NOOP_PREFIX + password; + public String getOrDeducePassword(SecurityProperties.User user, + PasswordEncoder encoder) { + String password = user.getPassword(); + if (user.isPasswordGenerated()) { + logger.info(String.format("%n%nUsing generated security password: %s%n", + user.getPassword())); } - return password; + if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) { + return password; + } + return NOOP_PASSWORD_PREFIX + password; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfiguration.java index 2acded6c1d7..eafa5c30992 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfiguration.java @@ -51,9 +51,10 @@ import org.springframework.security.crypto.password.PasswordEncoder; @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) class ReactiveAuthenticationManagerConfiguration { - private final Pattern pattern = Pattern.compile("^\\{.+}.*$"); + private static final String NOOP_PASSWORD_PREFIX = "{noop}"; - private static final String NOOP_PREFIX = "{noop}"; + private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern + .compile("^\\{.+}.*$"); private static final Log logger = LogFactory .getLog(ReactiveAuthenticationManagerConfiguration.class); @@ -63,28 +64,28 @@ class ReactiveAuthenticationManagerConfiguration { SecurityProperties properties, ObjectProvider passwordEncoder) { SecurityProperties.User user = properties.getUser(); - if (user.isPasswordGenerated()) { - logger.info(String.format("%n%nUsing default security password: %s%n", - user.getPassword())); - } - String password = deducePassword(passwordEncoder, user.getPassword()); - UserDetails userDetails = getUserDetails(user, password); + UserDetails userDetails = getUserDetails(user, + getOrDeducePassword(user, passwordEncoder.getIfAvailable())); return new MapReactiveUserDetailsService(userDetails); } - private String deducePassword(ObjectProvider passwordEncoder, String password) { - if (passwordEncoder.getIfAvailable() == null && - !this.pattern.matcher(password).matches()) { - return NOOP_PREFIX + password; - } - return password; - } - - private UserDetails getUserDetails(SecurityProperties.User user, - String password) { + private UserDetails getUserDetails(SecurityProperties.User user, String password) { List roles = user.getRoles(); return User.withUsername(user.getName()).password(password) .roles(roles.toArray(new String[roles.size()])).build(); } + private String getOrDeducePassword(SecurityProperties.User user, + PasswordEncoder encoder) { + String password = user.getPassword(); + if (user.isPasswordGenerated()) { + logger.info(String.format("%n%nUsing default security password: %s%n", + user.getPassword())); + } + if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) { + return password; + } + return NOOP_PASSWORD_PREFIX + password; + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java index 1692ea2263e..9d5f2094c4d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java @@ -34,35 +34,35 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * {@link org.springframework.format.support.FormattingConversionService} dedicated - * to web applications for formatting and converting values to/from the web. - * - *

This service replaces the default implementations provided by - * {@link org.springframework.web.servlet.config.annotation.EnableWebMvc} - * and {@link org.springframework.web.reactive.config.EnableWebFlux}. + * {@link org.springframework.format.support.FormattingConversionService} dedicated to web + * applications for formatting and converting values to/from the web. + *

+ * This service replaces the default implementations provided by + * {@link org.springframework.web.servlet.config.annotation.EnableWebMvc} and + * {@link org.springframework.web.reactive.config.EnableWebFlux}. * * @author Brian Clozel * @since 2.0.0 */ public class WebConversionService extends DefaultFormattingConversionService { - private static final boolean jsr354Present = ClassUtils - .isPresent("javax.money.MonetaryAmount", WebConversionService.class.getClassLoader()); + private static final boolean jsr354Present = ClassUtils.isPresent( + "javax.money.MonetaryAmount", WebConversionService.class.getClassLoader()); - private static final boolean jodaTimePresent = ClassUtils - .isPresent("org.joda.time.LocalDate", WebConversionService.class.getClassLoader()); + private static final boolean jodaTimePresent = ClassUtils.isPresent( + "org.joda.time.LocalDate", WebConversionService.class.getClassLoader()); - private String dateFormat; + private final String dateFormat; /** - * Create a new WebConversionService that configures formatters with the provided date format, - * or register the default ones if no custom format is provided. + * Create a new WebConversionService that configures formatters with the provided date + * format, or register the default ones if no custom format is provided. * @param dateFormat the custom date format to use for date conversions */ public WebConversionService(String dateFormat) { super(false); - if (StringUtils.hasText(dateFormat)) { - this.dateFormat = dateFormat; + this.dateFormat = (StringUtils.hasText(dateFormat) ? dateFormat : null); + if (this.dateFormat != null) { addFormatters(); } else { @@ -70,13 +70,13 @@ public class WebConversionService extends DefaultFormattingConversionService { } } - private void addFormatters() { addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); if (jsr354Present) { addFormatter(new CurrencyUnitFormatter()); addFormatter(new MonetaryAmountFormatter()); - addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory()); + addFormatterForFieldAnnotation( + new Jsr354NumberFormatAnnotationFormatterFactory()); } registerJsr310(); if (jodaTimePresent) { @@ -88,10 +88,8 @@ public class WebConversionService extends DefaultFormattingConversionService { private void registerJsr310() { DateTimeFormatterRegistrar dateTime = new DateTimeFormatterRegistrar(); if (this.dateFormat != null) { - DateTimeFormatter dateTimeFormatter = DateTimeFormatter - .ofPattern(this.dateFormat) - .withResolverStyle(ResolverStyle.STRICT); - dateTime.setDateFormatter(dateTimeFormatter); + dateTime.setDateFormatter(DateTimeFormatter.ofPattern(this.dateFormat) + .withResolverStyle(ResolverStyle.STRICT)); } dateTime.registerFormatters(this); } @@ -99,10 +97,8 @@ public class WebConversionService extends DefaultFormattingConversionService { private void registerJodaTime() { JodaTimeFormatterRegistrar jodaTime = new JodaTimeFormatterRegistrar(); if (this.dateFormat != null) { - org.joda.time.format.DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder() - .appendPattern(this.dateFormat) - .toFormatter(); - jodaTime.setDateFormatter(dateTimeFormatter); + jodaTime.setDateFormatter(new DateTimeFormatterBuilder() + .appendPattern(this.dateFormat).toFormatter()); } jodaTime.registerFormatters(this); } @@ -115,4 +111,5 @@ public class WebConversionService extends DefaultFormattingConversionService { } dateFormatterRegistrar.registerFormatters(this); } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java index c173e543d45..2d8802efe3c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java @@ -223,7 +223,8 @@ public class WebFluxAutoConfiguration { @Bean @Override public FormattingConversionService webFluxConversionService() { - WebConversionService conversionService = new WebConversionService(this.webFluxProperties.getDateFormat()); + WebConversionService conversionService = new WebConversionService( + this.webFluxProperties.getDateFormat()); addFormatters(conversionService); return conversionService; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java index 43b130b0d94..e5df7cb13e1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java @@ -301,8 +301,8 @@ public class WebMvcAutoConfiguration { return; } Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); - CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol() - .toHttpCacheControl(); + CacheControl cacheControl = this.resourceProperties.getCache() + .getCachecontrol().toHttpCacheControl(); if (!registry.hasMappingForPattern("/webjars/**")) { customizeResourceHandlerRegistration( registry.addResourceHandler("/webjars/**") @@ -475,7 +475,8 @@ public class WebMvcAutoConfiguration { @Bean @Override public FormattingConversionService mvcConversionService() { - WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat()); + WebConversionService conversionService = new WebConversionService( + this.mvcProperties.getDateFormat()); addFormatters(conversionService); return conversionService; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfigurationTests.java index e9b368ad05f..84b8f4a964c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfigurationTests.java @@ -40,22 +40,27 @@ public class AuthenticationManagerConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); @Test - public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() throws Exception { + public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() + throws Exception { this.contextRunner.withUserConfiguration(TestSecurityConfiguration.class, AuthenticationManagerConfiguration.class).run((context -> { - InMemoryUserDetailsManager userDetailsService = context.getBean(InMemoryUserDetailsManager.class); - String password = userDetailsService.loadUserByUsername("user").getPassword(); - assertThat(password).startsWith("{noop}"); - })); + InMemoryUserDetailsManager userDetailsService = context + .getBean(InMemoryUserDetailsManager.class); + String password = userDetailsService.loadUserByUsername("user") + .getPassword(); + assertThat(password).startsWith("{noop}"); + })); } @Test - public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword() throws Exception { + public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword() + throws Exception { testPasswordEncoding(TestSecurityConfiguration.class, "secret", "{noop}secret"); } @Test - public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword() throws Exception { + public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword() + throws Exception { String password = "{bcrypt}$2a$10$sCBi9fy9814vUPf2ZRbtp.fR5/VgRk2iBFZ.ypu5IyZ28bZgxrVDa"; testPasswordEncoding(TestSecurityConfiguration.class, password, password); } @@ -65,14 +70,19 @@ public class AuthenticationManagerConfigurationTests { testPasswordEncoding(TestConfigWithPasswordEncoder.class, "secret", "secret"); } - private void testPasswordEncoding(Class configClass, String providedPassword, String expectedPassword) { - this.contextRunner.withUserConfiguration(configClass, - AuthenticationManagerConfiguration.class) - .withPropertyValues("spring.security.user.password=" + providedPassword).run((context -> { - InMemoryUserDetailsManager userDetailsService = context.getBean(InMemoryUserDetailsManager.class); - String password = userDetailsService.loadUserByUsername("user").getPassword(); - assertThat(password).isEqualTo(expectedPassword); - })); + private void testPasswordEncoding(Class configClass, String providedPassword, + String expectedPassword) { + this.contextRunner + .withUserConfiguration(configClass, + AuthenticationManagerConfiguration.class) + .withPropertyValues("spring.security.user.password=" + providedPassword) + .run((context -> { + InMemoryUserDetailsManager userDetailsService = context + .getBean(InMemoryUserDetailsManager.class); + String password = userDetailsService.loadUserByUsername("user") + .getPassword(); + assertThat(password).isEqualTo(expectedPassword); + })); } @Configuration @@ -92,4 +102,5 @@ public class AuthenticationManagerConfigurationTests { } } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfigurationTests.java index bb62585e627..e02bccafc8c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveAuthenticationManagerConfigurationTests.java @@ -41,22 +41,29 @@ public class ReactiveAuthenticationManagerConfigurationTests { private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(); @Test - public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() throws Exception { - this.contextRunner.withUserConfiguration(TestSecurityConfiguration.class, - ReactiveAuthenticationManagerConfiguration.class).run((context -> { - MapReactiveUserDetailsService userDetailsService = context.getBean(MapReactiveUserDetailsService.class); - String password = userDetailsService.findByUsername("user").block().getPassword(); - assertThat(password).startsWith("{noop}"); - })); + public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() + throws Exception { + this.contextRunner + .withUserConfiguration(TestSecurityConfiguration.class, + ReactiveAuthenticationManagerConfiguration.class) + .run((context -> { + MapReactiveUserDetailsService userDetailsService = context + .getBean(MapReactiveUserDetailsService.class); + String password = userDetailsService.findByUsername("user").block() + .getPassword(); + assertThat(password).startsWith("{noop}"); + })); } @Test - public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword() throws Exception { + public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword() + throws Exception { testPasswordEncoding(TestSecurityConfiguration.class, "secret", "{noop}secret"); } @Test - public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword() throws Exception { + public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword() + throws Exception { String password = "{bcrypt}$2a$10$sCBi9fy9814vUPf2ZRbtp.fR5/VgRk2iBFZ.ypu5IyZ28bZgxrVDa"; testPasswordEncoding(TestSecurityConfiguration.class, password, password); } @@ -66,14 +73,19 @@ public class ReactiveAuthenticationManagerConfigurationTests { testPasswordEncoding(TestConfigWithPasswordEncoder.class, "secret", "secret"); } - private void testPasswordEncoding(Class configClass, String providedPassword, String expectedPassword) { - this.contextRunner.withUserConfiguration(configClass, - ReactiveAuthenticationManagerConfiguration.class) - .withPropertyValues("spring.security.user.password=" + providedPassword).run((context -> { - MapReactiveUserDetailsService userDetailsService = context.getBean(MapReactiveUserDetailsService.class); - String password = userDetailsService.findByUsername("user").block().getPassword(); - assertThat(password).isEqualTo(expectedPassword); - })); + private void testPasswordEncoding(Class configClass, String providedPassword, + String expectedPassword) { + this.contextRunner + .withUserConfiguration(configClass, + ReactiveAuthenticationManagerConfiguration.class) + .withPropertyValues("spring.security.user.password=" + providedPassword) + .run((context -> { + MapReactiveUserDetailsService userDetailsService = context + .getBean(MapReactiveUserDetailsService.class); + String password = userDetailsService.findByUsername("user").block() + .getPassword(); + assertThat(password).isEqualTo(expectedPassword); + })); } @Configuration diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java index 469945aa9ed..611b91717df 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java @@ -34,17 +34,14 @@ public class WebConversionServiceTests { @Test public void customDateFormat() { WebConversionService conversionService = new WebConversionService("dd*MM*yyyy"); - Date date = new DateTime(2018, 1, 1, 20, 30).toDate(); - assertThat(conversionService.convert(date, String.class)) - .isEqualTo("01*01*2018"); - + assertThat(conversionService.convert(date, String.class)).isEqualTo("01*01*2018"); LocalDate jodaDate = LocalDate.fromDateFields(date); assertThat(conversionService.convert(jodaDate, String.class)) .isEqualTo("01*01*2018"); - java.time.LocalDate localDate = java.time.LocalDate.of(2018, 1, 1); assertThat(conversionService.convert(localDate, String.class)) .isEqualTo("01*01*2018"); } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index ed51987b834..9fe0a30c2e1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -69,8 +69,7 @@ import static org.mockito.Mockito.verify; */ public class WebFluxAutoConfigurationTests { - private static final MockReactiveWebServerFactory mockReactiveWebServerFactory - = new MockReactiveWebServerFactory(); + private static final MockReactiveWebServerFactory mockReactiveWebServerFactory = new MockReactiveWebServerFactory(); private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class)) @@ -80,8 +79,10 @@ public class WebFluxAutoConfigurationTests { public void shouldNotProcessIfExistingWebReactiveConfiguration() { this.contextRunner.withUserConfiguration(WebFluxConfigurationSupport.class) .run(context -> { - assertThat(context).getBeans(RequestMappingHandlerMapping.class).hasSize(1); - assertThat(context).getBeans(RequestMappingHandlerAdapter.class).hasSize(1); + assertThat(context).getBeans(RequestMappingHandlerMapping.class) + .hasSize(1); + assertThat(context).getBeans(RequestMappingHandlerAdapter.class) + .hasSize(1); }); } @@ -99,28 +100,30 @@ public class WebFluxAutoConfigurationTests { @SuppressWarnings("unchecked") @Test public void shouldRegisterCustomHandlerMethodArgumentResolver() { - this.contextRunner.withUserConfiguration(CustomArgumentResolvers.class).run(context -> { - RequestMappingHandlerAdapter adapter = context - .getBean(RequestMappingHandlerAdapter.class); - List customResolvers = - (List) ReflectionTestUtils - .getField(adapter.getArgumentResolverConfigurer(), "customResolvers"); - assertThat(customResolvers).contains( - context.getBean("firstResolver", - HandlerMethodArgumentResolver.class), - context.getBean("secondResolver", - HandlerMethodArgumentResolver.class)); - }); + this.contextRunner.withUserConfiguration(CustomArgumentResolvers.class) + .run(context -> { + RequestMappingHandlerAdapter adapter = context + .getBean(RequestMappingHandlerAdapter.class); + List customResolvers = (List) ReflectionTestUtils + .getField(adapter.getArgumentResolverConfigurer(), + "customResolvers"); + assertThat(customResolvers).contains( + context.getBean("firstResolver", + HandlerMethodArgumentResolver.class), + context.getBean("secondResolver", + HandlerMethodArgumentResolver.class)); + }); } @Test public void shouldCustomizeCodecs() { - this.contextRunner.withUserConfiguration(CustomCodecCustomizers.class).run(context -> { - CodecCustomizer codecCustomizer = context.getBean("firstCodecCustomizer", - CodecCustomizer.class); - assertThat(codecCustomizer).isNotNull(); - verify(codecCustomizer).customize(any(ServerCodecConfigurer.class)); - }); + this.contextRunner.withUserConfiguration(CustomCodecCustomizers.class) + .run(context -> { + CodecCustomizer codecCustomizer = context + .getBean("firstCodecCustomizer", CodecCustomizer.class); + assertThat(codecCustomizer).isNotNull(); + verify(codecCustomizer).customize(any(ServerCodecConfigurer.class)); + }); } @Test @@ -129,7 +132,8 @@ public class WebFluxAutoConfigurationTests { SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class); - ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**"); + ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap() + .get("/**"); assertThat(staticHandler.getLocations()).hasSize(4); assertThat(hm.getUrlMap().get("/webjars/**")) .isInstanceOf(ResourceWebHandler.class); @@ -143,7 +147,8 @@ public class WebFluxAutoConfigurationTests { @Test public void shouldMapResourcesToCustomPath() { - this.contextRunner.withPropertyValues("spring.webflux.static-path-pattern:/static/**") + this.contextRunner + .withPropertyValues("spring.webflux.static-path-pattern:/static/**") .run(context -> { SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); @@ -170,11 +175,16 @@ public class WebFluxAutoConfigurationTests { .run(context -> { SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); - assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class); - ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**"); - assertThat(staticHandler.getResourceResolvers()).extractingResultOf("getClass") - .containsOnly(CachingResourceResolver.class, PathResourceResolver.class); - assertThat(staticHandler.getResourceTransformers()).extractingResultOf("getClass") + assertThat(hm.getUrlMap().get("/**")) + .isInstanceOf(ResourceWebHandler.class); + ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap() + .get("/**"); + assertThat(staticHandler.getResourceResolvers()) + .extractingResultOf("getClass") + .containsOnly(CachingResourceResolver.class, + PathResourceResolver.class); + assertThat(staticHandler.getResourceTransformers()) + .extractingResultOf("getClass") .containsOnly(CachingResourceTransformer.class); }); } @@ -216,29 +226,35 @@ public class WebFluxAutoConfigurationTests { @Test public void validatorWhenNoValidatorShouldUseDefault() { - this.contextRunner - .run(context -> { - assertThat(context).doesNotHaveBean(ValidatorFactory.class); - assertThat(context).doesNotHaveBean(javax.validation.Validator.class); - assertThat(context).getBeanNames(Validator.class).containsExactly("webFluxValidator"); - }); + this.contextRunner.run(context -> { + assertThat(context).doesNotHaveBean(ValidatorFactory.class); + assertThat(context).doesNotHaveBean(javax.validation.Validator.class); + assertThat(context).getBeanNames(Validator.class) + .containsExactly("webFluxValidator"); + }); } @Test public void validatorWhenNoCustomizationShouldUseAutoConfigured() { - this.contextRunner.withConfiguration( - AutoConfigurations.of(ValidationAutoConfiguration.class)) + this.contextRunner + .withConfiguration( + AutoConfigurations.of(ValidationAutoConfiguration.class)) .run(context -> { assertThat(context).getBeanNames(javax.validation.Validator.class) .containsExactly("defaultValidator"); assertThat(context).getBeanNames(Validator.class) - .containsExactlyInAnyOrder("defaultValidator", "webFluxValidator"); - Validator validator = context.getBean("webFluxValidator", Validator.class); + .containsExactlyInAnyOrder("defaultValidator", + "webFluxValidator"); + Validator validator = context.getBean("webFluxValidator", + Validator.class); assertThat(validator).isInstanceOf(ValidatorAdapter.class); Object defaultValidator = context.getBean("defaultValidator"); - assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator); - // Primary Spring validator is the one used by WebFlux behind the scenes - assertThat(context.getBean(Validator.class)).isEqualTo(defaultValidator); + assertThat(((ValidatorAdapter) validator).getTarget()) + .isSameAs(defaultValidator); + // Primary Spring validator is the one used by WebFlux behind the + // scenes + assertThat(context.getBean(Validator.class)) + .isEqualTo(defaultValidator); }); } @@ -250,15 +266,14 @@ public class WebFluxAutoConfigurationTests { assertThat(context).doesNotHaveBean(javax.validation.Validator.class); assertThat(context).getBeanNames(Validator.class) .containsOnly("webFluxValidator"); - assertThat(context.getBean("webFluxValidator")) - .isSameAs(context.getBean(ValidatorWebFluxConfigurer.class).validator); + assertThat(context.getBean("webFluxValidator")).isSameAs( + context.getBean(ValidatorWebFluxConfigurer.class).validator); }); } @Test public void validatorWithConfigurerDoesNotExposeJsr303() { - this.contextRunner - .withUserConfiguration(ValidatorJsr303WebFluxConfigurer.class) + this.contextRunner.withUserConfiguration(ValidatorJsr303WebFluxConfigurer.class) .run(context -> { assertThat(context).doesNotHaveBean(ValidatorFactory.class); assertThat(context).doesNotHaveBean(javax.validation.Validator.class); @@ -267,24 +282,28 @@ public class WebFluxAutoConfigurationTests { Validator validator = context.getBean("webFluxValidator", Validator.class); assertThat(validator).isInstanceOf(ValidatorAdapter.class); - assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs( - context.getBean(ValidatorJsr303WebFluxConfigurer.class).validator); + assertThat(((ValidatorAdapter) validator).getTarget()) + .isSameAs(context.getBean( + ValidatorJsr303WebFluxConfigurer.class).validator); }); } @Test public void validationCustomConfigurerTakesPrecedence() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class)) - .withUserConfiguration(ValidatorWebFluxConfigurer.class) - .run(context -> { + .withConfiguration( + AutoConfigurations.of(ValidationAutoConfiguration.class)) + .withUserConfiguration(ValidatorWebFluxConfigurer.class).run(context -> { assertThat(context).getBeans(ValidatorFactory.class).hasSize(1); - assertThat(context).getBeans(javax.validation.Validator.class).hasSize(1); + assertThat(context).getBeans(javax.validation.Validator.class) + .hasSize(1); assertThat(context).getBeanNames(Validator.class) - .containsExactlyInAnyOrder("defaultValidator", "webFluxValidator"); + .containsExactlyInAnyOrder("defaultValidator", + "webFluxValidator"); assertThat(context.getBean("webFluxValidator")).isSameAs( context.getBean(ValidatorWebFluxConfigurer.class).validator); - // Primary Spring validator is the auto-configured one as the WebFlux one has been + // Primary Spring validator is the auto-configured one as the WebFlux + // one has been // customized via a WebFluxConfigurer assertThat(context.getBean(Validator.class)) .isEqualTo(context.getBean("defaultValidator")); @@ -294,19 +313,24 @@ public class WebFluxAutoConfigurationTests { @Test public void validatorWithCustomSpringValidatorIgnored() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class)) - .withUserConfiguration(CustomSpringValidator.class) - .run(context -> { + .withConfiguration( + AutoConfigurations.of(ValidationAutoConfiguration.class)) + .withUserConfiguration(CustomSpringValidator.class).run(context -> { assertThat(context).getBeanNames(javax.validation.Validator.class) .containsExactly("defaultValidator"); assertThat(context).getBeanNames(Validator.class) - .containsExactlyInAnyOrder("customValidator", "defaultValidator", "webFluxValidator"); - Validator validator = context.getBean("webFluxValidator", Validator.class); + .containsExactlyInAnyOrder("customValidator", + "defaultValidator", "webFluxValidator"); + Validator validator = context.getBean("webFluxValidator", + Validator.class); assertThat(validator).isInstanceOf(ValidatorAdapter.class); Object defaultValidator = context.getBean("defaultValidator"); - assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator); - // Primary Spring validator is the one used by WebFlux behind the scenes - assertThat(context.getBean(Validator.class)).isEqualTo(defaultValidator); + assertThat(((ValidatorAdapter) validator).getTarget()) + .isSameAs(defaultValidator); + // Primary Spring validator is the one used by WebFlux behind the + // scenes + assertThat(context.getBean(Validator.class)) + .isEqualTo(defaultValidator); }); } @@ -322,8 +346,9 @@ public class WebFluxAutoConfigurationTests { Validator validator = context.getBean(Validator.class); assertThat(validator).isInstanceOf(ValidatorAdapter.class); Validator target = ((ValidatorAdapter) validator).getTarget(); - assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator")) - .isSameAs(context.getBean("customValidator")); + assertThat(new DirectFieldAccessor(target) + .getPropertyValue("targetValidator")) + .isSameAs(context.getBean("customValidator")); }); }