pull/10848/merge
Phillip Webb 7 years ago
parent 44d8e09aac
commit c55b5d7111

@ -22,6 +22,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.DefaultCachingCon
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
import org.springframework.boot.actuate.endpoint.ParameterMapper; import org.springframework.boot.actuate.endpoint.ParameterMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -82,7 +83,7 @@ public class CloudFoundryActuatorAutoConfiguration {
RestTemplateBuilder builder) { RestTemplateBuilder builder) {
WebAnnotationEndpointDiscoverer endpointDiscoverer = new WebAnnotationEndpointDiscoverer( WebAnnotationEndpointDiscoverer endpointDiscoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext, parameterMapper, cachingConfigurationFactory, this.applicationContext, parameterMapper, cachingConfigurationFactory,
endpointMediaTypes, (id) -> id); endpointMediaTypes, EndpointPathResolver.useEndpointId());
return new CloudFoundryWebEndpointServletHandlerMapping( return new CloudFoundryWebEndpointServletHandlerMapping(
new EndpointMapping("/cloudfoundryapplication"), new EndpointMapping("/cloudfoundryapplication"),
endpointDiscoverer.discoverEndpoints(), endpointMediaTypes, endpointDiscoverer.discoverEndpoints(), endpointMediaTypes,
@ -142,7 +143,6 @@ public class CloudFoundryActuatorAutoConfiguration {
@Override @Override
public void configure(WebSecurity builder) throws Exception { public void configure(WebSecurity builder) throws Exception {
} }
} }

@ -20,8 +20,8 @@ import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
/** /**
* Default {@link EndpointPathResolver} implementation that use the * Default {@link EndpointPathResolver} implementation that use the {@link Environment} to
* {@link Environment} to determine if an endpoint has a custom path. * determine if an endpoint has a custom path.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */

@ -68,12 +68,11 @@ import org.springframework.integration.support.management.IntegrationManagementC
@EnableConfigurationProperties(MetricsProperties.class) @EnableConfigurationProperties(MetricsProperties.class)
@Import({ MeterBindersConfiguration.class, WebMvcMetricsConfiguration.class, @Import({ MeterBindersConfiguration.class, WebMvcMetricsConfiguration.class,
WebFluxMetricsConfiguration.class, RestTemplateMetricsConfiguration.class, WebFluxMetricsConfiguration.class, RestTemplateMetricsConfiguration.class,
DataSourcePoolMetricsConfiguration.class, DataSourcePoolMetricsConfiguration.class, AtlasExportConfiguration.class,
AtlasExportConfiguration.class, DatadogExportConfiguration.class, DatadogExportConfiguration.class, GangliaExportConfiguration.class,
GangliaExportConfiguration.class, GraphiteExportConfiguration.class, GraphiteExportConfiguration.class, InfluxExportConfiguration.class,
InfluxExportConfiguration.class, JmxExportConfiguration.class, JmxExportConfiguration.class, PrometheusExportConfiguration.class,
PrometheusExportConfiguration.class, SimpleExportConfiguration.class, SimpleExportConfiguration.class, StatsdExportConfiguration.class })
StatsdExportConfiguration.class })
@AutoConfigureAfter(DataSourceAutoConfiguration.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MetricsAutoConfiguration { public class MetricsAutoConfiguration {

@ -17,11 +17,13 @@
package org.springframework.boot.actuate.autoconfigure.metrics.jdbc; package org.springframework.boot.actuate.autoconfigure.metrics.jdbc;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.sql.DataSource; import javax.sql.DataSource;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.Tags;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -62,12 +64,13 @@ public class DataSourcePoolMetricsConfiguration {
@Autowired @Autowired
public void bindDataSourcesToRegistry(Map<String, DataSource> dataSources) { public void bindDataSourcesToRegistry(Map<String, DataSource> dataSources) {
for (Map.Entry<String, DataSource> entry : dataSources.entrySet()) { dataSources.forEach(this::bindDataSourceToRegistry);
String beanName = entry.getKey();
DataSource dataSource = entry.getValue();
new DataSourcePoolMetrics(dataSource, this.metadataProviders, this.metricName,
Tags.zip("name", getDataSourceName(beanName))).bindTo(this.registry);
} }
private void bindDataSourceToRegistry(String beanName, DataSource dataSource) {
List<Tag> tags = Tags.zip("name", getDataSourceName(beanName));
new DataSourcePoolMetrics(dataSource, this.metadataProviders, this.metricName,
tags).bindTo(this.registry);
} }
/** /**

@ -220,8 +220,7 @@ public class CloudFoundryActuatorAutoConfigurationTests {
} }
@Test @Test
public void endpointPathCustomizationIsNotApplied() public void endpointPathCustomizationIsNotApplied() throws Exception {
throws Exception {
TestPropertyValues.of("endpoints.test.web.path=another/custom") TestPropertyValues.of("endpoints.test.web.path=another/custom")
.applyTo(this.context); .applyTo(this.context);
this.context.register(TestConfiguration.class); this.context.register(TestConfiguration.class);

@ -32,6 +32,7 @@ import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration; import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper; import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.endpoint.web.EndpointMapping; import org.springframework.boot.endpoint.web.EndpointMapping;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -219,7 +220,7 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
DefaultConversionService.getSharedInstance()); DefaultConversionService.getSharedInstance());
return new WebAnnotationEndpointDiscoverer(applicationContext, return new WebAnnotationEndpointDiscoverer(applicationContext,
parameterMapper, (id) -> new CachingConfiguration(0), parameterMapper, (id) -> new CachingConfiguration(0),
endpointMediaTypes, (id) -> id); endpointMediaTypes, EndpointPathResolver.useEndpointId());
} }
@Bean @Bean

@ -47,7 +47,8 @@ public class MetricsAutoConfigurationTests {
@Test @Test
public void autoConfiguredDataSourceIsInstrumented() { public void autoConfiguredDataSourceIsInstrumented() {
this.contextRunner this.contextRunner
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) .withConfiguration(
AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true", .withPropertyValues("spring.datasource.generate-unique-name=true",
"spring.metrics.use-global-registry=false") "spring.metrics.use-global-registry=false")
.run((context) -> { .run((context) -> {
@ -61,7 +62,8 @@ public class MetricsAutoConfigurationTests {
@Test @Test
public void autoConfiguredDataSourceWithCustomMetricName() { public void autoConfiguredDataSourceWithCustomMetricName() {
this.contextRunner this.contextRunner
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) .withConfiguration(
AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true", .withPropertyValues("spring.datasource.generate-unique-name=true",
"spring.metrics.jdbc.datasource-metric-name=custom.name", "spring.metrics.jdbc.datasource-metric-name=custom.name",
"spring.metrics.use-global-registry=false") "spring.metrics.use-global-registry=false")
@ -76,7 +78,8 @@ public class MetricsAutoConfigurationTests {
@Test @Test
public void dataSourceInstrumentationCanBeDisabled() { public void dataSourceInstrumentationCanBeDisabled() {
this.contextRunner this.contextRunner
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) .withConfiguration(
AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true", .withPropertyValues("spring.datasource.generate-unique-name=true",
"spring.metrics.jdbc.instrument-datasource=false", "spring.metrics.jdbc.instrument-datasource=false",
"spring.metrics.use-global-registry=false") "spring.metrics.use-global-registry=false")
@ -90,15 +93,15 @@ public class MetricsAutoConfigurationTests {
@Test @Test
public void allDataSourcesCanBeInstrumented() { public void allDataSourcesCanBeInstrumented() {
this.contextRunner this.contextRunner.withUserConfiguration(TwoDataSourcesConfiguration.class)
.withUserConfiguration(TwoDataSourcesConfiguration.class) .withConfiguration(
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("metrics.use-global-registry=false") .withPropertyValues("metrics.use-global-registry=false")
.run((context) -> { .run((context) -> {
context.getBean("firstDataSource", DataSource.class) context.getBean("firstDataSource", DataSource.class).getConnection()
.getConnection().getMetaData(); .getMetaData();
context.getBean("secondOne", DataSource.class) context.getBean("secondOne", DataSource.class).getConnection()
.getConnection().getMetaData(); .getMetaData();
MeterRegistry registry = context.getBean(MeterRegistry.class); MeterRegistry registry = context.getBean(MeterRegistry.class);
assertThat(registry.find("data.source.max.connections") assertThat(registry.find("data.source.max.connections")
.tags("name", "first").meter()).isPresent(); .tags("name", "first").meter()).isPresent();

@ -18,8 +18,7 @@ package org.springframework.boot.actuate.endpoint;
/** /**
* A {@code ParameterMappingException} is thrown when a failure occurs during * A {@code ParameterMappingException} is thrown when a failure occurs during
* {@link ParameterMapper#mapParameter(Object, Class) operation parameter * {@link ParameterMapper#mapParameter(Object, Class) operation parameter mapping}.
* mapping}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.0.0 * @since 2.0.0

@ -23,15 +23,14 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.DefaultFormattingConversionService;
/** /**
* {@link ParameterMapper} that uses a {@link ConversionService} to map parameter * {@link ParameterMapper} that uses a {@link ConversionService} to map parameter values
* values if necessary. * if necessary.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Phillip Webb * @author Phillip Webb
* @since 2.0.0 * @since 2.0.0
*/ */
public class ConversionServiceParameterMapper public class ConversionServiceParameterMapper implements ParameterMapper {
implements ParameterMapper {
private final ConversionService conversionService; private final ConversionService conversionService;
@ -43,8 +42,7 @@ public class ConversionServiceParameterMapper
* Create a new instance with the {@link ConversionService} to use. * Create a new instance with the {@link ConversionService} to use.
* @param conversionService the conversion service * @param conversionService the conversion service
*/ */
public ConversionServiceParameterMapper( public ConversionServiceParameterMapper(ConversionService conversionService) {
ConversionService conversionService) {
this.conversionService = new BinderConversionService(conversionService); this.conversionService = new BinderConversionService(conversionService);
} }

@ -115,8 +115,8 @@ public class JmxAnnotationEndpointDiscoverer
public JmxEndpointOperation createOperation(String endpointId, public JmxEndpointOperation createOperation(String endpointId,
AnnotationAttributes operationAttributes, Object target, Method method, AnnotationAttributes operationAttributes, Object target, Method method,
OperationType type, long timeToLive) { OperationType type, long timeToLive) {
ReflectiveOperationInvoker invoker = new ReflectiveOperationInvoker( ReflectiveOperationInvoker invoker = new ReflectiveOperationInvoker(target,
target, method, this.parameterMapper); method, this.parameterMapper);
String operationName = method.getName(); String operationName = method.getName();
Class<?> outputType = getJmxType(method.getReturnType()); Class<?> outputType = getJmxType(method.getReturnType());
String description = getDescription(method, String description = getDescription(method,

@ -32,4 +32,12 @@ public interface EndpointPathResolver {
*/ */
String resolvePath(String endpointId); String resolvePath(String endpointId);
/**
* Returns an {@link EndpointPathResolver} that uses the endpoint ID as the path.
* @return an {@link EndpointPathResolver} that uses the endpoint ID as the path
*/
static EndpointPathResolver useEndpointId() {
return (endpointId) -> endpointId;
}
} }

@ -30,8 +30,8 @@ import org.reactivestreams.Publisher;
import org.springframework.boot.actuate.endpoint.EndpointExposure; import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationInvoker;
import org.springframework.boot.actuate.endpoint.ParameterMapper;
import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.OperationType;
import org.springframework.boot.actuate.endpoint.ParameterMapper;
import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker;
import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
@ -67,8 +67,8 @@ public class WebAnnotationEndpointDiscoverer extends
* {@link Endpoint endpoints} and {@link WebEndpointExtension web extensions} using * {@link Endpoint endpoints} and {@link WebEndpointExtension web extensions} using
* the given {@link ApplicationContext}. * the given {@link ApplicationContext}.
* @param applicationContext the application context * @param applicationContext the application context
* @param parameterMapper the {@link ParameterMapper} used to * @param parameterMapper the {@link ParameterMapper} used to convert arguments when
* convert arguments when an operation is invoked * an operation is invoked
* @param cachingConfigurationFactory the {@link CachingConfiguration} factory to use * @param cachingConfigurationFactory the {@link CachingConfiguration} factory to use
* @param endpointMediaTypes the media types produced and consumed by web endpoint * @param endpointMediaTypes the media types produced and consumed by web endpoint
* operations * operations
@ -81,8 +81,8 @@ public class WebAnnotationEndpointDiscoverer extends
EndpointMediaTypes endpointMediaTypes, EndpointMediaTypes endpointMediaTypes,
EndpointPathResolver endpointPathResolver) { EndpointPathResolver endpointPathResolver) {
super(applicationContext, super(applicationContext,
new WebEndpointOperationFactory(parameterMapper, new WebEndpointOperationFactory(parameterMapper, endpointMediaTypes,
endpointMediaTypes, endpointPathResolver), endpointPathResolver),
WebEndpointOperation::getRequestPredicate, cachingConfigurationFactory); WebEndpointOperation::getRequestPredicate, cachingConfigurationFactory);
} }
@ -145,8 +145,8 @@ public class WebAnnotationEndpointDiscoverer extends
determineConsumedMediaTypes(httpMethod, method), determineConsumedMediaTypes(httpMethod, method),
determineProducedMediaTypes( determineProducedMediaTypes(
operationAttributes.getStringArray("produces"), method)); operationAttributes.getStringArray("produces"), method));
OperationInvoker invoker = new ReflectiveOperationInvoker( OperationInvoker invoker = new ReflectiveOperationInvoker(target, method,
target, method, this.parameterMapper); this.parameterMapper);
if (timeToLive > 0) { if (timeToLive > 0) {
invoker = new CachingOperationInvoker(invoker, timeToLive); invoker = new CachingOperationInvoker(invoker, timeToLive);
} }

@ -31,8 +31,7 @@ public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthI
@Override @Override
public final Mono<Health> health() { public final Mono<Health> health() {
try { try {
return doHealthCheck(new Health.Builder()) return doHealthCheck(new Health.Builder()).onErrorResume(this::handleFailure);
.onErrorResume(this::handleFailure);
} }
catch (Exception ex) { catch (Exception ex) {
return handleFailure(ex); return handleFailure(ex);

@ -385,7 +385,7 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
DefaultConversionService.getSharedInstance()); DefaultConversionService.getSharedInstance());
return new WebAnnotationEndpointDiscoverer(applicationContext, return new WebAnnotationEndpointDiscoverer(applicationContext,
parameterMapper, (id) -> new CachingConfiguration(0), parameterMapper, (id) -> new CachingConfiguration(0),
endpointMediaTypes(), (id) -> id); endpointMediaTypes(), EndpointPathResolver.useEndpointId());
} }
@Bean @Bean

@ -245,11 +245,12 @@ public class WebAnnotationEndpointDiscovererTests {
discoverer.discoverEndpoints()); discoverer.discoverEndpoints());
assertThat(endpoints).containsOnlyKeys("test"); assertThat(endpoints).containsOnlyKeys("test");
EndpointInfo<WebEndpointOperation> endpoint = endpoints.get("test"); EndpointInfo<WebEndpointOperation> endpoint = endpoints.get("test");
assertThat(requestPredicates(endpoint)).has(requestPredicates( Condition<List<? extends OperationRequestPredicate>> expected = requestPredicates(
path("custom/test").httpMethod(WebEndpointHttpMethod.GET).consumes() path("custom/test").httpMethod(WebEndpointHttpMethod.GET)
.produces("application/json"), .consumes().produces("application/json"),
path("custom/test/{id}").httpMethod(WebEndpointHttpMethod.GET).consumes() path("custom/test/{id}").httpMethod(WebEndpointHttpMethod.GET)
.produces("application/json"))); .consumes().produces("application/json"));
assertThat(requestPredicates(endpoint)).has(expected);
}); });
} }
@ -259,18 +260,16 @@ public class WebAnnotationEndpointDiscovererTests {
} }
private void load(CachingConfigurationFactory cachingConfigurationFactory, private void load(CachingConfigurationFactory cachingConfigurationFactory,
EndpointPathResolver endpointPathResolver, EndpointPathResolver endpointPathResolver, Class<?> configuration,
Class<?> configuration, Consumer<WebAnnotationEndpointDiscoverer> consumer) { Consumer<WebAnnotationEndpointDiscoverer> consumer) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
configuration); configuration);
try { try {
consumer.accept( consumer.accept(new WebAnnotationEndpointDiscoverer(context,
new WebAnnotationEndpointDiscoverer(context,
new ConversionServiceParameterMapper( new ConversionServiceParameterMapper(
DefaultConversionService.getSharedInstance()), DefaultConversionService.getSharedInstance()),
cachingConfigurationFactory, cachingConfigurationFactory,
new EndpointMediaTypes( new EndpointMediaTypes(Collections.singletonList("application/json"),
Collections.singletonList("application/json"),
Collections.singletonList("application/json")), Collections.singletonList("application/json")),
endpointPathResolver)); endpointPathResolver));
} }

@ -31,6 +31,7 @@ import org.junit.runners.model.InitializationError;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper; import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.jersey.JerseyEndpointResourceFactory; import org.springframework.boot.actuate.endpoint.web.jersey.JerseyEndpointResourceFactory;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@ -97,9 +98,9 @@ class JerseyEndpointsRunner extends AbstractWebEndpointRunner {
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes, EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes,
mediaTypes); mediaTypes);
WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer( WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext, this.applicationContext, new ConversionServiceParameterMapper(),
new ConversionServiceParameterMapper(), (id) -> null, (id) -> null, endpointMediaTypes,
endpointMediaTypes, (id) -> id); EndpointPathResolver.useEndpointId());
Collection<Resource> resources = new JerseyEndpointResourceFactory() Collection<Resource> resources = new JerseyEndpointResourceFactory()
.createEndpointResources(new EndpointMapping("/application"), .createEndpointResources(new EndpointMapping("/application"),
discoverer.discoverEndpoints(), endpointMediaTypes); discoverer.discoverEndpoints(), endpointMediaTypes);

@ -25,6 +25,7 @@ import org.junit.runners.model.InitializationError;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper; import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping; import org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@ -103,9 +104,9 @@ class WebFluxEndpointsRunner extends AbstractWebEndpointRunner {
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes, EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes,
mediaTypes); mediaTypes);
WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer( WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext, this.applicationContext, new ConversionServiceParameterMapper(),
new ConversionServiceParameterMapper(), (id) -> null, (id) -> null, endpointMediaTypes,
endpointMediaTypes, (id) -> id); EndpointPathResolver.useEndpointId());
return new WebFluxEndpointHandlerMapping(new EndpointMapping("/application"), return new WebFluxEndpointHandlerMapping(new EndpointMapping("/application"),
discoverer.discoverEndpoints(), endpointMediaTypes, discoverer.discoverEndpoints(), endpointMediaTypes,
new CorsConfiguration()); new CorsConfiguration());

@ -25,6 +25,7 @@ import org.junit.runners.model.InitializationError;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper; import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping; import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@ -86,9 +87,9 @@ class WebMvcEndpointRunner extends AbstractWebEndpointRunner {
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes, EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes,
mediaTypes); mediaTypes);
WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer( WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext, this.applicationContext, new ConversionServiceParameterMapper(),
new ConversionServiceParameterMapper(), (id) -> null, (id) -> null, endpointMediaTypes,
endpointMediaTypes, (id) -> id); EndpointPathResolver.useEndpointId());
return new WebMvcEndpointHandlerMapping(new EndpointMapping("/application"), return new WebMvcEndpointHandlerMapping(new EndpointMapping("/application"),
discoverer.discoverEndpoints(), endpointMediaTypes, discoverer.discoverEndpoints(), endpointMediaTypes,
new CorsConfiguration()); new CorsConfiguration());

@ -80,7 +80,8 @@ public class BatchAutoConfiguration {
@ConditionalOnBean(DataSource.class) @ConditionalOnBean(DataSource.class)
public BatchDataSourceInitializer batchDataSourceInitializer(DataSource dataSource, public BatchDataSourceInitializer batchDataSourceInitializer(DataSource dataSource,
ResourceLoader resourceLoader) { ResourceLoader resourceLoader) {
return new BatchDataSourceInitializer(dataSource, resourceLoader, this.properties); return new BatchDataSourceInitializer(dataSource, resourceLoader,
this.properties);
} }
@Bean @Bean

@ -141,8 +141,8 @@ public class JobLauncherCommandLineRunner
throws JobExecutionAlreadyRunningException, JobRestartException, throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException, JobInstanceAlreadyCompleteException, JobParametersInvalidException,
JobParametersNotFoundException { JobParametersNotFoundException {
JobParameters nextParameters = new JobParametersBuilder(jobParameters, this.jobExplorer) JobParameters nextParameters = new JobParametersBuilder(jobParameters,
.getNextJobParameters(job).toJobParameters(); this.jobExplorer).getNextJobParameters(job).toJobParameters();
JobExecution execution = this.jobLauncher.run(job, nextParameters); JobExecution execution = this.jobLauncher.run(job, nextParameters);
if (this.publisher != null) { if (this.publisher != null) {
this.publisher.publishEvent(new JobExecutionEvent(execution)); this.publisher.publishEvent(new JobExecutionEvent(execution));

@ -129,8 +129,7 @@ class DataSourceInitializer {
if (mode == DataSourceInitializationMode.NEVER) { if (mode == DataSourceInitializationMode.NEVER) {
return false; return false;
} }
if (mode == DataSourceInitializationMode.EMBEDDED if (mode == DataSourceInitializationMode.EMBEDDED && !isEmbedded()) {
&& !isEmbedded()) {
return false; return false;
} }
return true; return true;

@ -153,7 +153,8 @@ public class QuartzAutoConfiguration {
public QuartzDataSourceInitializer quartzDataSourceInitializer( public QuartzDataSourceInitializer quartzDataSourceInitializer(
DataSource dataSource, ResourceLoader resourceLoader, DataSource dataSource, ResourceLoader resourceLoader,
QuartzProperties properties) { QuartzProperties properties) {
return new QuartzDataSourceInitializer(dataSource, resourceLoader, properties); return new QuartzDataSourceInitializer(dataSource, resourceLoader,
properties);
} }
@Bean @Bean

@ -33,8 +33,8 @@ public class QuartzDataSourceInitializer extends AbstractDataSourceInitializer {
private final QuartzProperties properties; private final QuartzProperties properties;
public QuartzDataSourceInitializer(DataSource dataSource, ResourceLoader resourceLoader, public QuartzDataSourceInitializer(DataSource dataSource,
QuartzProperties properties) { ResourceLoader resourceLoader, QuartzProperties properties) {
super(dataSource, resourceLoader); super(dataSource, resourceLoader);
Assert.notNull(properties, "QuartzProperties must not be null"); Assert.notNull(properties, "QuartzProperties must not be null");
this.properties = properties; this.properties = properties;

@ -40,7 +40,8 @@ class OAuth2WebSecurityConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository clientRegistrationRepository) { public OAuth2AuthorizedClientService authorizedClientService(
ClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository); return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
} }

@ -58,12 +58,16 @@ class ReactiveAuthenticationManagerConfiguration {
ObjectProvider<PasswordEncoder> passwordEncoder) { ObjectProvider<PasswordEncoder> passwordEncoder) {
String password = UUID.randomUUID().toString(); String password = UUID.randomUUID().toString();
logger.info(String.format("%n%nUsing default security password: %s%n", password)); logger.info(String.format("%n%nUsing default security password: %s%n", password));
UserDetails userDetails = getUserDetails(password, passwordEncoder);
return new MapReactiveUserDetailsService(userDetails);
}
private UserDetails getUserDetails(String password,
ObjectProvider<PasswordEncoder> passwordEncoder) {
String encodedPassword = passwordEncoder String encodedPassword = passwordEncoder
.getIfAvailable(PasswordEncoderFactories::createDelegatingPasswordEncoder) .getIfAvailable(PasswordEncoderFactories::createDelegatingPasswordEncoder)
.encode(password); .encode(password);
UserDetails user = User.withUsername("user").password(encodedPassword).roles() return User.withUsername("user").password(encodedPassword).roles().build();
.build();
return new MapReactiveUserDetailsService(user);
} }
} }

@ -52,7 +52,8 @@ class JdbcSessionConfiguration {
public JdbcSessionDataSourceInitializer jdbcSessionDataSourceInitializer( public JdbcSessionDataSourceInitializer jdbcSessionDataSourceInitializer(
DataSource dataSource, ResourceLoader resourceLoader, DataSource dataSource, ResourceLoader resourceLoader,
JdbcSessionProperties properties) { JdbcSessionProperties properties) {
return new JdbcSessionDataSourceInitializer(dataSource, resourceLoader, properties); return new JdbcSessionDataSourceInitializer(dataSource, resourceLoader,
properties);
} }
@Configuration @Configuration

@ -155,6 +155,7 @@ public abstract class AbstractErrorWebExceptionHandler
} }
} }
catch (Exception ex) { catch (Exception ex) {
// Ignore
} }
} }
return null; return null;
@ -205,17 +206,23 @@ public abstract class AbstractErrorWebExceptionHandler
@Override @Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) { public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {
this.errorAttributes.storeErrorInformation(throwable, exchange); this.errorAttributes.storeErrorInformation(throwable, exchange);
ServerRequest request = ServerRequest.create(exchange, this.messageReaders); ServerRequest request = ServerRequest.create(exchange, this.messageReaders);
return getRoutingFunction(this.errorAttributes).route(request) return getRoutingFunction(this.errorAttributes).route(request)
.switchIfEmpty(Mono.error(throwable)) .switchIfEmpty(Mono.error(throwable))
.flatMap((handler) -> handler.handle(request)).flatMap((response) -> { .flatMap((handler) -> handler.handle(request))
// force content-type since writeTo won't overwrite response header .flatMap((response) -> write(exchange, response));
// values }
private Mono<? extends Void> write(ServerWebExchange exchange,
ServerResponse response) {
// force content-type since writeTo won't overwrite response header values
exchange.getResponse().getHeaders() exchange.getResponse().getHeaders()
.setContentType(response.headers().getContentType()); .setContentType(response.headers().getContentType());
return response.writeTo(exchange, new ServerResponse.Context() { return response.writeTo(exchange, new ResponseContext());
}
private class ResponseContext implements ServerResponse.Context {
@Override @Override
public List<HttpMessageWriter<?>> messageWriters() { public List<HttpMessageWriter<?>> messageWriters() {
@ -227,8 +234,6 @@ public abstract class AbstractErrorWebExceptionHandler
return AbstractErrorWebExceptionHandler.this.viewResolvers; return AbstractErrorWebExceptionHandler.this.viewResolvers;
} }
});
});
} }
} }

@ -124,7 +124,6 @@ public class DefaultErrorAttributes implements ErrorAttributes {
@Override @Override
public void storeErrorInformation(Throwable error, ServerWebExchange exchange) { public void storeErrorInformation(Throwable error, ServerWebExchange exchange) {
exchange.getAttributes().putIfAbsent(ERROR_ATTRIBUTE, error); exchange.getAttributes().putIfAbsent(ERROR_ATTRIBUTE, error);
} }
} }

@ -40,12 +40,10 @@ import org.springframework.web.reactive.function.server.ServerResponse;
/** /**
* Basic global {@link org.springframework.web.server.WebExceptionHandler}, rendering * Basic global {@link org.springframework.web.server.WebExceptionHandler}, rendering
* {@link ErrorAttributes}. * {@link ErrorAttributes}.
*
* <p> * <p>
* More specific errors can be handled either using Spring WebFlux abstractions (e.g. * More specific errors can be handled either using Spring WebFlux abstractions (e.g.
* {@code @ExceptionHandler} with the annotation model) or by adding * {@code @ExceptionHandler} with the annotation model) or by adding
* {@link RouterFunction} to the chain. * {@link RouterFunction} to the chain.
*
* <p> * <p>
* This implementation will render error as HTML views if the client explicitly supports * This implementation will render error as HTML views if the client explicitly supports
* that media type. It attempts to resolve error views using well known conventions. Will * that media type. It attempts to resolve error views using well known conventions. Will
@ -61,10 +59,8 @@ import org.springframework.web.reactive.function.server.ServerResponse;
* <li>{@code '/<templates>/error/error'}</li> * <li>{@code '/<templates>/error/error'}</li>
* <li>{@code '/<static>/error/error.html'}</li> * <li>{@code '/<static>/error/error.html'}</li>
* </ul> * </ul>
*
* <p> * <p>
* If none found, a default "Whitelabel Error" HTML view will be rendered. * If none found, a default "Whitelabel Error" HTML view will be rendered.
*
* <p> * <p>
* If the client doesn't support HTML, the error information will be rendered as a JSON * If the client doesn't support HTML, the error information will be rendered as a JSON
* payload. * payload.
@ -87,7 +83,6 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
/** /**
* Create a new {@code DefaultErrorWebExceptionHandler} instance. * Create a new {@code DefaultErrorWebExceptionHandler} instance.
*
* @param errorAttributes the error attributes * @param errorAttributes the error attributes
* @param resourceProperties the resources configuration properties * @param resourceProperties the resources configuration properties
* @param errorProperties the error configuration properties * @param errorProperties the error configuration properties
@ -103,7 +98,6 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
@Override @Override
protected RouterFunction<ServerResponse> getRoutingFunction( protected RouterFunction<ServerResponse> getRoutingFunction(
ErrorAttributes errorAttributes) { ErrorAttributes errorAttributes) {
return RouterFunctions.route(acceptsTextHtml(), this::renderErrorView) return RouterFunctions.route(acceptsTextHtml(), this::renderErrorView)
.andRoute(RequestPredicates.all(), this::renderErrorResponse); .andRoute(RequestPredicates.all(), this::renderErrorResponse);
} }
@ -116,11 +110,9 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
protected Mono<ServerResponse> renderErrorView(ServerRequest request) { protected Mono<ServerResponse> renderErrorView(ServerRequest request) {
boolean includeStackTrace = isIncludeStackTrace(request, MediaType.TEXT_HTML); boolean includeStackTrace = isIncludeStackTrace(request, MediaType.TEXT_HTML);
Map<String, Object> error = getErrorAttributes(request, includeStackTrace); Map<String, Object> error = getErrorAttributes(request, includeStackTrace);
HttpStatus errorStatus = getHttpStatus(error); HttpStatus errorStatus = getHttpStatus(error);
ServerResponse.BodyBuilder response = ServerResponse.status(errorStatus) ServerResponse.BodyBuilder response = ServerResponse.status(errorStatus)
.contentType(MediaType.TEXT_HTML); .contentType(MediaType.TEXT_HTML);
return Flux return Flux
.just("error/" + errorStatus.toString(), .just("error/" + errorStatus.toString(),
"error/" + SERIES_VIEWS.get(errorStatus.series()), "error/error") "error/" + SERIES_VIEWS.get(errorStatus.series()), "error/error")

@ -94,8 +94,7 @@ public class MixedNeo4jRepositoriesAutoConfigurationTests {
private void load(Class<?> config, String... environment) { private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
TestPropertyValues.of(environment) TestPropertyValues.of(environment)
.and("spring.datasource.initialization-mode=never") .and("spring.datasource.initialization-mode=never").applyTo(context);
.applyTo(context);
context.register(config); context.register(config);
context.register(DataSourceAutoConfiguration.class, context.register(DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,

@ -111,8 +111,7 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithMultipleScripts() { public void dataSourceInitializedWithMultipleScripts() {
this.contextRunner this.contextRunner
.withPropertyValues( .withPropertyValues("spring.datasource.initialization-mode:always",
"spring.datasource.initialization-mode:always",
"spring.datasource.schema:" + getRelativeLocationFor("schema.sql") "spring.datasource.schema:" + getRelativeLocationFor("schema.sql")
+ "," + getRelativeLocationFor("another.sql"), + "," + getRelativeLocationFor("another.sql"),
"spring.datasource.data:" + getRelativeLocationFor("data.sql")) "spring.datasource.data:" + getRelativeLocationFor("data.sql"))
@ -130,12 +129,13 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithExplicitSqlScriptEncoding() { public void dataSourceInitializedWithExplicitSqlScriptEncoding() {
this.contextRunner.withPropertyValues( this.contextRunner
"spring.datasource.initialization-mode:always", .withPropertyValues("spring.datasource.initialization-mode:always",
"spring.datasource.sqlScriptEncoding:UTF-8", "spring.datasource.sqlScriptEncoding:UTF-8",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("encoding-schema.sql"), + getRelativeLocationFor("encoding-schema.sql"),
"spring.datasource.data:" + getRelativeLocationFor("encoding-data.sql")) "spring.datasource.data:"
+ getRelativeLocationFor("encoding-data.sql"))
.run((context) -> { .run((context) -> {
DataSource dataSource = context.getBean(DataSource.class); DataSource dataSource = context.getBean(DataSource.class);
assertThat(dataSource).isInstanceOf(HikariDataSource.class); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
@ -266,8 +266,7 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithInvalidDataResource() { public void dataSourceInitializedWithInvalidDataResource() {
this.contextRunner this.contextRunner
.withPropertyValues( .withPropertyValues("spring.datasource.initialization-mode:always",
"spring.datasource.initialization-mode:always",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("schema.sql"), + getRelativeLocationFor("schema.sql"),
"spring.datasource.data:classpath:does/not/exist.sql") "spring.datasource.data:classpath:does/not/exist.sql")

@ -94,7 +94,6 @@ public class DataSourceInitializerTests {
given(connection.getMetaData()).willReturn(metadata); given(connection.getMetaData()).willReturn(metadata);
DataSource dataSource = mock(DataSource.class); DataSource dataSource = mock(DataSource.class);
given(dataSource.getConnection()).willReturn(connection); given(dataSource.getConnection()).willReturn(connection);
DataSourceInitializer initializer = new DataSourceInitializer(dataSource, DataSourceInitializer initializer = new DataSourceInitializer(dataSource,
new DataSourceProperties()); new DataSourceProperties());
assertThat(initializer.createSchema()).isFalse(); assertThat(initializer.createSchema()).isFalse();

@ -68,8 +68,8 @@ public class DataSourcePropertiesTests {
@Test @Test
public void determineUrlWithNoEmbeddedSupport() throws Exception { public void determineUrlWithNoEmbeddedSupport() throws Exception {
DataSourceProperties properties = new DataSourceProperties(); DataSourceProperties properties = new DataSourceProperties();
properties.setBeanClassLoader(new HidePackagesClassLoader("org.h2", properties.setBeanClassLoader(
"org.apache.derby", "org.hsqldb")); new HidePackagesClassLoader("org.h2", "org.apache.derby", "org.hsqldb"));
properties.afterPropertiesSet(); properties.afterPropertiesSet();
this.thrown.expect(DataSourceProperties.DataSourceBeanCreationException.class); this.thrown.expect(DataSourceProperties.DataSourceBeanCreationException.class);
this.thrown.expectMessage("Cannot determine embedded database url"); this.thrown.expectMessage("Cannot determine embedded database url");

@ -121,14 +121,12 @@ public class JndiDataSourceAutoConfigurationTests {
throws IllegalStateException, NamingException { throws IllegalStateException, NamingException {
DataSource dataSource = new BasicDataSource(); DataSource dataSource = new BasicDataSource();
configureJndi("foo", dataSource); configureJndi("foo", dataSource);
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.jndi-name:foo").applyTo(this.context); TestPropertyValues.of("spring.datasource.jndi-name:foo").applyTo(this.context);
this.context.register(JndiDataSourceAutoConfiguration.class, this.context.register(JndiDataSourceAutoConfiguration.class,
MBeanExporterConfiguration.class, MBeanExporterConfiguration.class,
AnotherMBeanExporterConfiguration.class); AnotherMBeanExporterConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(DataSource.class)).isEqualTo(dataSource); assertThat(this.context.getBean(DataSource.class)).isEqualTo(dataSource);
for (MBeanExporter exporter : this.context.getBeansOfType(MBeanExporter.class) for (MBeanExporter exporter : this.context.getBeansOfType(MBeanExporter.class)
.values()) { .values()) {

@ -328,8 +328,7 @@ public class KafkaAutoConfigurationTests {
@Test @Test
public void testConcurrentKafkaListenerContainerFactoryWithKafkaTemplate() { public void testConcurrentKafkaListenerContainerFactoryWithKafkaTemplate() {
this.contextRunner this.contextRunner.run((context) -> {
.run((context) -> {
ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory = context ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory = context
.getBean(ConcurrentKafkaListenerContainerFactory.class); .getBean(ConcurrentKafkaListenerContainerFactory.class);
DirectFieldAccessor dfa = new DirectFieldAccessor( DirectFieldAccessor dfa = new DirectFieldAccessor(

@ -208,8 +208,10 @@ public class SecurityAutoConfigurationTests {
public void testJpaCoexistsHappily() throws Exception { public void testJpaCoexistsHappily() throws Exception {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
TestPropertyValues.of("spring.datasource.url:jdbc:hsqldb:mem:testsecdb", TestPropertyValues
"spring.datasource.initialization-mode:never").applyTo(this.context); .of("spring.datasource.url:jdbc:hsqldb:mem:testsecdb",
"spring.datasource.initialization-mode:never")
.applyTo(this.context);
this.context.register(EntityConfiguration.class, this.context.register(EntityConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,

@ -92,11 +92,10 @@ public class OAuth2WebSecurityConfigurationTests {
@Test @Test
public void configurationRegistersAuthorizedClientServiceBean() throws Exception { public void configurationRegistersAuthorizedClientServiceBean() throws Exception {
this.contextRunner this.contextRunner.withUserConfiguration(ClientRepositoryConfiguration.class,
.withUserConfiguration(ClientRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class).run(context -> {
OAuth2WebSecurityConfiguration.class) OAuth2AuthorizedClientService bean = context
.run(context -> { .getBean(OAuth2AuthorizedClientService.class);
OAuth2AuthorizedClientService bean = context.getBean(OAuth2AuthorizedClientService.class);
OAuth2AuthorizedClientService authorizedClientService = (OAuth2AuthorizedClientService) ReflectionTestUtils OAuth2AuthorizedClientService authorizedClientService = (OAuth2AuthorizedClientService) ReflectionTestUtils
.getField(getAuthCodeFilters(context).get(0), .getField(getAuthCodeFilters(context).get(0),
"authorizedClientService"); "authorizedClientService");
@ -110,7 +109,8 @@ public class OAuth2WebSecurityConfigurationTests {
.withUserConfiguration(OAuth2AuthorizedClientServiceConfiguration.class, .withUserConfiguration(OAuth2AuthorizedClientServiceConfiguration.class,
OAuth2WebSecurityConfiguration.class) OAuth2WebSecurityConfiguration.class)
.run(context -> { .run(context -> {
OAuth2AuthorizedClientService bean = context.getBean(OAuth2AuthorizedClientService.class); OAuth2AuthorizedClientService bean = context
.getBean(OAuth2AuthorizedClientService.class);
OAuth2AuthorizedClientService authorizedClientService = (OAuth2AuthorizedClientService) ReflectionTestUtils OAuth2AuthorizedClientService authorizedClientService = (OAuth2AuthorizedClientService) ReflectionTestUtils
.getField(getAuthCodeFilters(context).get(0), .getField(getAuthCodeFilters(context).get(0),
"authorizedClientService"); "authorizedClientService");
@ -211,8 +211,10 @@ public class OAuth2WebSecurityConfigurationTests {
static class OAuth2AuthorizedClientServiceConfiguration { static class OAuth2AuthorizedClientServiceConfiguration {
@Bean @Bean
public OAuth2AuthorizedClientService testAuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) { public OAuth2AuthorizedClientService testAuthorizedClientService(
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository); ClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(
clientRegistrationRepository);
} }
} }

@ -56,8 +56,7 @@ public class ReactiveSecurityAutoConfigurationTests {
.withConfiguration( .withConfiguration(
AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class)) AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class))
.run((context) -> { .run((context) -> {
assertThat(context).getBean(WebFilterChainProxy.class) assertThat(context).getBean(WebFilterChainProxy.class).isNotNull();
.isNotNull();
assertThat(context).getBean(WebFluxSecurityConfiguration.class) assertThat(context).getBean(WebFluxSecurityConfiguration.class)
.isNotNull(); .isNotNull();
assertThat(context).getBean(WebFilterChainProxy.class).isNotNull(); assertThat(context).getBean(WebFilterChainProxy.class).isNotNull();

@ -159,11 +159,9 @@ public class DefaultErrorAttributesTests {
Collections.singletonMap("a", "b"), "objectName"); Collections.singletonMap("a", "b"), "objectName");
bindingResult.addError(new ObjectError("c", "d")); bindingResult.addError(new ObjectError("c", "d"));
Exception ex = new WebExchangeBindException(stringParam, bindingResult); Exception ex = new WebExchangeBindException(stringParam, bindingResult);
MockServerHttpRequest request = MockServerHttpRequest.get("/test").build(); MockServerHttpRequest request = MockServerHttpRequest.get("/test").build();
Map<String, Object> attributes = this.errorAttributes Map<String, Object> attributes = this.errorAttributes
.getErrorAttributes(buildServerRequest(request, ex), false); .getErrorAttributes(buildServerRequest(request, ex), false);
assertThat(attributes.get("message")).asString() assertThat(attributes.get("message")).asString()
.startsWith("Validation failed for argument at index 0 in method: " .startsWith("Validation failed for argument at index 0 in method: "
+ "public int org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorAttributesTests" + "public int org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorAttributesTests"

@ -71,12 +71,14 @@ public class WebTestClientSpringBootTestIntegrationTests {
@Configuration @Configuration
static class TestConfiguration { static class TestConfiguration {
@Bean @Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
throws Exception { throws Exception {
http.authorizeExchange().anyExchange().permitAll(); http.authorizeExchange().anyExchange().permitAll();
return http.build(); return http.build();
} }
} }
} }

@ -708,8 +708,8 @@ public class ConfigurationMetadataAnnotationProcessorTests {
private Metadata.MetadataItemCondition webPath(String endpointId) { private Metadata.MetadataItemCondition webPath(String endpointId) {
return Metadata.withProperty("endpoints." + endpointId + ".web.path") return Metadata.withProperty("endpoints." + endpointId + ".web.path")
.ofType(String.class).withDefaultValue(endpointId).withDescription(String .ofType(String.class).withDefaultValue(endpointId)
.format("Path of the %s endpoint.", endpointId)); .withDescription(String.format("Path of the %s endpoint.", endpointId));
} }
private Metadata.MetadataItemCondition cacheTtl(String endpointId) { private Metadata.MetadataItemCondition cacheTtl(String endpointId) {

@ -141,9 +141,8 @@ final class JavaPluginAction implements PluginApplicationAction {
private void configureAdditionalMetadataLocations(Project project) { private void configureAdditionalMetadataLocations(Project project) {
project.afterEvaluate((evaluated) -> { project.afterEvaluate((evaluated) -> {
evaluated.getTasks().withType(JavaCompile.class, (compile) -> { evaluated.getTasks().withType(JavaCompile.class,
configureAdditionalMetadataLocations(project, compile); (compile) -> configureAdditionalMetadataLocations(project, compile));
});
}); });
} }

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

@ -118,20 +118,20 @@ public class ConfigurationPropertiesBindingPostProcessor
+ "PropertySourcesPlaceholderConfigurer or Environment"); + "PropertySourcesPlaceholderConfigurer or Environment");
} }
PropertySources appliedPropertySources = configurer.getAppliedPropertySources(); PropertySources appliedPropertySources = configurer.getAppliedPropertySources();
return environmentPropertySources == null ? appliedPropertySources if (environmentPropertySources == null) {
: new CompositePropertySources( return appliedPropertySources;
}
return new CompositePropertySources(
new FilteredPropertySources(appliedPropertySources, new FilteredPropertySources(appliedPropertySources,
PropertySourcesPlaceholderConfigurer.ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME), PropertySourcesPlaceholderConfigurer.ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME),
environmentPropertySources); environmentPropertySources);
} }
private MutablePropertySources extractEnvironmentPropertySources() { private MutablePropertySources extractEnvironmentPropertySources() {
MutablePropertySources environmentPropertySources = null;
if (this.environment instanceof ConfigurableEnvironment) { if (this.environment instanceof ConfigurableEnvironment) {
environmentPropertySources = ((ConfigurableEnvironment) this.environment) return ((ConfigurableEnvironment) this.environment).getPropertySources();
.getPropertySources();
} }
return environmentPropertySources; return null;
} }
private PropertySourcesPlaceholderConfigurer getSinglePropertySourcesPlaceholderConfigurer() { private PropertySourcesPlaceholderConfigurer getSinglePropertySourcesPlaceholderConfigurer() {

@ -20,7 +20,6 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
@ -33,21 +32,15 @@ import org.springframework.core.env.PropertySources;
*/ */
final class FilteredPropertySources implements PropertySources { final class FilteredPropertySources implements PropertySources {
private final Set<String> filtered;
private final PropertySources delegate; private final PropertySources delegate;
private final Set<String> filtered;
FilteredPropertySources(PropertySources delegate, String... filtered) { FilteredPropertySources(PropertySources delegate, String... filtered) {
this.delegate = delegate; this.delegate = delegate;
this.filtered = new HashSet<>(Arrays.asList(filtered)); this.filtered = new HashSet<>(Arrays.asList(filtered));
} }
@Override
public Iterator<PropertySource<?>> iterator() {
return StreamSupport.stream(this.delegate.spliterator(), false)
.filter(this::included).collect(Collectors.toList()).iterator();
}
@Override @Override
public boolean contains(String name) { public boolean contains(String name) {
if (included(name)) { if (included(name)) {
@ -64,6 +57,12 @@ final class FilteredPropertySources implements PropertySources {
return null; return null;
} }
@Override
public Iterator<PropertySource<?>> iterator() {
return StreamSupport.stream(this.delegate.spliterator(), false)
.filter(this::included).iterator();
}
private boolean included(PropertySource<?> propertySource) { private boolean included(PropertySource<?> propertySource) {
return included(propertySource.getName()); return included(propertySource.getName());
} }

@ -23,6 +23,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import reactor.ipc.netty.http.server.HttpServer; import reactor.ipc.netty.http.server.HttpServer;
import reactor.ipc.netty.http.server.HttpServerOptions.Builder;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
@ -66,33 +67,30 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
} }
/** /**
* Set {@link NettyServerCustomizer}s that should be applied to the Netty * Set {@link NettyServerCustomizer}s that should be applied to the Netty server
* server builder. Calling this method will replace any existing customizers. * builder. Calling this method will replace any existing customizers.
* @param nettyServerCustomizers the customizers to set * @param nettyServerCustomizers the customizers to set
*/ */
public void setNettyServerCustomizers( public void setNettyServerCustomizers(
Collection<? extends NettyServerCustomizer> nettyServerCustomizers) { Collection<? extends NettyServerCustomizer> nettyServerCustomizers) {
Assert.notNull(nettyServerCustomizers, Assert.notNull(nettyServerCustomizers, "NettyServerCustomizers must not be null");
"NettyServerCustomizers must not be null");
this.nettyServerCustomizers = new ArrayList<>(nettyServerCustomizers); this.nettyServerCustomizers = new ArrayList<>(nettyServerCustomizers);
} }
/** /**
* Add {@link NettyServerCustomizer}s that should applied while building the server. * Add {@link NettyServerCustomizer}s that should applied while building the server.
* @param nettyServerCustomizer the customizers to add * @param nettyServerCustomizer the customizers to add
*/ */
public void addContextCustomizers( public void addContextCustomizers(NettyServerCustomizer... nettyServerCustomizer) {
NettyServerCustomizer... nettyServerCustomizer) {
Assert.notNull(nettyServerCustomizer, Assert.notNull(nettyServerCustomizer,
"NettyWebServerCustomizer must not be null"); "NettyWebServerCustomizer must not be null");
this.nettyServerCustomizers.addAll(Arrays.asList(nettyServerCustomizer)); this.nettyServerCustomizers.addAll(Arrays.asList(nettyServerCustomizer));
} }
private HttpServer createHttpServer() { private HttpServer createHttpServer() {
return HttpServer.builder().options(options -> { return HttpServer.builder().options((options) -> {
options.listenAddress(getListenAddress()); options.listenAddress(getListenAddress());
this.nettyServerCustomizers.forEach(customizer -> customizer.customize(options)); applyCustomizers(options);
}).build(); }).build();
} }
@ -100,9 +98,12 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
if (getAddress() != null) { if (getAddress() != null) {
return new InetSocketAddress(getAddress().getHostAddress(), getPort()); return new InetSocketAddress(getAddress().getHostAddress(), getPort());
} }
else {
return new InetSocketAddress(getPort()); return new InetSocketAddress(getPort());
} }
private void applyCustomizers(Builder options) {
this.nettyServerCustomizers
.forEach((customizer) -> customizer.customize(options));
} }
} }

