Polish
This commit is contained in:
		
							parent
							
								
									ad4ce9cf57
								
							
						
					
					
						commit
						f1c5fc41b4
					
				| 
						 | 
				
			
			@ -246,9 +246,8 @@ public class EndpointAutoConfiguration {
 | 
			
		|||
				}
 | 
			
		||||
				Map<String, HealthIndicator> allIndicators = new LinkedHashMap<>(
 | 
			
		||||
						healthIndicators);
 | 
			
		||||
				reactiveHealthIndicators.forEach((beanName, indicator) -> {
 | 
			
		||||
					allIndicators.computeIfAbsent(beanName, n -> adapt(indicator));
 | 
			
		||||
				});
 | 
			
		||||
				reactiveHealthIndicators.forEach((beanName, indicator) -> allIndicators
 | 
			
		||||
						.computeIfAbsent(beanName, n -> adapt(indicator)));
 | 
			
		||||
				return allIndicators;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,4 +67,3 @@ public class CompositeReactiveHealthIndicatorConfiguration<H extends ReactiveHea
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,8 +43,7 @@ public class ReactiveHealthIndicatorsConfiguration {
 | 
			
		|||
	@ConditionalOnBean(ReactiveRedisConnectionFactory.class)
 | 
			
		||||
	@ConditionalOnEnabledHealthIndicator("redis")
 | 
			
		||||
	static class RedisHealthIndicatorConfiguration extends
 | 
			
		||||
			CompositeReactiveHealthIndicatorConfiguration<RedisReactiveHealthIndicator,
 | 
			
		||||
					ReactiveRedisConnectionFactory> {
 | 
			
		||||
			CompositeReactiveHealthIndicatorConfiguration<RedisReactiveHealthIndicator, ReactiveRedisConnectionFactory> {
 | 
			
		||||
 | 
			
		||||
		private final Map<String, ReactiveRedisConnectionFactory> redisConnectionFactories;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ public class HealthReactiveWebEndpointExtension {
 | 
			
		|||
 | 
			
		||||
	@ReadOperation
 | 
			
		||||
	public Mono<WebEndpointResponse<Health>> health() {
 | 
			
		||||
		return this.delegate.health().map(health -> {
 | 
			
		||||
		return this.delegate.health().map((health) -> {
 | 
			
		||||
			Integer status = this.statusHttpMapper.mapStatus(health.getStatus());
 | 
			
		||||
			return new WebEndpointResponse<>(health, status);
 | 
			
		||||
		});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,10 +47,10 @@ public class StatusReactiveWebEndpointExtension {
 | 
			
		|||
 | 
			
		||||
	@ReadOperation
 | 
			
		||||
	public Mono<WebEndpointResponse<Health>> health() {
 | 
			
		||||
		return this.delegate.health().map(health -> {
 | 
			
		||||
		return this.delegate.health().map((health) -> {
 | 
			
		||||
			Integer status = this.statusHttpMapper.mapStatus(health.getStatus());
 | 
			
		||||
			return new WebEndpointResponse<>(
 | 
			
		||||
					Health.status(health.getStatus()).build(), status);
 | 
			
		||||
			return new WebEndpointResponse<>(Health.status(health.getStatus()).build(),
 | 
			
		||||
					status);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,18 +25,17 @@ import reactor.core.publisher.Mono;
 | 
			
		|||
 * @author Stephane Nicoll
 | 
			
		||||
 * @since 2.0.0
 | 
			
		||||
 */
 | 
			
		||||
public abstract class AbstractReactiveHealthIndicator
 | 
			
		||||
		implements ReactiveHealthIndicator {
 | 
			
		||||
public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthIndicator {
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public final Mono<Health> health() {
 | 
			
		||||
		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
 | 
			
		||||
	 * handled automatically.
 | 
			
		||||
	 * Actual health check logic. If an error occurs in the pipeline it will be handled
 | 
			
		||||
	 * automatically.
 | 
			
		||||
	 * @param builder the {@link Health.Builder} to report health status and details
 | 
			
		||||
	 * @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
 | 
			
		||||
	 * {@code healthIndicators}.
 | 
			
		||||
	 */
 | 
			
		||||
	public CompositeHealthIndicator createHealthIndicator(HealthAggregator healthAggregator,
 | 
			
		||||
	public CompositeHealthIndicator createHealthIndicator(
 | 
			
		||||
			HealthAggregator healthAggregator,
 | 
			
		||||
			Map<String, HealthIndicator> healthIndicators) {
 | 
			
		||||
		Assert.notNull(healthAggregator, "HealthAggregator 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");
 | 
			
		||||
		this.indicators = new LinkedHashMap<>(indicators);
 | 
			
		||||
		this.healthAggregator = healthAggregator;
 | 
			
		||||
		this.timeoutCompose = mono -> this.timeout != null ?
 | 
			
		||||
				mono.timeout(Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) :
 | 
			
		||||
				mono;
 | 
			
		||||
		this.timeoutCompose = (mono) -> this.timeout != null ? mono.timeout(
 | 
			
		||||
				Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) : mono;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -77,9 +76,10 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
 | 
			
		|||
	/**
 | 
			
		||||
	 * Specify an alternative timeout {@link Health} if an {@link HealthIndicator} failed
 | 
			
		||||
	 * 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
 | 
			
		||||
	 * {@code} timeout
 | 
			
		||||
	 * {@code timeout}
 | 
			
		||||
	 * @return this instance
 | 
			
		||||
	 */
 | 
			
		||||
	public CompositeReactiveHealthIndicator timeoutStrategy(long timeout,
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
 | 
			
		|||
	@Override
 | 
			
		||||
	public Mono<Health> health() {
 | 
			
		||||
		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)))
 | 
			
		||||
				.collectMap(Tuple2::getT1, Tuple2::getT2)
 | 
			
		||||
				.map(this.healthAggregator::aggregate);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,13 +60,15 @@ public class CompositeReactiveHealthIndicatorFactory {
 | 
			
		|||
			Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
 | 
			
		||||
			Map<String, HealthIndicator> healthIndicators) {
 | 
			
		||||
		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(
 | 
			
		||||
				healthAggregator);
 | 
			
		||||
		merge(reactiveHealthIndicators, healthIndicators).forEach((beanName, indicator) -> {
 | 
			
		||||
			String name = this.healthIndicatorNameFactory.apply(beanName);
 | 
			
		||||
			healthIndicator.addHealthIndicator(name, indicator);
 | 
			
		||||
		});
 | 
			
		||||
		merge(reactiveHealthIndicators, healthIndicators)
 | 
			
		||||
				.forEach((beanName, indicator) -> {
 | 
			
		||||
					String name = this.healthIndicatorNameFactory.apply(beanName);
 | 
			
		||||
					healthIndicator.addHealthIndicator(name, indicator);
 | 
			
		||||
				});
 | 
			
		||||
		return healthIndicator;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +82,8 @@ public class CompositeReactiveHealthIndicatorFactory {
 | 
			
		|||
				reactiveHealthIndicators);
 | 
			
		||||
		healthIndicators.forEach((beanName, indicator) -> {
 | 
			
		||||
			String name = this.healthIndicatorNameFactory.apply(beanName);
 | 
			
		||||
			allIndicators.computeIfAbsent(name, n ->
 | 
			
		||||
					new HealthIndicatorReactiveAdapter(indicator));
 | 
			
		||||
			allIndicators.computeIfAbsent(name,
 | 
			
		||||
					(n) -> new HealthIndicatorReactiveAdapter(indicator));
 | 
			
		||||
		});
 | 
			
		||||
		return allIndicators;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,8 @@ import reactor.core.scheduler.Schedulers;
 | 
			
		|||
import org.springframework.util.Assert;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Adapts a {@link HealthIndicator} to a {@link ReactiveHealthIndicator} so that it can
 | 
			
		||||
 * be safely invoked in a reactive environment.
 | 
			
		||||
 * Adapts a {@link HealthIndicator} to a {@link ReactiveHealthIndicator} so that it can be
 | 
			
		||||
 * safely invoked in a reactive environment.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 * @since 2.0.0
 | 
			
		||||
| 
						 | 
				
			
			@ -40,8 +40,7 @@ public class HealthIndicatorReactiveAdapter implements ReactiveHealthIndicator {
 | 
			
		|||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Mono<Health> health() {
 | 
			
		||||
		return Mono.create((sink) ->
 | 
			
		||||
				Schedulers.elastic().schedule(() -> invoke(sink)));
 | 
			
		||||
		return Mono.create((sink) -> Schedulers.elastic().schedule(() -> invoke(sink)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void invoke(MonoSink<Health> sink) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,11 +42,11 @@ public class RedisReactiveHealthIndicator extends AbstractReactiveHealthIndicato
 | 
			
		|||
		ReactiveRedisConnection connection = this.connectionFactory
 | 
			
		||||
				.getReactiveConnection();
 | 
			
		||||
		return connection.serverCommands().info()
 | 
			
		||||
				.map(info -> builder.up()
 | 
			
		||||
				.map((info) -> builder.up()
 | 
			
		||||
						.withDetail(RedisHealthIndicator.VERSION,
 | 
			
		||||
								info.getProperty(RedisHealthIndicator.REDIS_VERSION))
 | 
			
		||||
						.build())
 | 
			
		||||
				.doFinally(signal -> connection.close());
 | 
			
		||||
				.doFinally((signal) -> connection.close());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,37 +47,38 @@ public class EndpointAutoConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void healthEndpointAdaptReactiveHealthIndicator() {
 | 
			
		||||
		this.contextRunner.withUserConfiguration(
 | 
			
		||||
				ReactiveHealthIndicatorConfiguration.class).run((context) -> {
 | 
			
		||||
			ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
 | 
			
		||||
					"reactiveHealthIndicator", ReactiveHealthIndicator.class);
 | 
			
		||||
			verify(reactiveHealthIndicator, times(0)).health();
 | 
			
		||||
			Health health = context.getBean(HealthEndpoint.class).health();
 | 
			
		||||
			assertThat(health.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
			assertThat(health.getDetails()).containsOnlyKeys("reactive");
 | 
			
		||||
			verify(reactiveHealthIndicator, times(1)).health();
 | 
			
		||||
		});
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class)
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
 | 
			
		||||
							"reactiveHealthIndicator", ReactiveHealthIndicator.class);
 | 
			
		||||
					verify(reactiveHealthIndicator, times(0)).health();
 | 
			
		||||
					Health health = context.getBean(HealthEndpoint.class).health();
 | 
			
		||||
					assertThat(health.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
					assertThat(health.getDetails()).containsOnlyKeys("reactive");
 | 
			
		||||
					verify(reactiveHealthIndicator, times(1)).health();
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void healthEndpointMergeRegularAndReactive() {
 | 
			
		||||
		this.contextRunner.withUserConfiguration(HealthIndicatorConfiguration.class,
 | 
			
		||||
				ReactiveHealthIndicatorConfiguration.class).run((context) -> {
 | 
			
		||||
			HealthIndicator simpleHealthIndicator = context.getBean(
 | 
			
		||||
					"simpleHealthIndicator", HealthIndicator.class);
 | 
			
		||||
			ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
 | 
			
		||||
					"reactiveHealthIndicator", ReactiveHealthIndicator.class);
 | 
			
		||||
			verify(simpleHealthIndicator, times(0)).health();
 | 
			
		||||
			verify(reactiveHealthIndicator, times(0)).health();
 | 
			
		||||
			Health health = context.getBean(HealthEndpoint.class).health();
 | 
			
		||||
			assertThat(health.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
			assertThat(health.getDetails()).containsOnlyKeys("simple", "reactive");
 | 
			
		||||
			verify(simpleHealthIndicator, times(1)).health();
 | 
			
		||||
			verify(reactiveHealthIndicator, times(1)).health();
 | 
			
		||||
		});
 | 
			
		||||
					HealthIndicator simpleHealthIndicator = context
 | 
			
		||||
							.getBean("simpleHealthIndicator", HealthIndicator.class);
 | 
			
		||||
					ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
 | 
			
		||||
							"reactiveHealthIndicator", ReactiveHealthIndicator.class);
 | 
			
		||||
					verify(simpleHealthIndicator, times(0)).health();
 | 
			
		||||
					verify(reactiveHealthIndicator, times(0)).health();
 | 
			
		||||
					Health health = context.getBean(HealthEndpoint.class).health();
 | 
			
		||||
					assertThat(health.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
					assertThat(health.getDetails()).containsOnlyKeys("simple",
 | 
			
		||||
							"reactive");
 | 
			
		||||
					verify(simpleHealthIndicator, times(1)).health();
 | 
			
		||||
					verify(reactiveHealthIndicator, times(1)).health();
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	static class HealthIndicatorConfiguration {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,17 +43,16 @@ public class ReactiveHealthIndicatorsConfigurationTests {
 | 
			
		|||
	@Test
 | 
			
		||||
	public void redisHealthIndicator() {
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withConfiguration(AutoConfigurations.of(
 | 
			
		||||
						RedisAutoConfiguration.class))
 | 
			
		||||
				.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
 | 
			
		||||
				.withPropertyValues("management.health.diskspace.enabled:false")
 | 
			
		||||
				.run(hasSingleReactiveHealthIndicator(RedisReactiveHealthIndicator.class));
 | 
			
		||||
				.run(hasSingleReactiveHealthIndicator(
 | 
			
		||||
						RedisReactiveHealthIndicator.class));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private ContextConsumer<AssertableApplicationContext> hasSingleReactiveHealthIndicator(
 | 
			
		||||
			Class<? extends ReactiveHealthIndicator> type) {
 | 
			
		||||
		return (context) -> assertThat(context).getBeans(ReactiveHealthIndicator.class)
 | 
			
		||||
				.hasSize(1)
 | 
			
		||||
				.hasValueSatisfying(
 | 
			
		||||
				.hasSize(1).hasValueSatisfying(
 | 
			
		||||
						new Condition<>((indicator) -> indicator.getClass().equals(type),
 | 
			
		||||
								"Wrong indicator type"));
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,6 @@ public class LiquibaseEndpointTests {
 | 
			
		|||
					LiquibaseAutoConfiguration.class))
 | 
			
		||||
			.withPropertyValues("spring.datasource.generate-unique-name=true");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void liquibaseReportIsReturned() throws Exception {
 | 
			
		||||
		this.contextRunner.withUserConfiguration(Config.class)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,8 +69,9 @@ public class HealthEndpointWebIntegrationTests {
 | 
			
		|||
		@Bean
 | 
			
		||||
		public HealthEndpoint healthEndpoint(
 | 
			
		||||
				Map<String, HealthIndicator> healthIndicators) {
 | 
			
		||||
			return new HealthEndpoint(new CompositeHealthIndicatorFactory().createHealthIndicator(
 | 
			
		||||
					new OrderedHealthAggregator(), healthIndicators));
 | 
			
		||||
			return new HealthEndpoint(
 | 
			
		||||
					new CompositeHealthIndicatorFactory().createHealthIndicator(
 | 
			
		||||
							new OrderedHealthAggregator(), healthIndicators));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,8 +67,9 @@ public class StatusEndpointWebIntegrationTests {
 | 
			
		|||
		@Bean
 | 
			
		||||
		public StatusEndpoint statusEndpoint(
 | 
			
		||||
				Map<String, HealthIndicator> healthIndicators) {
 | 
			
		||||
			return new StatusEndpoint(new CompositeHealthIndicatorFactory().createHealthIndicator(
 | 
			
		||||
					new OrderedHealthAggregator(), healthIndicators));
 | 
			
		||||
			return new StatusEndpoint(
 | 
			
		||||
					new CompositeHealthIndicatorFactory().createHealthIndicator(
 | 
			
		||||
							new OrderedHealthAggregator(), healthIndicators));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
 | 
			
		|||
	public void noHealthIndicator() {
 | 
			
		||||
		ReactiveHealthIndicator healthIndicator = createHealthIndicator(
 | 
			
		||||
				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.getDetails()).containsOnlyKeys("test");
 | 
			
		||||
		}).verifyComplete();
 | 
			
		||||
| 
						 | 
				
			
			@ -53,10 +53,9 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
 | 
			
		|||
	@Test
 | 
			
		||||
	public void defaultHealthIndicatorNameFactory() {
 | 
			
		||||
		ReactiveHealthIndicator healthIndicator = new CompositeReactiveHealthIndicatorFactory()
 | 
			
		||||
				.createReactiveHealthIndicator(new OrderedHealthAggregator(),
 | 
			
		||||
						Collections.singletonMap("myHealthIndicator", () -> Mono.just(UP)),
 | 
			
		||||
						null);
 | 
			
		||||
		StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> {
 | 
			
		||||
				.createReactiveHealthIndicator(new OrderedHealthAggregator(), Collections
 | 
			
		||||
						.singletonMap("myHealthIndicator", () -> Mono.just(UP)), null);
 | 
			
		||||
		StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
 | 
			
		||||
			assertThat(h.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
			assertThat(h.getDetails()).containsOnlyKeys("my");
 | 
			
		||||
		}).verifyComplete();
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +66,7 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
 | 
			
		|||
		ReactiveHealthIndicator healthIndicator = createHealthIndicator(
 | 
			
		||||
				Collections.singletonMap("test", () -> Mono.just(UP)),
 | 
			
		||||
				Collections.singletonMap("regular", () -> DOWN));
 | 
			
		||||
		StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> {
 | 
			
		||||
		StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
 | 
			
		||||
			assertThat(h.getStatus()).isEqualTo(Status.DOWN);
 | 
			
		||||
			assertThat(h.getDetails()).containsOnlyKeys("test", "regular");
 | 
			
		||||
		}).verifyComplete();
 | 
			
		||||
| 
						 | 
				
			
			@ -75,14 +74,15 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void reactiveHealthIndicatorTakesPrecedence() {
 | 
			
		||||
		ReactiveHealthIndicator reactivehealthIndicator = mock(ReactiveHealthIndicator.class);
 | 
			
		||||
		ReactiveHealthIndicator reactivehealthIndicator = mock(
 | 
			
		||||
				ReactiveHealthIndicator.class);
 | 
			
		||||
		given(reactivehealthIndicator.health()).willReturn(Mono.just(UP));
 | 
			
		||||
		HealthIndicator regularHealthIndicator = mock(HealthIndicator.class);
 | 
			
		||||
		given(regularHealthIndicator.health()).willReturn(UP);
 | 
			
		||||
		ReactiveHealthIndicator healthIndicator = createHealthIndicator(
 | 
			
		||||
				Collections.singletonMap("test", reactivehealthIndicator),
 | 
			
		||||
				Collections.singletonMap("test", regularHealthIndicator));
 | 
			
		||||
		StepVerifier.create(healthIndicator.health()).consumeNextWith(h -> {
 | 
			
		||||
		StepVerifier.create(healthIndicator.health()).consumeNextWith((h) -> {
 | 
			
		||||
			assertThat(h.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
			assertThat(h.getDetails()).containsOnlyKeys("test");
 | 
			
		||||
		}).verifyComplete();
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ public class CompositeReactiveHealthIndicatorFactoryTests {
 | 
			
		|||
	private ReactiveHealthIndicator createHealthIndicator(
 | 
			
		||||
			Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
 | 
			
		||||
			Map<String, HealthIndicator> healthIndicators) {
 | 
			
		||||
		return new CompositeReactiveHealthIndicatorFactory(n -> n)
 | 
			
		||||
		return new CompositeReactiveHealthIndicatorFactory((n) -> n)
 | 
			
		||||
				.createReactiveHealthIndicator(new OrderedHealthAggregator(),
 | 
			
		||||
						reactiveHealthIndicators, healthIndicators);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,13 +38,13 @@ public class CompositeReactiveHealthIndicatorTests {
 | 
			
		|||
 | 
			
		||||
	private OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator();
 | 
			
		||||
 | 
			
		||||
	private CompositeReactiveHealthIndicator indicator =
 | 
			
		||||
			new CompositeReactiveHealthIndicator(this.healthAggregator);
 | 
			
		||||
	private CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
 | 
			
		||||
			this.healthAggregator);
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void singleIndicator() {
 | 
			
		||||
		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.getDetails()).containsOnlyKeys("test");
 | 
			
		||||
			assertThat(h.getDetails().get("test")).isEqualTo(HEALTHY);
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +54,14 @@ public class CompositeReactiveHealthIndicatorTests {
 | 
			
		|||
	@Test
 | 
			
		||||
	public void longHealth() {
 | 
			
		||||
		for (int i = 0; i < 50; i++) {
 | 
			
		||||
			this.indicator.addHealthIndicator(
 | 
			
		||||
					"test" + i, new TimeoutHealth(10000, Status.UP));
 | 
			
		||||
			this.indicator.addHealthIndicator("test" + i,
 | 
			
		||||
					new TimeoutHealth(10000, Status.UP));
 | 
			
		||||
		}
 | 
			
		||||
		StepVerifier.withVirtualTime(this.indicator::health)
 | 
			
		||||
				.expectSubscription()
 | 
			
		||||
				.thenAwait(Duration.ofMillis(10000))
 | 
			
		||||
				.consumeNextWith(h -> {
 | 
			
		||||
		StepVerifier.withVirtualTime(this.indicator::health).expectSubscription()
 | 
			
		||||
				.thenAwait(Duration.ofMillis(10000)).consumeNextWith((h) -> {
 | 
			
		||||
					assertThat(h.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
					assertThat(h.getDetails()).hasSize(50);
 | 
			
		||||
				})
 | 
			
		||||
				.verifyComplete();
 | 
			
		||||
				}).verifyComplete();
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +70,7 @@ public class CompositeReactiveHealthIndicatorTests {
 | 
			
		|||
		this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP))
 | 
			
		||||
				.addHealthIndicator("fast", new TimeoutHealth(10, Status.UP))
 | 
			
		||||
				.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.getDetails()).containsOnlyKeys("slow", "fast");
 | 
			
		||||
			assertThat(h.getDetails().get("slow")).isEqualTo(UNKNOWN_HEALTH);
 | 
			
		||||
| 
						 | 
				
			
			@ -86,16 +83,13 @@ public class CompositeReactiveHealthIndicatorTests {
 | 
			
		|||
		this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP))
 | 
			
		||||
				.addHealthIndicator("fast", new TimeoutHealth(10, Status.UP))
 | 
			
		||||
				.timeoutStrategy(20000, null);
 | 
			
		||||
		StepVerifier.withVirtualTime(this.indicator::health)
 | 
			
		||||
				.expectSubscription()
 | 
			
		||||
				.thenAwait(Duration.ofMillis(10000))
 | 
			
		||||
				.consumeNextWith(h -> {
 | 
			
		||||
		StepVerifier.withVirtualTime(this.indicator::health).expectSubscription()
 | 
			
		||||
				.thenAwait(Duration.ofMillis(10000)).consumeNextWith((h) -> {
 | 
			
		||||
					assertThat(h.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
					assertThat(h.getDetails()).containsOnlyKeys("slow", "fast");
 | 
			
		||||
					assertThat(h.getDetails().get("slow")).isEqualTo(HEALTHY);
 | 
			
		||||
					assertThat(h.getDetails().get("fast")).isEqualTo(HEALTHY);
 | 
			
		||||
				})
 | 
			
		||||
				.verifyComplete();
 | 
			
		||||
				}).verifyComplete();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static class TimeoutHealth implements ReactiveHealthIndicator {
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +106,7 @@ public class CompositeReactiveHealthIndicatorTests {
 | 
			
		|||
		@Override
 | 
			
		||||
		public Mono<Health> health() {
 | 
			
		||||
			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
 | 
			
		||||
	public void delegateReturnsHealth() {
 | 
			
		||||
		HealthIndicator delegate = mock(HealthIndicator.class);
 | 
			
		||||
		HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate);
 | 
			
		||||
		HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(
 | 
			
		||||
				delegate);
 | 
			
		||||
		Health status = Health.up().build();
 | 
			
		||||
		given(delegate.health()).willReturn(status);
 | 
			
		||||
		StepVerifier.create(adapter.health()).expectNext(status).verifyComplete();
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +42,8 @@ public class HealthIndicatorReactiveAdapterTests {
 | 
			
		|||
	@Test
 | 
			
		||||
	public void delegateThrowError() {
 | 
			
		||||
		HealthIndicator delegate = mock(HealthIndicator.class);
 | 
			
		||||
		HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate);
 | 
			
		||||
		HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(
 | 
			
		||||
				delegate);
 | 
			
		||||
		given(delegate.health()).willThrow(new IllegalStateException("Expected"));
 | 
			
		||||
		StepVerifier.create(adapter.health()).expectError(IllegalStateException.class);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -49,9 +51,12 @@ public class HealthIndicatorReactiveAdapterTests {
 | 
			
		|||
	@Test
 | 
			
		||||
	public void delegateRunsOnTheElasticScheduler() {
 | 
			
		||||
		String currentThread = Thread.currentThread().getName();
 | 
			
		||||
		HealthIndicator delegate = () -> Health.status(Thread.currentThread().getName()
 | 
			
		||||
				.equals(currentThread) ? Status.DOWN : Status.UP).build();
 | 
			
		||||
		HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate);
 | 
			
		||||
		HealthIndicator delegate = () -> Health
 | 
			
		||||
				.status(Thread.currentThread().getName().equals(currentThread)
 | 
			
		||||
						? Status.DOWN : Status.UP)
 | 
			
		||||
				.build();
 | 
			
		||||
		HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(
 | 
			
		||||
				delegate);
 | 
			
		||||
		StepVerifier.create(adapter.health()).expectNext(Health.status(Status.UP).build())
 | 
			
		||||
				.verifyComplete();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,9 +47,10 @@ public class RedisReactiveHealthIndicatorTests {
 | 
			
		|||
		ReactiveRedisConnection redisConnection = mock(ReactiveRedisConnection.class);
 | 
			
		||||
		ReactiveServerCommands commands = mock(ReactiveServerCommands.class);
 | 
			
		||||
		given(commands.info()).willReturn(Mono.just(info));
 | 
			
		||||
		RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(redisConnection, commands);
 | 
			
		||||
		RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(
 | 
			
		||||
				redisConnection, commands);
 | 
			
		||||
		Mono<Health> health = healthIndicator.health();
 | 
			
		||||
		StepVerifier.create(health).consumeNextWith(h -> {
 | 
			
		||||
		StepVerifier.create(health).consumeNextWith((h) -> {
 | 
			
		||||
			assertThat(h.getStatus()).isEqualTo(Status.UP);
 | 
			
		||||
			assertThat(h.getDetails()).containsOnlyKeys("version");
 | 
			
		||||
			assertThat(h.getDetails().get("version")).isEqualTo("2.8.9");
 | 
			
		||||
| 
						 | 
				
			
			@ -60,19 +61,21 @@ public class RedisReactiveHealthIndicatorTests {
 | 
			
		|||
	@Test
 | 
			
		||||
	public void redisIsDown() throws Exception {
 | 
			
		||||
		ReactiveServerCommands commands = mock(ReactiveServerCommands.class);
 | 
			
		||||
		given(commands.info()).willReturn(Mono.error(
 | 
			
		||||
				new RedisConnectionFailureException("Connection failed")));
 | 
			
		||||
		given(commands.info()).willReturn(
 | 
			
		||||
				Mono.error(new RedisConnectionFailureException("Connection failed")));
 | 
			
		||||
		ReactiveRedisConnection redisConnection = mock(ReactiveRedisConnection.class);
 | 
			
		||||
		RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(redisConnection, commands);
 | 
			
		||||
		RedisReactiveHealthIndicator healthIndicator = createHealthIndicator(
 | 
			
		||||
				redisConnection, commands);
 | 
			
		||||
		Mono<Health> health = healthIndicator.health();
 | 
			
		||||
		StepVerifier.create(health).consumeNextWith(h -> {
 | 
			
		||||
			assertThat(h.getStatus()).isEqualTo(Status.DOWN);
 | 
			
		||||
		}).verifyComplete();
 | 
			
		||||
		StepVerifier.create(health)
 | 
			
		||||
				.consumeNextWith((h) -> assertThat(h.getStatus()).isEqualTo(Status.DOWN))
 | 
			
		||||
				.verifyComplete();
 | 
			
		||||
		verify(redisConnection).close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private RedisReactiveHealthIndicator createHealthIndicator(
 | 
			
		||||
			ReactiveRedisConnection redisConnection, ReactiveServerCommands serverCommands) {
 | 
			
		||||
			ReactiveRedisConnection redisConnection,
 | 
			
		||||
			ReactiveServerCommands serverCommands) {
 | 
			
		||||
 | 
			
		||||
		ReactiveRedisConnectionFactory redisConnectionFactory = mock(
 | 
			
		||||
				ReactiveRedisConnectionFactory.class);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,16 +76,16 @@ public class ConfigurationPropertiesBinder {
 | 
			
		|||
	 * @throws ConfigurationPropertiesBindingException if the binding failed
 | 
			
		||||
	 */
 | 
			
		||||
	public void bind(Object target) {
 | 
			
		||||
		ConfigurationProperties annotation = AnnotationUtils.findAnnotation(
 | 
			
		||||
				target.getClass(), ConfigurationProperties.class);
 | 
			
		||||
		ConfigurationProperties annotation = AnnotationUtils
 | 
			
		||||
				.findAnnotation(target.getClass(), ConfigurationProperties.class);
 | 
			
		||||
		if (annotation != null) {
 | 
			
		||||
			bind(target, annotation);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Bind the specified {@code target} object using the configuration defined by
 | 
			
		||||
	 * the specified {@code annotation}.
 | 
			
		||||
	 * Bind the specified {@code target} object using the configuration defined by the
 | 
			
		||||
	 * specified {@code annotation}.
 | 
			
		||||
	 * @param target the target to bind the configuration property sources to
 | 
			
		||||
	 * @param annotation the binding configuration
 | 
			
		||||
	 * @throws ConfigurationPropertiesBindingException if the binding failed
 | 
			
		||||
| 
						 | 
				
			
			@ -154,10 +154,9 @@ public class ConfigurationPropertiesBinder {
 | 
			
		|||
		return details.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@link Validator} extension to be implemented to signal that that validator can
 | 
			
		||||
	 * be destroyed once the binder is no longer in use.
 | 
			
		||||
	 * {@link Validator} extension to be implemented to signal that that validator can be
 | 
			
		||||
	 * destroyed once the binder is no longer in use.
 | 
			
		||||
	 */
 | 
			
		||||
	interface InternalValidator extends Validator {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,8 +33,8 @@ import org.springframework.util.ClassUtils;
 | 
			
		|||
import org.springframework.validation.Validator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Builder for creating {@link ConfigurationPropertiesBinder} based on the state of
 | 
			
		||||
 * the {@link ApplicationContext}.
 | 
			
		||||
 * Builder for creating {@link ConfigurationPropertiesBinder} based on the state of the
 | 
			
		||||
 * {@link ApplicationContext}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 * @since 2.0.0
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +46,10 @@ public class ConfigurationPropertiesBinderBuilder {
 | 
			
		|||
	 */
 | 
			
		||||
	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",
 | 
			
		||||
			"javax.validation.ValidatorFactory" };
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +90,7 @@ public class ConfigurationPropertiesBinderBuilder {
 | 
			
		|||
	/**
 | 
			
		||||
	 * Specify the {@link Validator} to use or {@code null} to use the default.
 | 
			
		||||
	 * <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.
 | 
			
		||||
	 * No validation occurs otherwise.
 | 
			
		||||
	 * @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
 | 
			
		||||
	 * available {@link PropertySource}.
 | 
			
		||||
	 * Specify the {@link ConfigurableEnvironment Environment} to use, use all available
 | 
			
		||||
	 * {@link PropertySource}.
 | 
			
		||||
	 * @param environment the environment to use
 | 
			
		||||
	 * @return this instance
 | 
			
		||||
	 * @see #withPropertySources(Iterable)
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +139,8 @@ public class ConfigurationPropertiesBinderBuilder {
 | 
			
		|||
		if (this.validator != null) {
 | 
			
		||||
			return this.validator;
 | 
			
		||||
		}
 | 
			
		||||
		Validator defaultValidator = getOptionalBean(VALIDATOR_BEAN_NAME, Validator.class);
 | 
			
		||||
		Validator defaultValidator = getOptionalBean(VALIDATOR_BEAN_NAME,
 | 
			
		||||
				Validator.class);
 | 
			
		||||
		if (defaultValidator != null) {
 | 
			
		||||
			return defaultValidator;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +164,8 @@ public class ConfigurationPropertiesBinderBuilder {
 | 
			
		|||
 | 
			
		||||
	private ConversionService createDefaultConversionService() {
 | 
			
		||||
		ConversionServiceFactory conversionServiceFactory = this.applicationContext
 | 
			
		||||
				.getAutowireCapableBeanFactory().createBean(ConversionServiceFactory.class);
 | 
			
		||||
				.getAutowireCapableBeanFactory()
 | 
			
		||||
				.createBean(ConversionServiceFactory.class);
 | 
			
		||||
		return conversionServiceFactory.createConversionService();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,8 @@ import org.springframework.core.NestedExceptionUtils;
 | 
			
		|||
import org.springframework.util.ClassUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Exception thrown when a {@code @ConfigurationProperties} annotated object failed
 | 
			
		||||
 * to be bound.
 | 
			
		||||
 * Exception thrown when a {@code @ConfigurationProperties} annotated object failed to be
 | 
			
		||||
 * bound.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 * @since 2.0.0
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +30,8 @@ public class ConfigurationPropertiesBindingException extends RuntimeException {
 | 
			
		|||
 | 
			
		||||
	private final Class<?> targetClass;
 | 
			
		||||
 | 
			
		||||
	public ConfigurationPropertiesBindingException(Class<?> targetClass,
 | 
			
		||||
			String message, Throwable cause) {
 | 
			
		||||
	public ConfigurationPropertiesBindingException(Class<?> targetClass, String message,
 | 
			
		||||
			Throwable cause) {
 | 
			
		||||
		super("Could not bind properties to '" + ClassUtils.getShortName(targetClass)
 | 
			
		||||
				+ "': " + message, cause);
 | 
			
		||||
		this.targetClass = targetClass;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -233,10 +233,10 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
 | 
			
		|||
 | 
			
		||||
	private ConfigurationPropertiesBinder getBinder() {
 | 
			
		||||
		if (this.configurationPropertiesBinder == null) {
 | 
			
		||||
			this.configurationPropertiesBinder = new ConfigurationPropertiesBinderBuilder(this.applicationContext)
 | 
			
		||||
					.withConversionService(this.conversionService)
 | 
			
		||||
					.withValidator(this.validator)
 | 
			
		||||
					.withPropertySources(this.propertySources).build();
 | 
			
		||||
			this.configurationPropertiesBinder = new ConfigurationPropertiesBinderBuilder(
 | 
			
		||||
					this.applicationContext).withConversionService(this.conversionService)
 | 
			
		||||
							.withValidator(this.validator)
 | 
			
		||||
							.withPropertySources(this.propertySources).build();
 | 
			
		||||
		}
 | 
			
		||||
		return this.configurationPropertiesBinder;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,8 +51,8 @@ class ValidatedLocalValidatorFactoryBean extends LocalValidatorFactoryBean
 | 
			
		|||
		if (AnnotatedElementUtils.hasAnnotation(type, Validated.class)) {
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		if (type.getPackage() != null && type.getPackage().getName()
 | 
			
		||||
				.startsWith("org.springframework.boot")) {
 | 
			
		||||
		if (type.getPackage() != null
 | 
			
		||||
				&& type.getPackage().getName().startsWith("org.springframework.boot")) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		if (getConstraintsForClass(type).isBeanConstrained()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,9 +276,8 @@ public class WebEndpointReactiveHandlerMapping extends RequestMappingInfoHandler
 | 
			
		|||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Object invoke(Map<String, Object> arguments) {
 | 
			
		||||
			return Mono.create((sink) -> {
 | 
			
		||||
				Schedulers.elastic().schedule(() -> invoke(arguments, sink));
 | 
			
		||||
			});
 | 
			
		||||
			return Mono.create((sink) -> Schedulers.elastic()
 | 
			
		||||
					.schedule(() -> invoke(arguments, 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 ConfigurationPropertiesBinderBuilder builder =
 | 
			
		||||
			new ConfigurationPropertiesBinderBuilder(this.applicationContext);
 | 
			
		||||
	private final ConfigurationPropertiesBinderBuilder builder = new ConfigurationPropertiesBinderBuilder(
 | 
			
		||||
			this.applicationContext);
 | 
			
		||||
 | 
			
		||||
	private final MockEnvironment environment = new MockEnvironment();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -78,8 +78,8 @@ public class ConfigurationPropertiesBinderBuilderTests {
 | 
			
		|||
				DefaultConversionService.class);
 | 
			
		||||
		ConfigurationPropertiesBinder binder = this.builder
 | 
			
		||||
				.withEnvironment(this.environment).build();
 | 
			
		||||
		assertThat(ReflectionTestUtils.getField(binder, "conversionService")).isSameAs(
 | 
			
		||||
				this.applicationContext.getBean("conversionService"));
 | 
			
		||||
		assertThat(ReflectionTestUtils.getField(binder, "conversionService"))
 | 
			
		||||
				.isSameAs(this.applicationContext.getBean("conversionService"));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			@ -97,8 +97,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
 | 
			
		|||
	public void useCustomValidator() {
 | 
			
		||||
		LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
 | 
			
		||||
		ConfigurationPropertiesBinder binder = this.builder
 | 
			
		||||
				.withEnvironment(this.environment)
 | 
			
		||||
				.withValidator(validator).build();
 | 
			
		||||
				.withEnvironment(this.environment).withValidator(validator).build();
 | 
			
		||||
		assertThat(ReflectionTestUtils.getField(binder, "validator")).isSameAs(validator);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,8 +123,9 @@ public class ConfigurationPropertiesBinderBuilderTests {
 | 
			
		|||
	public void validationWithJsr303() {
 | 
			
		||||
		ConfigurationPropertiesBinder binder = this.builder
 | 
			
		||||
				.withEnvironment(this.environment).build();
 | 
			
		||||
		assertThat(bindWithValidationErrors(binder, new PropertyWithJSR303())
 | 
			
		||||
				.getAllErrors()).hasSize(2);
 | 
			
		||||
		assertThat(
 | 
			
		||||
				bindWithValidationErrors(binder, new PropertyWithJSR303()).getAllErrors())
 | 
			
		||||
						.hasSize(2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,7 +114,8 @@ public class ConfigurationPropertiesBinderTests {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private void bindToEnum(String property) {
 | 
			
		||||
		TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, property);
 | 
			
		||||
		TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
 | 
			
		||||
				property);
 | 
			
		||||
		ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
 | 
			
		||||
				this.environment.getPropertySources(), null, null);
 | 
			
		||||
		PropertyWithEnum target = new PropertyWithEnum();
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +130,8 @@ public class ConfigurationPropertiesBinderTests {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private void bindToEnumSet(String property, FooEnum... expected) {
 | 
			
		||||
		TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, property);
 | 
			
		||||
		TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
 | 
			
		||||
				property);
 | 
			
		||||
		ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
 | 
			
		||||
				this.environment.getPropertySources(), null, null);
 | 
			
		||||
		PropertyWithEnum target = new PropertyWithEnum();
 | 
			
		||||
| 
						 | 
				
			
			@ -237,11 +239,9 @@ public class ConfigurationPropertiesBinderTests {
 | 
			
		|||
	public void validationWithCustomValidator() {
 | 
			
		||||
		CustomPropertyValidator validator = spy(new CustomPropertyValidator());
 | 
			
		||||
		ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
 | 
			
		||||
				this.environment.getPropertySources(), null,
 | 
			
		||||
				validator);
 | 
			
		||||
				this.environment.getPropertySources(), null, validator);
 | 
			
		||||
		PropertyWithCustomValidator target = new PropertyWithCustomValidator();
 | 
			
		||||
		assertThat(bindWithValidationErrors(binder, target)
 | 
			
		||||
				.getAllErrors()).hasSize(1);
 | 
			
		||||
		assertThat(bindWithValidationErrors(binder, target).getAllErrors()).hasSize(1);
 | 
			
		||||
		verify(validator).validate(eq(target), any(Errors.class));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -251,8 +251,7 @@ public class ConfigurationPropertiesBinderTests {
 | 
			
		|||
				"test.foo=bar");
 | 
			
		||||
		CustomPropertyValidator validator = spy(new CustomPropertyValidator());
 | 
			
		||||
		ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
 | 
			
		||||
				this.environment.getPropertySources(), null,
 | 
			
		||||
				validator);
 | 
			
		||||
				this.environment.getPropertySources(), null, validator);
 | 
			
		||||
		PropertyWithValidatingSetter target = new PropertyWithValidatingSetter();
 | 
			
		||||
		binder.bind(target);
 | 
			
		||||
		assertThat(target.getFoo()).isEqualTo("bar");
 | 
			
		||||
| 
						 | 
				
			
			@ -431,7 +430,6 @@ public class ConfigurationPropertiesBinderTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@ConfigurationProperties(prefix = "test")
 | 
			
		||||
	public static class PropertyWithValidatingSetter {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -249,7 +249,8 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void genericConverterIsFound() {
 | 
			
		||||
		prepareConverterContext(GenericConverterConfiguration.class, PersonProperty.class);
 | 
			
		||||
		prepareConverterContext(GenericConverterConfiguration.class,
 | 
			
		||||
				PersonProperty.class);
 | 
			
		||||
		this.context.refresh();
 | 
			
		||||
		Person person = this.context.getBean(PersonProperty.class).getPerson();
 | 
			
		||||
		assertThat(person.firstName).isEqualTo("John");
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +357,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@EnableConfigurationProperties
 | 
			
		||||
	@ConfigurationProperties(prefix = "test")
 | 
			
		||||
| 
						 | 
				
			
			@ -381,7 +381,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@EnableConfigurationProperties
 | 
			
		||||
	public static class PrototypePropertiesConfig {
 | 
			
		||||
| 
						 | 
				
			
			@ -427,7 +426,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings("rawtypes")
 | 
			
		||||
	// Must be a raw type
 | 
			
		||||
	static class FactoryBeanTester implements FactoryBean, InitializingBean {
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +452,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@EnableConfigurationProperties(PropertyWithoutConfigurationPropertiesAnnotation.class)
 | 
			
		||||
	public static class ConfigurationPropertiesWithoutAnnotation {
 | 
			
		||||
| 
						 | 
				
			
			@ -553,13 +550,13 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
 | 
			
		|||
 | 
			
		||||
		@Nullable
 | 
			
		||||
		@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, " ");
 | 
			
		||||
			return new Person(content[0], content[1]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@EnableConfigurationProperties
 | 
			
		||||
	@ConfigurationProperties(prefix = "test")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,8 +63,8 @@ public class AnnotationEndpointDiscovererTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void endpointIsInParentContextIsDiscovered() {
 | 
			
		||||
		AnnotationConfigApplicationContext parent =
 | 
			
		||||
				new AnnotationConfigApplicationContext(TestEndpointConfiguration.class);
 | 
			
		||||
		AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
 | 
			
		||||
				TestEndpointConfiguration.class);
 | 
			
		||||
		loadWithParent(parent, EmptyConfiguration.class, hasTestEndpoint());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +125,7 @@ public class AnnotationEndpointDiscovererTests {
 | 
			
		|||
			Map<String, EndpointInfo<TestEndpointOperation>> endpoints = mapEndpoints(
 | 
			
		||||
					new TestAnnotationEndpointDiscoverer(context,
 | 
			
		||||
							(endpointId) -> new CachingConfiguration(0))
 | 
			
		||||
							.discoverEndpoints());
 | 
			
		||||
									.discoverEndpoints());
 | 
			
		||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
			
		||||
			Map<Method, TestEndpointOperation> operations = mapOperations(
 | 
			
		||||
					endpoints.get("test"));
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ public class AnnotationEndpointDiscovererTests {
 | 
			
		|||
	public void endpointMainReadOperationIsNotCachedWithNonMatchingId() {
 | 
			
		||||
		Function<String, CachingConfiguration> cachingConfigurationFactory = (
 | 
			
		||||
				endpointId) -> (endpointId.equals("foo") ? new CachingConfiguration(500)
 | 
			
		||||
				: new CachingConfiguration(0));
 | 
			
		||||
						: new CachingConfiguration(0));
 | 
			
		||||
		load(TestEndpointConfiguration.class, (context) -> {
 | 
			
		||||
			Map<String, EndpointInfo<TestEndpointOperation>> endpoints = mapEndpoints(
 | 
			
		||||
					new TestAnnotationEndpointDiscoverer(context,
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ public class AnnotationEndpointDiscovererTests {
 | 
			
		|||
	public void endpointMainReadOperationIsCachedWithMatchingId() {
 | 
			
		||||
		Function<String, CachingConfiguration> cachingConfigurationFactory = (
 | 
			
		||||
				endpointId) -> (endpointId.equals("test") ? new CachingConfiguration(500)
 | 
			
		||||
				: new CachingConfiguration(0));
 | 
			
		||||
						: new CachingConfiguration(0));
 | 
			
		||||
		load(TestEndpointConfiguration.class, (context) -> {
 | 
			
		||||
			Map<String, EndpointInfo<TestEndpointOperation>> endpoints = mapEndpoints(
 | 
			
		||||
					new TestAnnotationEndpointDiscoverer(context,
 | 
			
		||||
| 
						 | 
				
			
			@ -174,10 +174,10 @@ public class AnnotationEndpointDiscovererTests {
 | 
			
		|||
					.isEqualTo(500);
 | 
			
		||||
			assertThat(operations.get(ReflectionUtils.findMethod(TestEndpoint.class,
 | 
			
		||||
					"getOne", String.class)).getInvoker())
 | 
			
		||||
					.isNotInstanceOf(CachingOperationInvoker.class);
 | 
			
		||||
							.isNotInstanceOf(CachingOperationInvoker.class);
 | 
			
		||||
			assertThat(operations.get(ReflectionUtils.findMethod(TestEndpoint.class,
 | 
			
		||||
					"update", String.class, String.class)).getInvoker())
 | 
			
		||||
					.isNotInstanceOf(CachingOperationInvoker.class);
 | 
			
		||||
							.isNotInstanceOf(CachingOperationInvoker.class);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,8 +69,8 @@ public class JerseyWebEndpointIntegrationTests extends
 | 
			
		|||
		@Bean
 | 
			
		||||
		public ServletRegistrationBean<ServletContainer> servletContainer(
 | 
			
		||||
				ResourceConfig resourceConfig) {
 | 
			
		||||
			return new ServletRegistrationBean<>(
 | 
			
		||||
					new ServletContainer(resourceConfig), "/*");
 | 
			
		||||
			return new ServletRegistrationBean<>(new ServletContainer(resourceConfig),
 | 
			
		||||
					"/*");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue