pull/10168/head
Andy Wilkinson 7 years ago
parent ad4ce9cf57
commit f1c5fc41b4

@ -246,9 +246,8 @@ public class EndpointAutoConfiguration {
} }
Map<String, HealthIndicator> allIndicators = new LinkedHashMap<>( Map<String, HealthIndicator> allIndicators = new LinkedHashMap<>(
healthIndicators); healthIndicators);
reactiveHealthIndicators.forEach((beanName, indicator) -> { reactiveHealthIndicators.forEach((beanName, indicator) -> allIndicators
allIndicators.computeIfAbsent(beanName, n -> adapt(indicator)); .computeIfAbsent(beanName, n -> adapt(indicator)));
});
return allIndicators; return allIndicators;
} }

@ -67,4 +67,3 @@ public class CompositeReactiveHealthIndicatorConfiguration<H extends ReactiveHea
} }
} }

@ -43,8 +43,7 @@ public class ReactiveHealthIndicatorsConfiguration {
@ConditionalOnBean(ReactiveRedisConnectionFactory.class) @ConditionalOnBean(ReactiveRedisConnectionFactory.class)
@ConditionalOnEnabledHealthIndicator("redis") @ConditionalOnEnabledHealthIndicator("redis")
static class RedisHealthIndicatorConfiguration extends static class RedisHealthIndicatorConfiguration extends
CompositeReactiveHealthIndicatorConfiguration<RedisReactiveHealthIndicator, CompositeReactiveHealthIndicatorConfiguration<RedisReactiveHealthIndicator, ReactiveRedisConnectionFactory> {
ReactiveRedisConnectionFactory> {
private final Map<String, ReactiveRedisConnectionFactory> redisConnectionFactories; private final Map<String, ReactiveRedisConnectionFactory> redisConnectionFactories;

@ -47,7 +47,7 @@ public class HealthReactiveWebEndpointExtension {
@ReadOperation @ReadOperation
public Mono<WebEndpointResponse<Health>> health() { public Mono<WebEndpointResponse<Health>> health() {
return this.delegate.health().map(health -> { return this.delegate.health().map((health) -> {
Integer status = this.statusHttpMapper.mapStatus(health.getStatus()); Integer status = this.statusHttpMapper.mapStatus(health.getStatus());
return new WebEndpointResponse<>(health, status); return new WebEndpointResponse<>(health, status);
}); });

@ -47,10 +47,10 @@ public class StatusReactiveWebEndpointExtension {
@ReadOperation @ReadOperation
public Mono<WebEndpointResponse<Health>> health() { public Mono<WebEndpointResponse<Health>> health() {
return this.delegate.health().map(health -> { return this.delegate.health().map((health) -> {
Integer status = this.statusHttpMapper.mapStatus(health.getStatus()); Integer status = this.statusHttpMapper.mapStatus(health.getStatus());
return new WebEndpointResponse<>( return new WebEndpointResponse<>(Health.status(health.getStatus()).build(),
Health.status(health.getStatus()).build(), status); status);
}); });
} }

@ -25,18 +25,17 @@ import reactor.core.publisher.Mono;
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.0.0 * @since 2.0.0
*/ */
public abstract class AbstractReactiveHealthIndicator public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthIndicator {
implements ReactiveHealthIndicator {
@Override @Override
public final Mono<Health> health() { public final Mono<Health> health() {
return doHealthCheck(new Health.Builder()) return doHealthCheck(new Health.Builder())
.onErrorResume(ex -> Mono.just(new Health.Builder().down(ex).build())); .onErrorResume((ex) -> Mono.just(new Health.Builder().down(ex).build()));
} }
/** /**
* Actual health check logic. If an error occurs in the pipeline it will be * Actual health check logic. If an error occurs in the pipeline it will be handled
* handled automatically. * automatically.
* @param builder the {@link Health.Builder} to report health status and details * @param builder the {@link Health.Builder} to report health status and details
* @return a {@link Mono} that provides the {@link Health} * @return a {@link Mono} that provides the {@link Health}
*/ */

@ -47,7 +47,8 @@ public class CompositeHealthIndicatorFactory {
* @return a {@link HealthIndicator} that delegates to the specified * @return a {@link HealthIndicator} that delegates to the specified
* {@code healthIndicators}. * {@code healthIndicators}.
*/ */
public CompositeHealthIndicator createHealthIndicator(HealthAggregator healthAggregator, public CompositeHealthIndicator createHealthIndicator(
HealthAggregator healthAggregator,
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
Assert.notNull(healthAggregator, "HealthAggregator must not be null"); Assert.notNull(healthAggregator, "HealthAggregator must not be null");
Assert.notNull(healthIndicators, "HealthIndicators must not be null"); Assert.notNull(healthIndicators, "HealthIndicators must not be null");

@ -57,9 +57,8 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
Assert.notNull(indicators, "Indicators must not be null"); Assert.notNull(indicators, "Indicators must not be null");
this.indicators = new LinkedHashMap<>(indicators); this.indicators = new LinkedHashMap<>(indicators);
this.healthAggregator = healthAggregator; this.healthAggregator = healthAggregator;
this.timeoutCompose = mono -> this.timeout != null ? this.timeoutCompose = (mono) -> this.timeout != null ? mono.timeout(
mono.timeout(Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) : Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) : mono;
mono;
} }
/** /**
@ -77,9 +76,10 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
/** /**
* Specify an alternative timeout {@link Health} if an {@link HealthIndicator} failed * Specify an alternative timeout {@link Health} if an {@link HealthIndicator} failed
* to reply after specified {@code timeout}. * to reply after specified {@code timeout}.
* @param timeout number of milliseconds to wait before using the {@code timeoutHealth} * @param timeout number of milliseconds to wait before using the
* {@code timeoutHealth}
* @param timeoutHealth the {@link Health} to use if an health indicator reached the * @param timeoutHealth the {@link Health} to use if an health indicator reached the
* {@code} timeout * {@code timeout}
* @return this instance * @return this instance
*/ */
public CompositeReactiveHealthIndicator timeoutStrategy(long timeout, public CompositeReactiveHealthIndicator timeoutStrategy(long timeout,
@ -93,7 +93,7 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
@Override @Override
public Mono<Health> health() { public Mono<Health> health() {
return Flux.fromIterable(this.indicators.entrySet()) return Flux.fromIterable(this.indicators.entrySet())
.flatMap(entry -> Mono.just(entry.getKey()) .flatMap((entry) -> Mono.just(entry.getKey())
.and(entry.getValue().health().compose(this.timeoutCompose))) .and(entry.getValue().health().compose(this.timeoutCompose)))
.collectMap(Tuple2::getT1, Tuple2::getT2) .collectMap(Tuple2::getT1, Tuple2::getT2)
.map(this.healthAggregator::aggregate); .map(this.healthAggregator::aggregate);

@ -60,10 +60,12 @@ public class CompositeReactiveHealthIndicatorFactory {
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators, Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
Assert.notNull(healthAggregator, "HealthAggregator must not be null"); Assert.notNull(healthAggregator, "HealthAggregator must not be null");
Assert.notNull(reactiveHealthIndicators, "ReactiveHealthIndicators must not be null"); Assert.notNull(reactiveHealthIndicators,
"ReactiveHealthIndicators must not be null");
CompositeReactiveHealthIndicator healthIndicator = new CompositeReactiveHealthIndicator( CompositeReactiveHealthIndicator healthIndicator = new CompositeReactiveHealthIndicator(
healthAggregator); healthAggregator);
merge(reactiveHealthIndicators, healthIndicators).forEach((beanName, indicator) -> { merge(reactiveHealthIndicators, healthIndicators)
.forEach((beanName, indicator) -> {
String name = this.healthIndicatorNameFactory.apply(beanName); String name = this.healthIndicatorNameFactory.apply(beanName);
healthIndicator.addHealthIndicator(name, indicator); healthIndicator.addHealthIndicator(name, indicator);
}); });
@ -80,8 +82,8 @@ public class CompositeReactiveHealthIndicatorFactory {
reactiveHealthIndicators); reactiveHealthIndicators);
healthIndicators.forEach((beanName, indicator) -> { healthIndicators.forEach((beanName, indicator) -> {
String name = this.healthIndicatorNameFactory.apply(beanName); String name = this.healthIndicatorNameFactory.apply(beanName);
allIndicators.computeIfAbsent(name, n -> allIndicators.computeIfAbsent(name,
new HealthIndicatorReactiveAdapter(indicator)); (n) -> new HealthIndicatorReactiveAdapter(indicator));
}); });
return allIndicators; return allIndicators;
} }

@ -23,8 +23,8 @@ import reactor.core.scheduler.Schedulers;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Adapts a {@link HealthIndicator} to a {@link ReactiveHealthIndicator} so that it can * Adapts a {@link HealthIndicator} to a {@link ReactiveHealthIndicator} so that it can be
* be safely invoked in a reactive environment. * safely invoked in a reactive environment.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.0.0 * @since 2.0.0
@ -40,8 +40,7 @@ public class HealthIndicatorReactiveAdapter implements ReactiveHealthIndicator {
@Override @Override
public Mono<Health> health() { public Mono<Health> health() {
return Mono.create((sink) -> return Mono.create((sink) -> Schedulers.elastic().schedule(() -> invoke(sink)));
Schedulers.elastic().schedule(() -> invoke(sink)));
} }
private void invoke(MonoSink<Health> sink) { private void invoke(MonoSink<Health> sink) {

@ -42,11 +42,11 @@ public class RedisReactiveHealthIndicator extends AbstractReactiveHealthIndicato
ReactiveRedisConnection connection = this.connectionFactory ReactiveRedisConnection connection = this.connectionFactory
.getReactiveConnection(); .getReactiveConnection();
return connection.serverCommands().info() return connection.serverCommands().info()
.map(info -> builder.up() .map((info) -> builder.up()
.withDetail(RedisHealthIndicator.VERSION, .withDetail(RedisHealthIndicator.VERSION,
info.getProperty(RedisHealthIndicator.REDIS_VERSION)) info.getProperty(RedisHealthIndicator.REDIS_VERSION))
.build()) .build())
.doFinally(signal -> connection.close()); .doFinally((signal) -> connection.close());
} }
} }

@ -47,8 +47,9 @@ public class EndpointAutoConfigurationTests {
@Test @Test
public void healthEndpointAdaptReactiveHealthIndicator() { public void healthEndpointAdaptReactiveHealthIndicator() {
this.contextRunner.withUserConfiguration( this.contextRunner
ReactiveHealthIndicatorConfiguration.class).run((context) -> { .withUserConfiguration(ReactiveHealthIndicatorConfiguration.class)
.run((context) -> {
ReactiveHealthIndicator reactiveHealthIndicator = context.getBean( ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
"reactiveHealthIndicator", ReactiveHealthIndicator.class); "reactiveHealthIndicator", ReactiveHealthIndicator.class);
verify(reactiveHealthIndicator, times(0)).health(); verify(reactiveHealthIndicator, times(0)).health();
@ -63,21 +64,21 @@ public class EndpointAutoConfigurationTests {
public void healthEndpointMergeRegularAndReactive() { public void healthEndpointMergeRegularAndReactive() {
this.contextRunner.withUserConfiguration(HealthIndicatorConfiguration.class, this.contextRunner.withUserConfiguration(HealthIndicatorConfiguration.class,
ReactiveHealthIndicatorConfiguration.class).run((context) -> { ReactiveHealthIndicatorConfiguration.class).run((context) -> {
HealthIndicator simpleHealthIndicator = context.getBean( HealthIndicator simpleHealthIndicator = context
"simpleHealthIndicator", HealthIndicator.class); .getBean("simpleHealthIndicator", HealthIndicator.class);
ReactiveHealthIndicator reactiveHealthIndicator = context.getBean( ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
"reactiveHealthIndicator", ReactiveHealthIndicator.class); "reactiveHealthIndicator", ReactiveHealthIndicator.class);
verify(simpleHealthIndicator, times(0)).health(); verify(simpleHealthIndicator, times(0)).health();
verify(reactiveHealthIndicator, times(0)).health(); verify(reactiveHealthIndicator, times(0)).health();
Health health = context.getBean(HealthEndpoint.class).health(); Health health = context.getBean(HealthEndpoint.class).health();
assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).containsOnlyKeys("simple", "reactive"); assertThat(health.getDetails()).containsOnlyKeys("simple",
"reactive");
verify(simpleHealthIndicator, times(1)).health(); verify(simpleHealthIndicator, times(1)).health();
verify(reactiveHealthIndicator, times(1)).health(); verify(reactiveHealthIndicator, times(1)).health();
}); });
} }
@Configuration @Configuration
static class HealthIndicatorConfiguration { static class HealthIndicatorConfiguration {

@ -43,17 +43,16 @@ public class ReactiveHealthIndicatorsConfigurationTests {
@Test @Test
public void redisHealthIndicator() { public void redisHealthIndicator() {
this.contextRunner this.contextRunner
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
RedisAutoConfiguration.class))
.withPropertyValues("management.health.diskspace.enabled:false") .withPropertyValues("management.health.diskspace.enabled:false")
.run(hasSingleReactiveHealthIndicator(RedisReactiveHealthIndicator.class)); .run(hasSingleReactiveHealthIndicator(
RedisReactiveHealthIndicator.class));
} }
private ContextConsumer<AssertableApplicationContext> hasSingleReactiveHealthIndicator( private ContextConsumer<AssertableApplicationContext> hasSingleReactiveHealthIndicator(
Class<? extends ReactiveHealthIndicator> type) { Class<? extends ReactiveHealthIndicator> type) {
return (context) -> assertThat(context).getBeans(ReactiveHealthIndicator.class) return (context) -> assertThat(context).getBeans(ReactiveHealthIndicator.class)
.hasSize(1) .hasSize(1).hasValueSatisfying(
.hasValueSatisfying(
new Condition<>((indicator) -> indicator.getClass().equals(type), new Condition<>((indicator) -> indicator.getClass().equals(type),
"Wrong indicator type")); "Wrong indicator type"));
} }

@ -44,7 +44,6 @@ public class LiquibaseEndpointTests {
LiquibaseAutoConfiguration.class)) LiquibaseAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true"); .withPropertyValues("spring.datasource.generate-unique-name=true");
@Test @Test
public void liquibaseReportIsReturned() throws Exception { public void liquibaseReportIsReturned() throws Exception {
this.contextRunner.withUserConfiguration(Config.class) this.contextRunner.withUserConfiguration(Config.class)

@ -69,7 +69,8 @@ public class HealthEndpointWebIntegrationTests {
@Bean @Bean
public HealthEndpoint healthEndpoint( public HealthEndpoint healthEndpoint(
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
return new HealthEndpoint(new CompositeHealthIndicatorFactory().createHealthIndicator( return new HealthEndpoint(
new CompositeHealthIndicatorFactory().createHealthIndicator(
new OrderedHealthAggregator(), healthIndicators)); new OrderedHealthAggregator(), healthIndicators));
} }

@ -67,7 +67,8 @@ public class StatusEndpointWebIntegrationTests {
@Bean @Bean
public StatusEndpoint statusEndpoint( public StatusEndpoint statusEndpoint(
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
return new StatusEndpoint(new CompositeHealthIndicatorFactory().createHealthIndicator( return new StatusEndpoint(
new CompositeHealthIndicatorFactory().createHealthIndicator(
new OrderedHealthAggregator(), healthIndicators)); new OrderedHealthAggregator(), healthIndicators));
} }

@ -44,7 +44,7 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
public void noHealthIndicator() { public void noHealthIndicator() {
ReactiveHealthIndicator healthIndicator = createHealthIndicator( ReactiveHealthIndicator healthIndicator = createHealthIndicator(
Collections.singletonMap("test", () -> Mono.just(UP)), null); Collections.singletonMap("test", () -> Mono.just(UP)), null);
StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> { StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("test"); assertThat(h.getDetails()).containsOnlyKeys("test");
}).verifyComplete(); }).verifyComplete();
@ -53,10 +53,9 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
@Test @Test
public void defaultHealthIndicatorNameFactory() { public void defaultHealthIndicatorNameFactory() {
ReactiveHealthIndicator healthIndicator = new CompositeReactiveHealthIndicatorFactory() ReactiveHealthIndicator healthIndicator = new CompositeReactiveHealthIndicatorFactory()
.createReactiveHealthIndicator(new OrderedHealthAggregator(), .createReactiveHealthIndicator(new OrderedHealthAggregator(), Collections
Collections.singletonMap("myHealthIndicator", () -> Mono.just(UP)), .singletonMap("myHealthIndicator", () -> Mono.just(UP)), null);
null); StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("my"); assertThat(h.getDetails()).containsOnlyKeys("my");
}).verifyComplete(); }).verifyComplete();
@ -67,7 +66,7 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
ReactiveHealthIndicator healthIndicator = createHealthIndicator( ReactiveHealthIndicator healthIndicator = createHealthIndicator(
Collections.singletonMap("test", () -> Mono.just(UP)), Collections.singletonMap("test", () -> Mono.just(UP)),
Collections.singletonMap("regular", () -> DOWN)); Collections.singletonMap("regular", () -> DOWN));
StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> { StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.DOWN); assertThat(h.getStatus()).isEqualTo(Status.DOWN);
assertThat(h.getDetails()).containsOnlyKeys("test", "regular"); assertThat(h.getDetails()).containsOnlyKeys("test", "regular");
}).verifyComplete(); }).verifyComplete();
@ -75,14 +74,15 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
@Test @Test
public void reactiveHealthIndicatorTakesPrecedence() { public void reactiveHealthIndicatorTakesPrecedence() {
ReactiveHealthIndicator reactivehealthIndicator = mock(ReactiveHealthIndicator.class); ReactiveHealthIndicator reactivehealthIndicator = mock(
ReactiveHealthIndicator.class);
given(reactivehealthIndicator.health()).willReturn(Mono.just(UP)); given(reactivehealthIndicator.health()).willReturn(Mono.just(UP));
HealthIndicator regularHealthIndicator = mock(HealthIndicator.class); HealthIndicator regularHealthIndicator = mock(HealthIndicator.class);
given(regularHealthIndicator.health()).willReturn(UP); given(regularHealthIndicator.health()).willReturn(UP);
ReactiveHealthIndicator healthIndicator = createHealthIndicator( ReactiveHealthIndicator healthIndicator = createHealthIndicator(
Collections.singletonMap("test", reactivehealthIndicator), Collections.singletonMap("test", reactivehealthIndicator),
Collections.singletonMap("test", regularHealthIndicator)); Collections.singletonMap("test", regularHealthIndicator));
StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> { StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("test"); assertThat(h.getDetails()).containsOnlyKeys("test");
}).verifyComplete(); }).verifyComplete();
@ -93,7 +93,7 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
private ReactiveHealthIndicator createHealthIndicator( private ReactiveHealthIndicator createHealthIndicator(
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators, Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
return new CompositeReactiveHealthIndicatorFactory(n -> n) return new CompositeReactiveHealthIndicatorFactory((n) -> n)
.createReactiveHealthIndicator(new OrderedHealthAggregator(), .createReactiveHealthIndicator(new OrderedHealthAggregator(),
reactiveHealthIndicators, healthIndicators); reactiveHealthIndicators, healthIndicators);
} }

@ -38,13 +38,13 @@ public class CompositeReactiveHealthIndicatorTests {
private OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator(); private OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator();
private CompositeReactiveHealthIndicator indicator = private CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
new CompositeReactiveHealthIndicator(this.healthAggregator); this.healthAggregator);
@Test @Test
public void singleIndicator() { public void singleIndicator() {
this.indicator.addHealthIndicator("test", () -> Mono.just(HEALTHY)); this.indicator.addHealthIndicator("test", () -> Mono.just(HEALTHY));
StepVerifier.create(this.indicator.health()).consumeNextWith(h -> { StepVerifier.create(this.indicator.health()).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("test"); assertThat(h.getDetails()).containsOnlyKeys("test");
assertThat(h.getDetails().get("test")).isEqualTo(HEALTHY); assertThat(h.getDetails().get("test")).isEqualTo(HEALTHY);
@ -54,17 +54,14 @@ public class CompositeReactiveHealthIndicatorTests {
@Test @Test
public void longHealth() { public void longHealth() {
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
this.indicator.addHealthIndicator( this.indicator.addHealthIndicator("test" + i,
"test" + i, new TimeoutHealth(10000, Status.UP)); new TimeoutHealth(10000, Status.UP));
} }
StepVerifier.withVirtualTime(this.indicator::health) StepVerifier.withVirtualTime(this.indicator::health).expectSubscription()
.expectSubscription() .thenAwait(Duration.ofMillis(10000)).consumeNextWith((h) -> {
.thenAwait(Duration.ofMillis(10000))
.consumeNextWith(h -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).hasSize(50); assertThat(h.getDetails()).hasSize(50);
}) }).verifyComplete();
.verifyComplete();
} }
@ -73,7 +70,7 @@ public class CompositeReactiveHealthIndicatorTests {
this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP)) this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP))
.addHealthIndicator("fast", new TimeoutHealth(10, Status.UP)) .addHealthIndicator("fast", new TimeoutHealth(10, Status.UP))
.timeoutStrategy(100, UNKNOWN_HEALTH); .timeoutStrategy(100, UNKNOWN_HEALTH);
StepVerifier.create(this.indicator.health()).consumeNextWith(h -> { StepVerifier.create(this.indicator.health()).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("slow", "fast"); assertThat(h.getDetails()).containsOnlyKeys("slow", "fast");
assertThat(h.getDetails().get("slow")).isEqualTo(UNKNOWN_HEALTH); assertThat(h.getDetails().get("slow")).isEqualTo(UNKNOWN_HEALTH);
@ -86,16 +83,13 @@ public class CompositeReactiveHealthIndicatorTests {
this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP)) this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP))
.addHealthIndicator("fast", new TimeoutHealth(10, Status.UP)) .addHealthIndicator("fast", new TimeoutHealth(10, Status.UP))
.timeoutStrategy(20000, null); .timeoutStrategy(20000, null);
StepVerifier.withVirtualTime(this.indicator::health) StepVerifier.withVirtualTime(this.indicator::health).expectSubscription()
.expectSubscription() .thenAwait(Duration.ofMillis(10000)).consumeNextWith((h) -> {
.thenAwait(Duration.ofMillis(10000))
.consumeNextWith(h -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("slow", "fast"); assertThat(h.getDetails()).containsOnlyKeys("slow", "fast");
assertThat(h.getDetails().get("slow")).isEqualTo(HEALTHY); assertThat(h.getDetails().get("slow")).isEqualTo(HEALTHY);
assertThat(h.getDetails().get("fast")).isEqualTo(HEALTHY); assertThat(h.getDetails().get("fast")).isEqualTo(HEALTHY);
}) }).verifyComplete();
.verifyComplete();
} }
static class TimeoutHealth implements ReactiveHealthIndicator { static class TimeoutHealth implements ReactiveHealthIndicator {
@ -112,7 +106,7 @@ public class CompositeReactiveHealthIndicatorTests {
@Override @Override
public Mono<Health> health() { public Mono<Health> health() {
return Mono.delay(Duration.ofMillis(this.timeout)) return Mono.delay(Duration.ofMillis(this.timeout))
.map(l -> Health.status(this.status).build()); .map((l) -> Health.status(this.status).build());
} }
} }

@ -32,7 +32,8 @@ public class HealthIndicatorReactiveAdapterTests {
@Test @Test
public void delegateReturnsHealth() { public void delegateReturnsHealth() {
HealthIndicator delegate = mock(HealthIndicator.class); HealthIndicator delegate = mock(HealthIndicator.class);
HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate); HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(
delegate);
Health status = Health.up().build(); Health status = Health.up().build();
given(delegate.health()).willReturn(status); given(delegate.health()).willReturn(status);
StepVerifier.create(adapter.health()).expectNext(status).verifyComplete(); StepVerifier.create(adapter.health()).expectNext(status).verifyComplete();
@ -41,7 +42,8 @@ public class HealthIndicatorReactiveAdapterTests {
@Test @Test
public void delegateThrowError() { public void delegateThrowError() {
HealthIndicator delegate = mock(HealthIndicator.class); HealthIndicator delegate = mock(HealthIndicator.class);
HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate); HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(
delegate);
given(delegate.health()).willThrow(new IllegalStateException("Expected")); given(delegate.health()).willThrow(new IllegalStateException("Expected"));
StepVerifier.create(adapter.health()).expectError(IllegalStateException.class); StepVerifier.create(adapter.health()).expectError(IllegalStateException.class);
} }
@ -49,9 +51,12 @@ public class HealthIndicatorReactiveAdapterTests {
@Test @Test
public void delegateRunsOnTheElasticScheduler() { public void delegateRunsOnTheElasticScheduler() {
String currentThread = Thread.currentThread().getName(); String currentThread = Thread.currentThread().getName();
HealthIndicator delegate = () -> Health.status(Thread.currentThread().getName() HealthIndicator delegate = () -> Health
.equals(currentThread) ? Status.DOWN : Status.UP).build(); .status(Thread.currentThread().getName().equals(currentThread)
HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate); ? Status.DOWN : Status.UP)
.build();
HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(
delegate);
StepVerifier.create(adapter.health()).expectNext(Health.status(Status.UP).build()) StepVerifier.create(adapter.health()).expectNext(Health.status(Status.UP).build())
.verifyComplete(); .verifyComplete();
} }

@ -47,9 +47,10 @@ public class RedisReactiveHealthIndicatorTests {
ReactiveRedisConnection redisConnection = mock(ReactiveRedisConnection.class); ReactiveRedisConnection redisConnection = mock(ReactiveRedisConnection.class);
ReactiveServerCommands commands = mock(ReactiveServerCommands.class); ReactiveServerCommands commands = mock(ReactiveServerCommands.class);
given(commands.info()).willReturn(Mono.just(info)); given(commands.info()).willReturn(Mono.just(info));
RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(redisConnection, commands); RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(
redisConnection, commands);
Mono<Health> health = healthIndicator.health(); Mono<Health> health = healthIndicator.health();
StepVerifier.create(health).consumeNextWith(h -> { StepVerifier.create(health).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.UP); assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("version"); assertThat(h.getDetails()).containsOnlyKeys("version");
assertThat(h.getDetails().get("version")).isEqualTo("2.8.9"); assertThat(h.getDetails().get("version")).isEqualTo("2.8.9");
@ -60,19 +61,21 @@ public class RedisReactiveHealthIndicatorTests {
@Test @Test
public void redisIsDown() throws Exception { public void redisIsDown() throws Exception {
ReactiveServerCommands commands = mock(ReactiveServerCommands.class); ReactiveServerCommands commands = mock(ReactiveServerCommands.class);
given(commands.info()).willReturn(Mono.error( given(commands.info()).willReturn(
new RedisConnectionFailureException("Connection failed"))); Mono.error(new RedisConnectionFailureException("Connection failed")));
ReactiveRedisConnection redisConnection = mock(ReactiveRedisConnection.class); ReactiveRedisConnection redisConnection = mock(ReactiveRedisConnection.class);
RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(redisConnection, commands); RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(
redisConnection, commands);
Mono<Health> health = healthIndicator.health(); Mono<Health> health = healthIndicator.health();
StepVerifier.create(health).consumeNextWith(h -> { StepVerifier.create(health)
assertThat(h.getStatus()).isEqualTo(Status.DOWN); .consumeNextWith((h) -> assertThat(h.getStatus()).isEqualTo(Status.DOWN))
}).verifyComplete(); .verifyComplete();
verify(redisConnection).close(); verify(redisConnection).close();
} }
private RedisReactiveHealthIndicator createHealthIndicator( private RedisReactiveHealthIndicator createHealthIndicator(
ReactiveRedisConnection redisConnection, ReactiveServerCommands serverCommands) { ReactiveRedisConnection redisConnection,
ReactiveServerCommands serverCommands) {
ReactiveRedisConnectionFactory redisConnectionFactory = mock( ReactiveRedisConnectionFactory redisConnectionFactory = mock(
ReactiveRedisConnectionFactory.class); ReactiveRedisConnectionFactory.class);

@ -76,16 +76,16 @@ public class ConfigurationPropertiesBinder {
* @throws ConfigurationPropertiesBindingException if the binding failed * @throws ConfigurationPropertiesBindingException if the binding failed
*/ */
public void bind(Object target) { public void bind(Object target) {
ConfigurationProperties annotation = AnnotationUtils.findAnnotation( ConfigurationProperties annotation = AnnotationUtils
target.getClass(), ConfigurationProperties.class); .findAnnotation(target.getClass(), ConfigurationProperties.class);
if (annotation != null) { if (annotation != null) {
bind(target, annotation); bind(target, annotation);
} }
} }
/** /**
* Bind the specified {@code target} object using the configuration defined by * Bind the specified {@code target} object using the configuration defined by the
* the specified {@code annotation}. * specified {@code annotation}.
* @param target the target to bind the configuration property sources to * @param target the target to bind the configuration property sources to
* @param annotation the binding configuration * @param annotation the binding configuration
* @throws ConfigurationPropertiesBindingException if the binding failed * @throws ConfigurationPropertiesBindingException if the binding failed
@ -154,10 +154,9 @@ public class ConfigurationPropertiesBinder {
return details.toString(); return details.toString();
} }
/** /**
* {@link Validator} extension to be implemented to signal that that validator can * {@link Validator} extension to be implemented to signal that that validator can be
* be destroyed once the binder is no longer in use. * destroyed once the binder is no longer in use.
*/ */
interface InternalValidator extends Validator { interface InternalValidator extends Validator {

@ -33,8 +33,8 @@ import org.springframework.util.ClassUtils;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
/** /**
* Builder for creating {@link ConfigurationPropertiesBinder} based on the state of * Builder for creating {@link ConfigurationPropertiesBinder} based on the state of the
* the {@link ApplicationContext}. * {@link ApplicationContext}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.0.0 * @since 2.0.0
@ -46,7 +46,10 @@ public class ConfigurationPropertiesBinderBuilder {
*/ */
public static final String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator"; public static final String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";
private static final String CONVERSION_SERVICE_BEAN_NAME = ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME; /**
* The bean name of the configuration properties conversion service.
*/
public static final String CONVERSION_SERVICE_BEAN_NAME = ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME;
private static final String[] VALIDATOR_CLASSES = { "javax.validation.Validator", private static final String[] VALIDATOR_CLASSES = { "javax.validation.Validator",
"javax.validation.ValidatorFactory" }; "javax.validation.ValidatorFactory" };
@ -87,7 +90,7 @@ public class ConfigurationPropertiesBinderBuilder {
/** /**
* Specify the {@link Validator} to use or {@code null} to use the default. * Specify the {@link Validator} to use or {@code null} to use the default.
* <p> * <p>
* By default, use a {@link Validator} bean named {@value VALIDATOR_BEAN_NAME} if * By default, use a {@link Validator} bean named {@value #VALIDATOR_BEAN_NAME} if
* any. If not, create a JSR 303 Validator if the necessary libraries are available. * any. If not, create a JSR 303 Validator if the necessary libraries are available.
* No validation occurs otherwise. * No validation occurs otherwise.
* @param validator the validator to use or {@code null} * @param validator the validator to use or {@code null}
@ -111,8 +114,8 @@ public class ConfigurationPropertiesBinderBuilder {
} }
/** /**
* Specify the {@link ConfigurableEnvironment Environment} to use, use all * Specify the {@link ConfigurableEnvironment Environment} to use, use all available
* available {@link PropertySource}. * {@link PropertySource}.
* @param environment the environment to use * @param environment the environment to use
* @return this instance * @return this instance
* @see #withPropertySources(Iterable) * @see #withPropertySources(Iterable)
@ -136,7 +139,8 @@ public class ConfigurationPropertiesBinderBuilder {
if (this.validator != null) { if (this.validator != null) {
return this.validator; return this.validator;
} }
Validator defaultValidator = getOptionalBean(VALIDATOR_BEAN_NAME, Validator.class); Validator defaultValidator = getOptionalBean(VALIDATOR_BEAN_NAME,
Validator.class);
if (defaultValidator != null) { if (defaultValidator != null) {
return defaultValidator; return defaultValidator;
} }
@ -160,7 +164,8 @@ public class ConfigurationPropertiesBinderBuilder {
private ConversionService createDefaultConversionService() { private ConversionService createDefaultConversionService() {
ConversionServiceFactory conversionServiceFactory = this.applicationContext ConversionServiceFactory conversionServiceFactory = this.applicationContext
.getAutowireCapableBeanFactory().createBean(ConversionServiceFactory.class); .getAutowireCapableBeanFactory()
.createBean(ConversionServiceFactory.class);
return conversionServiceFactory.createConversionService(); return conversionServiceFactory.createConversionService();
} }

@ -20,8 +20,8 @@ import org.springframework.core.NestedExceptionUtils;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
/** /**
* Exception thrown when a {@code @ConfigurationProperties} annotated object failed * Exception thrown when a {@code @ConfigurationProperties} annotated object failed to be
* to be bound. * bound.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.0.0 * @since 2.0.0
@ -30,8 +30,8 @@ public class ConfigurationPropertiesBindingException extends RuntimeException {
private final Class<?> targetClass; private final Class<?> targetClass;
public ConfigurationPropertiesBindingException(Class<?> targetClass, public ConfigurationPropertiesBindingException(Class<?> targetClass, String message,
String message, Throwable cause) { Throwable cause) {
super("Could not bind properties to '" + ClassUtils.getShortName(targetClass) super("Could not bind properties to '" + ClassUtils.getShortName(targetClass)
+ "': " + message, cause); + "': " + message, cause);
this.targetClass = targetClass; this.targetClass = targetClass;

@ -233,8 +233,8 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
private ConfigurationPropertiesBinder getBinder() { private ConfigurationPropertiesBinder getBinder() {
if (this.configurationPropertiesBinder == null) { if (this.configurationPropertiesBinder == null) {
this.configurationPropertiesBinder = new ConfigurationPropertiesBinderBuilder(this.applicationContext) this.configurationPropertiesBinder = new ConfigurationPropertiesBinderBuilder(
.withConversionService(this.conversionService) this.applicationContext).withConversionService(this.conversionService)
.withValidator(this.validator) .withValidator(this.validator)
.withPropertySources(this.propertySources).build(); .withPropertySources(this.propertySources).build();
} }

@ -51,8 +51,8 @@ class ValidatedLocalValidatorFactoryBean extends LocalValidatorFactoryBean
if (AnnotatedElementUtils.hasAnnotation(type, Validated.class)) { if (AnnotatedElementUtils.hasAnnotation(type, Validated.class)) {
return true; return true;
} }
if (type.getPackage() != null && type.getPackage().getName() if (type.getPackage() != null
.startsWith("org.springframework.boot")) { && type.getPackage().getName().startsWith("org.springframework.boot")) {
return false; return false;
} }
if (getConstraintsForClass(type).isBeanConstrained()) { if (getConstraintsForClass(type).isBeanConstrained()) {

@ -276,9 +276,8 @@ public class WebEndpointReactiveHandlerMapping extends RequestMappingInfoHandler
@Override @Override
public Object invoke(Map<String, Object> arguments) { public Object invoke(Map<String, Object> arguments) {
return Mono.create((sink) -> { return Mono.create((sink) -> Schedulers.elastic()
Schedulers.elastic().schedule(() -> invoke(arguments, sink)); .schedule(() -> invoke(arguments, sink)));
});
} }
private void invoke(Map<String, Object> arguments, MonoSink<Object> sink) { private void invoke(Map<String, Object> arguments, MonoSink<Object> sink) {

@ -51,8 +51,8 @@ public class ConfigurationPropertiesBinderBuilderTests {
private final StaticApplicationContext applicationContext = new StaticApplicationContext(); private final StaticApplicationContext applicationContext = new StaticApplicationContext();
private final ConfigurationPropertiesBinderBuilder builder = private final ConfigurationPropertiesBinderBuilder builder = new ConfigurationPropertiesBinderBuilder(
new ConfigurationPropertiesBinderBuilder(this.applicationContext); this.applicationContext);
private final MockEnvironment environment = new MockEnvironment(); private final MockEnvironment environment = new MockEnvironment();
@ -78,8 +78,8 @@ public class ConfigurationPropertiesBinderBuilderTests {
DefaultConversionService.class); DefaultConversionService.class);
ConfigurationPropertiesBinder binder = this.builder ConfigurationPropertiesBinder binder = this.builder
.withEnvironment(this.environment).build(); .withEnvironment(this.environment).build();
assertThat(ReflectionTestUtils.getField(binder, "conversionService")).isSameAs( assertThat(ReflectionTestUtils.getField(binder, "conversionService"))
this.applicationContext.getBean("conversionService")); .isSameAs(this.applicationContext.getBean("conversionService"));
} }
@Test @Test
@ -97,8 +97,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
public void useCustomValidator() { public void useCustomValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
ConfigurationPropertiesBinder binder = this.builder ConfigurationPropertiesBinder binder = this.builder
.withEnvironment(this.environment) .withEnvironment(this.environment).withValidator(validator).build();
.withValidator(validator).build();
assertThat(ReflectionTestUtils.getField(binder, "validator")).isSameAs(validator); assertThat(ReflectionTestUtils.getField(binder, "validator")).isSameAs(validator);
} }
@ -124,8 +123,9 @@ public class ConfigurationPropertiesBinderBuilderTests {
public void validationWithJsr303() { public void validationWithJsr303() {
ConfigurationPropertiesBinder binder = this.builder ConfigurationPropertiesBinder binder = this.builder
.withEnvironment(this.environment).build(); .withEnvironment(this.environment).build();
assertThat(bindWithValidationErrors(binder, new PropertyWithJSR303()) assertThat(
.getAllErrors()).hasSize(2); bindWithValidationErrors(binder, new PropertyWithJSR303()).getAllErrors())
.hasSize(2);
} }
@Test @Test

@ -114,7 +114,8 @@ public class ConfigurationPropertiesBinderTests {
} }
private void bindToEnum(String property) { private void bindToEnum(String property) {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, property); TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
property);
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder( ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
this.environment.getPropertySources(), null, null); this.environment.getPropertySources(), null, null);
PropertyWithEnum target = new PropertyWithEnum(); PropertyWithEnum target = new PropertyWithEnum();
@ -129,7 +130,8 @@ public class ConfigurationPropertiesBinderTests {
} }
private void bindToEnumSet(String property, FooEnum... expected) { private void bindToEnumSet(String property, FooEnum... expected) {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, property); TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
property);
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder( ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
this.environment.getPropertySources(), null, null); this.environment.getPropertySources(), null, null);
PropertyWithEnum target = new PropertyWithEnum(); PropertyWithEnum target = new PropertyWithEnum();
@ -237,11 +239,9 @@ public class ConfigurationPropertiesBinderTests {
public void validationWithCustomValidator() { public void validationWithCustomValidator() {
CustomPropertyValidator validator = spy(new CustomPropertyValidator()); CustomPropertyValidator validator = spy(new CustomPropertyValidator());
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder( ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
this.environment.getPropertySources(), null, this.environment.getPropertySources(), null, validator);
validator);
PropertyWithCustomValidator target = new PropertyWithCustomValidator(); PropertyWithCustomValidator target = new PropertyWithCustomValidator();
assertThat(bindWithValidationErrors(binder, target) assertThat(bindWithValidationErrors(binder, target).getAllErrors()).hasSize(1);
.getAllErrors()).hasSize(1);
verify(validator).validate(eq(target), any(Errors.class)); verify(validator).validate(eq(target), any(Errors.class));
} }
@ -251,8 +251,7 @@ public class ConfigurationPropertiesBinderTests {
"test.foo=bar"); "test.foo=bar");
CustomPropertyValidator validator = spy(new CustomPropertyValidator()); CustomPropertyValidator validator = spy(new CustomPropertyValidator());
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder( ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
this.environment.getPropertySources(), null, this.environment.getPropertySources(), null, validator);
validator);
PropertyWithValidatingSetter target = new PropertyWithValidatingSetter(); PropertyWithValidatingSetter target = new PropertyWithValidatingSetter();
binder.bind(target); binder.bind(target);
assertThat(target.getFoo()).isEqualTo("bar"); assertThat(target.getFoo()).isEqualTo("bar");
@ -431,7 +430,6 @@ public class ConfigurationPropertiesBinderTests {
} }
@ConfigurationProperties(prefix = "test") @ConfigurationProperties(prefix = "test")
public static class PropertyWithValidatingSetter { public static class PropertyWithValidatingSetter {

@ -249,7 +249,8 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
@Test @Test
public void genericConverterIsFound() { public void genericConverterIsFound() {
prepareConverterContext(GenericConverterConfiguration.class, PersonProperty.class); prepareConverterContext(GenericConverterConfiguration.class,
PersonProperty.class);
this.context.refresh(); this.context.refresh();
Person person = this.context.getBean(PersonProperty.class).getPerson(); Person person = this.context.getBean(PersonProperty.class).getPerson();
assertThat(person.firstName).isEqualTo("John"); assertThat(person.firstName).isEqualTo("John");
@ -356,7 +357,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
} }
@Configuration @Configuration
@EnableConfigurationProperties @EnableConfigurationProperties
@ConfigurationProperties(prefix = "test") @ConfigurationProperties(prefix = "test")
@ -381,7 +381,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
} }
@Configuration @Configuration
@EnableConfigurationProperties @EnableConfigurationProperties
public static class PrototypePropertiesConfig { public static class PrototypePropertiesConfig {
@ -427,7 +426,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
// Must be a raw type // Must be a raw type
static class FactoryBeanTester implements FactoryBean, InitializingBean { static class FactoryBeanTester implements FactoryBean, InitializingBean {
@ -454,7 +452,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
} }
@Configuration @Configuration
@EnableConfigurationProperties(PropertyWithoutConfigurationPropertiesAnnotation.class) @EnableConfigurationProperties(PropertyWithoutConfigurationPropertiesAnnotation.class)
public static class ConfigurationPropertiesWithoutAnnotation { public static class ConfigurationPropertiesWithoutAnnotation {
@ -553,13 +550,13 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
@Nullable @Nullable
@Override @Override
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { public Object convert(@Nullable Object source, TypeDescriptor sourceType,
TypeDescriptor targetType) {
String[] content = StringUtils.split((String) source, " "); String[] content = StringUtils.split((String) source, " ");
return new Person(content[0], content[1]); return new Person(content[0], content[1]);
} }
} }
@Configuration @Configuration
@EnableConfigurationProperties @EnableConfigurationProperties
@ConfigurationProperties(prefix = "test") @ConfigurationProperties(prefix = "test")

@ -63,8 +63,8 @@ public class AnnotationEndpointDiscovererTests {
@Test @Test
public void endpointIsInParentContextIsDiscovered() { public void endpointIsInParentContextIsDiscovered() {
AnnotationConfigApplicationContext parent = AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
new AnnotationConfigApplicationContext(TestEndpointConfiguration.class); TestEndpointConfiguration.class);
loadWithParent(parent, EmptyConfiguration.class, hasTestEndpoint()); loadWithParent(parent, EmptyConfiguration.class, hasTestEndpoint());
} }

@ -69,8 +69,8 @@ public class JerseyWebEndpointIntegrationTests extends
@Bean @Bean
public ServletRegistrationBean<ServletContainer> servletContainer( public ServletRegistrationBean<ServletContainer> servletContainer(
ResourceConfig resourceConfig) { ResourceConfig resourceConfig) {
return new ServletRegistrationBean<>( return new ServletRegistrationBean<>(new ServletContainer(resourceConfig),
new ServletContainer(resourceConfig), "/*"); "/*");
} }
@Bean @Bean

Loading…
Cancel
Save