@ -33,4 +33,5 @@ public interface NettyServerCustomizer {
* @param builder the server options builder to customize * @param builder the server options builder to customize
*/ */
void customize(HttpServerOptions.Builder builder); void customize(HttpServerOptions.Builder builder);
} }

@ -20,7 +20,6 @@ import org.springframework.context.ConfigurableApplicationContext
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
* Top level function acting as a Kotlin shortcut allowing to write * Top level function acting as a Kotlin shortcut allowing to write
* `runApplication<FooApplication>(arg1, arg2)` instead of * `runApplication<FooApplication>(arg1, arg2)` instead of

@ -66,7 +66,6 @@ public class NettyReactiveWebServerFactoryTests
} }
factory.setNettyServerCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.setNettyServerCustomizers(Arrays.asList(customizers[0], customizers[1]));
this.webServer = factory.getWebServer(new EchoHandler()); this.webServer = factory.getWebServer(new EchoHandler());
InOrder ordered = inOrder((Object[]) customizers); InOrder ordered = inOrder((Object[]) customizers);
for (NettyServerCustomizer customizer : customizers) { for (NettyServerCustomizer customizer : customizers) {
ordered.verify(customizer).customize(any(HttpServerOptions.Builder.class)); ordered.verify(customizer).customize(any(HttpServerOptions.Builder.class));

@ -117,6 +117,7 @@ class SpringApplicationExtensionsTests {
open fun webServer(): MockServletWebServerFactory { open fun webServer(): MockServletWebServerFactory {
return MockServletWebServerFactory() return MockServletWebServerFactory()
} }
} }
} }

@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
"management.server.port=0", "management.server.context-path=/management"}) "management.server.port=0", "management.server.context-path=/management" })
@DirtiesContext @DirtiesContext
public class InsecureManagementPortAndPathSampleActuatorApplicationTests { public class InsecureManagementPortAndPathSampleActuatorApplicationTests {
@ -59,17 +59,17 @@ public class InsecureManagementPortAndPathSampleActuatorApplicationTests {
@Test @Test
public void testSecureActuator() throws Exception { public void testSecureActuator() throws Exception {
ResponseEntity<String> entity = new TestRestTemplate().getForEntity( ResponseEntity<String> entity = new TestRestTemplate()
"http://localhost:" + this.managementPort + "/management/application/health", .getForEntity("http://localhost:" + this.managementPort
String.class); + "/management/application/health", String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
} }
@Test @Test
public void testInsecureActuator() throws Exception { public void testInsecureActuator() throws Exception {
ResponseEntity<String> entity = new TestRestTemplate().getForEntity( ResponseEntity<String> entity = new TestRestTemplate()
"http://localhost:" + this.managementPort + "/management/application/status", .getForEntity("http://localhost:" + this.managementPort
String.class); + "/management/application/status", String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("\"status\":\"UP\""); assertThat(entity.getBody()).contains("\"status\":\"UP\"");
} }
@ -77,9 +77,8 @@ public class InsecureManagementPortAndPathSampleActuatorApplicationTests {
@Test @Test
public void testMissing() throws Exception { public void testMissing() throws Exception {
ResponseEntity<String> entity = new TestRestTemplate("admin", "admin") ResponseEntity<String> entity = new TestRestTemplate("admin", "admin")
.getForEntity( .getForEntity("http://localhost:" + this.managementPort
"http://localhost:" + this.managementPort + "/management/application/missing", + "/management/application/missing", String.class);
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
assertThat(entity.getBody()).contains("\"status\":404"); assertThat(entity.getBody()).contains("\"status\":404");
} }

@ -62,8 +62,8 @@ public class ManagementAddressActuatorApplicationTests {
@Test @Test
public void testHealth() throws Exception { public void testHealth() throws Exception {
ResponseEntity<String> entity = new TestRestTemplate() ResponseEntity<String> entity = new TestRestTemplate()
.withBasicAuth("user", getPassword()) .withBasicAuth("user", getPassword()).getForEntity("http://localhost:"
.getForEntity("http://localhost:" + this.managementPort + "/admin/application/health", + this.managementPort + "/admin/application/health",
String.class); String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("\"status\":\"UP\""); assertThat(entity.getBody()).contains("\"status\":\"UP\"");

@ -49,9 +49,9 @@ public class ServletPathSampleActuatorApplicationTests {
@Test @Test
public void testErrorPath() throws Exception { public void testErrorPath() throws Exception {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = this.restTemplate.withBasicAuth("user", getPassword()) ResponseEntity<Map> entity = this.restTemplate
.getForEntity("/spring/error", .withBasicAuth("user", getPassword())
Map.class); .getForEntity("/spring/error", Map.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> body = entity.getBody(); Map<String, Object> body = entity.getBody();

@ -30,7 +30,7 @@ public class City implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@SequenceGenerator(name="city_generator", sequenceName="city_sequence", initialValue = 23) @SequenceGenerator(name = "city_generator", sequenceName = "city_sequence", initialValue = 23)
@GeneratedValue(generator = "city_generator") @GeneratedValue(generator = "city_generator")
private Long id; private Long id;

@ -36,7 +36,7 @@ public class Hotel implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@SequenceGenerator(name="hotel_generator", sequenceName="hotel_sequence", initialValue = 28) @SequenceGenerator(name = "hotel_generator", sequenceName = "hotel_sequence", initialValue = 28)
@GeneratedValue(generator = "hotel_generator") @GeneratedValue(generator = "hotel_generator")
private Long id; private Long id;

@ -38,7 +38,7 @@ public class Review implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@SequenceGenerator(name="review_generator", sequenceName="review_sequence", initialValue = 64) @SequenceGenerator(name = "review_generator", sequenceName = "review_sequence", initialValue = 64)
@GeneratedValue(generator = "review_generator") @GeneratedValue(generator = "review_generator")
private Long id; private Long id;

@ -30,7 +30,7 @@ public class City implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@SequenceGenerator(name="city_generator", sequenceName="city_sequence", initialValue = 23) @SequenceGenerator(name = "city_generator", sequenceName = "city_sequence", initialValue = 23)
@GeneratedValue(generator = "city_generator") @GeneratedValue(generator = "city_generator")
private Long id; private Long id;

@ -33,7 +33,7 @@ public class Hotel implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@SequenceGenerator(name="hotel_generator", sequenceName="hotel_sequence", initialValue = 28) @SequenceGenerator(name = "hotel_generator", sequenceName = "hotel_sequence", initialValue = 28)
@GeneratedValue(generator = "hotel_generator") @GeneratedValue(generator = "hotel_generator")
private Long id; private Long id;

@ -24,7 +24,7 @@ import javax.persistence.SequenceGenerator;
@Entity @Entity
public class Person { public class Person {
@Id @Id
@SequenceGenerator(name="person_generator", sequenceName="person_sequence", allocationSize = 1) @SequenceGenerator(name = "person_generator", sequenceName = "person_sequence", allocationSize = 1)
@GeneratedValue(generator = "person_generator") @GeneratedValue(generator = "person_generator")
private Long id; private Long id;
private String firstName; private String firstName;

@ -28,7 +28,7 @@ import javax.persistence.SequenceGenerator;
public class Note { public class Note {
@Id @Id
@SequenceGenerator(name="note_generator", sequenceName="note_sequence", initialValue = 5) @SequenceGenerator(name = "note_generator", sequenceName = "note_sequence", initialValue = 5)
@GeneratedValue(generator = "note_generator") @GeneratedValue(generator = "note_generator")
private long id; private long id;

@ -57,10 +57,8 @@ public class SampleOAuth2ClientApplicationTests {
ResponseEntity<String> entity = this.restTemplate.getForEntity("/login", ResponseEntity<String> entity = this.restTemplate.getForEntity("/login",
String.class); String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()) assertThat(entity.getBody()).contains("/oauth2/authorization/github-client-1");
.contains("/oauth2/authorization/github-client-1"); assertThat(entity.getBody()).contains("/oauth2/authorization/github-client-2");
assertThat(entity.getBody())
.contains("/oauth2/authorization/github-client-2");
} }
} }

@ -49,8 +49,8 @@ public class SamplePropertyValidationApplicationTests {
@Test @Test
public void bindValidProperties() { public void bindValidProperties() {
this.context.register(SamplePropertyValidationApplication.class); this.context.register(SamplePropertyValidationApplication.class);
TestPropertyValues.of("sample.host:192.168.0.1", TestPropertyValues.of("sample.host:192.168.0.1", "sample.port:9090")
"sample.port:9090").applyTo(this.context); .applyTo(this.context);
this.context.refresh(); this.context.refresh();
SampleProperties properties = this.context.getBean(SampleProperties.class); SampleProperties properties = this.context.getBean(SampleProperties.class);
assertThat(properties.getHost()).isEqualTo("192.168.0.1"); assertThat(properties.getHost()).isEqualTo("192.168.0.1");
@ -60,8 +60,8 @@ public class SamplePropertyValidationApplicationTests {
@Test @Test
public void bindInvalidHost() { public void bindInvalidHost() {
this.context.register(SamplePropertyValidationApplication.class); this.context.register(SamplePropertyValidationApplication.class);
TestPropertyValues.of("sample.host:xxxxxx", TestPropertyValues.of("sample.host:xxxxxx", "sample.port:9090")
"sample.port:9090").applyTo(this.context); .applyTo(this.context);
this.thrown.expect(BeanCreationException.class); this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("Failed to bind properties under 'sample'"); this.thrown.expectMessage("Failed to bind properties under 'sample'");
this.context.refresh(); this.context.refresh();
@ -79,8 +79,8 @@ public class SamplePropertyValidationApplicationTests {
public void validatorOnlyCalledOnSupportedClass() { public void validatorOnlyCalledOnSupportedClass() {
this.context.register(SamplePropertyValidationApplication.class); this.context.register(SamplePropertyValidationApplication.class);
this.context.register(ServerProperties.class); // our validator will not apply this.context.register(ServerProperties.class); // our validator will not apply
TestPropertyValues.of("sample.host:192.168.0.1", TestPropertyValues.of("sample.host:192.168.0.1", "sample.port:9090")
"sample.port:9090").applyTo(this.context); .applyTo(this.context);
this.context.refresh(); this.context.refresh();
SampleProperties properties = this.context.getBean(SampleProperties.class); SampleProperties properties = this.context.getBean(SampleProperties.class);
assertThat(properties.getHost()).isEqualTo("192.168.0.1"); assertThat(properties.getHost()).isEqualTo("192.168.0.1");

Loading…
Cancel
Save