From 3ca1e91cded30d483f31d2c61fc58c48e41b568b Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 12 Jun 2025 09:57:33 -0700 Subject: [PATCH] Create spring-boot-health module Closes gh-46155 --- settings.gradle | 1 + .../build.gradle | 3 +- ...ityHealthContributorAutoConfiguration.java | 3 + .../AvailabilityProbesAutoConfiguration.java | 3 + .../JacksonEndpointAutoConfiguration.java | 25 +- ...toConfiguredHealthContributorRegistry.java | 55 --- .../AutoConfiguredHealthEndpointGroups.java | 4 +- ...uredReactiveHealthContributorRegistry.java | 55 --- .../GroupsHealthContributorNameValidator.java | 45 +++ .../HealthEndpointAutoConfiguration.java | 12 +- .../health/HealthEndpointConfiguration.java | 117 +----- ...ointReactiveWebExtensionConfiguration.java | 10 +- ...althEndpointWebExtensionConfiguration.java | 8 +- .../OnEnabledHealthIndicatorCondition.java | 33 -- .../ReactiveHealthEndpointConfiguration.java | 57 --- ...SslHealthContributorAutoConfiguration.java | 9 +- ...aceHealthContributorAutoConfiguration.java | 9 +- ...ot.autoconfigure.AutoConfiguration.imports | 1 - ...ilabilityProbesAutoConfigurationTests.java | 8 + .../JmxEndpointAccessIntegrationTests.java | 2 +- .../jmx/JmxEndpointIntegrationTests.java | 6 +- ...figuredHealthContributorRegistryTests.java | 54 --- ...toConfiguredHealthEndpointGroupsTests.java | 2 +- ...eactiveHealthContributorRegistryTests.java | 55 --- .../HealthEndpointAutoConfigurationTests.java | 104 ++--- ...HealthContributorFailureAnalyzerTests.java | 5 +- ...althContributorAutoConfigurationTests.java | 11 +- ...althContributorAutoConfigurationTests.java | 2 +- .../spring-boot-actuator-docs/build.gradle | 1 + .../HealthEndpointDocumentationTests.java | 22 +- .../build.gradle | 1 + .../HealthEndpointWebIntegrationTests.java | 44 ++- .../spring-boot-actuator/build.gradle | 1 + .../AvailabilityStateHealthIndicator.java | 10 +- .../LivenessStateHealthIndicator.java | 4 +- .../ReadinessStateHealthIndicator.java | 4 +- ...ositeHealthContributorReactiveAdapter.java | 66 ---- ...th.java => CompositeHealthDescriptor.java} | 38 +- .../boot/actuate/health/Contributor.java | 196 ++++++++++ .../health/DefaultContributorRegistry.java | 114 ------ .../DefaultHealthContributorRegistry.java | 43 -- ...aultReactiveHealthContributorRegistry.java | 43 -- .../health/HealthContributorNameFactory.java | 48 --- ...thComponent.java => HealthDescriptor.java} | 13 +- .../boot/actuate/health/HealthEndpoint.java | 41 +- .../actuate/health/HealthEndpointGroup.java | 6 +- .../actuate/health/HealthEndpointSupport.java | 167 ++++---- .../health/HealthEndpointWebExtension.java | 50 ++- ...ealthEndpointWebExtensionRuntimeHints.java | 4 +- .../actuate/health/HttpCodeStatusMapper.java | 2 + .../health/IndicatedHealthDescriptor.java | 56 +++ .../boot/actuate/health/NamedContributor.java | 62 --- .../actuate/health/NamedContributors.java | 48 --- .../health/NamedContributorsMapAdapter.java | 89 ----- .../health/ReactiveHealthContributor.java | 45 --- .../ReactiveHealthEndpointWebExtension.java | 83 ++-- .../health/SimpleHttpCodeStatusMapper.java | 1 + .../health/SimpleStatusAggregator.java | 1 + .../boot/actuate/health/StatusAggregator.java | 3 + ...ealth.java => SystemHealthDescriptor.java} | 16 +- .../boot/actuate/ssl/SslHealthIndicator.java | 10 +- .../system/DiskSpaceHealthIndicator.java | 8 +- ...AvailabilityStateHealthIndicatorTests.java | 8 +- .../LivenessStateHealthIndicatorTests.java | 2 +- .../ReadinessStateHealthIndicatorTests.java | 2 +- .../CompositeHealthDescriptorTests.java | 95 +++++ .../actuate/health/CompositeHealthTests.java | 97 ----- .../DefaultContributorRegistryTests.java | 165 -------- .../HealthContributorNameFactoryTests.java | 55 --- .../health/HealthEndpointSupportTests.java | 368 +++++++++--------- .../actuate/health/HealthEndpointTests.java | 68 ++-- ...EndpointWebExtensionRuntimeHintsTests.java | 3 +- .../HealthEndpointWebExtensionTests.java | 70 ++-- .../IndicatedHealthDescriptorTests.java | 54 +++ .../actuate/health/NamedContributorTests.java | 51 --- ...activeHealthEndpointWebExtensionTests.java | 64 +-- ...iveHealthIndicatorImplementationTests.java | 9 +- .../SimpleHttpCodeStatusMapperTests.java | 1 + .../health/SimpleStatusAggregatorTests.java | 2 + .../health/SystemHealthDescriptorTests.java | 84 ++++ .../actuate/health/SystemHealthTests.java | 53 --- .../actuate/ssl/SslHealthIndicatorTests.java | 4 +- .../system/DiskSpaceHealthIndicatorTests.java | 6 +- .../spring-boot-amqp/build.gradle | 2 +- ...bitHealthContributorAutoConfiguration.java | 8 +- .../health/RabbitHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- .../health/RabbitHealthIndicatorTests.java | 6 +- .../spring-boot-cassandra/build.gradle | 2 +- ...draHealthContributorAutoConfiguration.java | 4 +- ...sandraHealthContributorConfigurations.java | 12 +- ...iveHealthContributorAutoConfiguration.java | 4 +- .../CassandraDriverHealthIndicator.java | 10 +- ...assandraDriverReactiveHealthIndicator.java | 10 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- ...althContributorAutoConfigurationTests.java | 4 +- .../CassandraDriverHealthIndicatorTests.java | 6 +- ...draDriverReactiveHealthIndicatorTests.java | 6 +- .../spring-boot-cloudfoundry/build.gradle | 1 + ...dryReactiveHealthEndpointWebExtension.java | 6 +- ...loudFoundryHealthEndpointWebExtension.java | 6 +- ...loudFoundryWebEndpointDiscovererTests.java | 4 +- ...activeHealthEndpointWebExtensionTests.java | 24 +- ...FoundryActuatorAutoConfigurationTests.java | 21 +- ...FoundryActuatorAutoConfigurationTests.java | 5 +- ...oundryHealthEndpointWebExtensionTests.java | 25 +- .../spring-boot-couchbase/build.gradle | 2 +- ...aseHealthContributorAutoConfiguration.java | 8 +- ...iveHealthContributorAutoConfiguration.java | 8 +- .../{actuate => }/health/CouchbaseHealth.java | 6 +- .../health/CouchbaseHealthIndicator.java | 8 +- .../CouchbaseReactiveHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 6 +- ...althContributorAutoConfigurationTests.java | 6 +- .../health/CouchbaseHealthIndicatorTests.java | 6 +- ...CouchbaseReactiveHealthIndicatorTests.java | 6 +- .../build.gradle | 2 +- ...iveHealthContributorAutoConfiguration.java | 8 +- .../ElasticsearchReactiveHealthIndicator.java | 10 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 6 +- ...ticsearchReactiveHealthIndicatorTests.java | 6 +- .../spring-boot-data-mongodb/build.gradle | 2 +- .../MongoHealthIndicatorIntegrationTests.java | 8 +- ...activeHealthIndicatorIntegrationTests.java | 8 +- ...ngoHealthContributorAutoConfiguration.java | 8 +- ...iveHealthContributorAutoConfiguration.java | 8 +- .../health/MongoHealthIndicator.java | 8 +- .../health/MongoReactiveHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- ...althContributorAutoConfigurationTests.java | 6 +- .../health/MongoHealthIndicatorTests.java | 6 +- .../MongoReactiveHealthIndicatorTests.java | 6 +- .../spring-boot-data-redis/build.gradle | 2 +- ...disHealthContributorAutoConfiguration.java | 10 +- ...iveHealthContributorAutoConfiguration.java | 10 +- .../{actuate => }/health/RedisHealth.java | 9 +- .../health/RedisHealthIndicator.java | 8 +- .../health/RedisReactiveHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 6 +- ...althContributorAutoConfigurationTests.java | 6 +- .../health/RedisHealthIndicatorTests.java | 6 +- .../RedisReactiveHealthIndicatorTests.java | 6 +- .../spring-boot-dependencies/build.gradle | 1 + .../spring-boot-docs/build.gradle | 1 + .../reference/pages/actuator/endpoints.adoc | 10 +- .../MyReactiveHealthIndicator.java | 4 +- .../MyHealthIndicator.java | 4 +- .../MyHealthMetricsExportConfiguration.java | 2 +- .../MyReactiveHealthIndicator.kt | 4 +- .../MyHealthIndicator.kt | 4 +- .../MyHealthMetricsExportConfiguration.kt | 2 +- .../MetricsHealthMicrometerExportTests.java | 12 +- .../spring-boot-elasticsearch/build.gradle | 2 +- ...estHealthContributorAutoConfiguration.java | 8 +- ...lasticsearchRestClientHealthIndicator.java | 16 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- ...csearchRestClientHealthIndicatorTests.java | 9 +- .../spring-boot-hazelcast/build.gradle | 2 +- ...astHealthContributorAutoConfiguration.java | 8 +- .../health/HazelcastHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...utorAutoConfigurationIntegrationTests.java | 8 +- ...althContributorAutoConfigurationTests.java | 4 +- .../health/HazelcastHealthIndicatorTests.java | 6 +- .../spring-boot-health/build.gradle | 39 ++ ...mpositeHealthContributorConfiguration.java | 5 +- ...mpositeHealthContributorConfiguration.java | 11 +- ...eactiveHealthContributorConfiguration.java | 11 +- .../ConditionalOnEnabledHealthIndicator.java | 4 +- .../HealthContributorAutoConfiguration.java | 12 +- .../OnEnabledHealthIndicatorCondition.java | 54 +++ .../contributor/package-info.java | 20 + .../HealthContributorNameGenerator.java | 97 +++++ ...hContributorRegistryAutoConfiguration.java | 78 ++++ .../autoconfigure/registry/package-info.java | 20 + .../contributor}/AbstractHealthIndicator.java | 13 +- .../AbstractReactiveHealthIndicator.java | 5 +- .../CompositeHealthContributor.java | 10 +- .../CompositeHealthContributorAdapter.java | 33 ++ .../CompositeHealthContributors.java | 56 +++ .../CompositeReactiveHealthContributor.java | 16 +- ...siteReactiveHealthContributorAdapter.java} | 16 +- .../CompositeReactiveHealthContributors.java | 57 +++ .../boot/health/contributor}/Health.java | 28 +- .../contributor}/HealthContributor.java | 11 +- .../contributor/HealthContributors.java | 75 ++++ .../HealthContributorsAdapter.java | 46 +++ .../health/contributor}/HealthIndicator.java | 12 +- .../contributor/HealthIndicatorAdapter.java} | 7 +- .../MapCompositeHealthContributor.java | 61 +++ ...MapCompositeReactiveHealthContributor.java | 63 +++ .../contributor}/PingHealthIndicator.java | 6 +- .../ReactiveHealthContributor.java | 58 +++ .../ReactiveHealthContributors.java | 97 +++++ .../ReactiveHealthContributorsAdapter.java | 49 +++ .../contributor}/ReactiveHealthIndicator.java | 18 +- .../ReactiveHealthIndicatorAdapter.java} | 30 +- .../boot/health/contributor}/Status.java | 4 +- .../boot/health/contributor/package-info.java | 20 + .../health/registry/AbstractRegistry.java | 110 ++++++ .../DefaultHealthContributorRegistry.java | 73 ++++ ...aultReactiveHealthContributorRegistry.java | 73 ++++ .../HealthContributorNameValidator.java | 36 ++ .../registry/HealthContributorRegistry.java} | 21 +- .../ReactiveHealthContributorRegistry.java | 47 +++ .../boot/health/registry/package-info.java | 20 + ...ot.autoconfigure.AutoConfiguration.imports | 2 + ...teHealthContributorConfigurationTests.java | 14 +- ...teHealthContributorConfigurationTests.java | 20 +- ...veHealthContributorConfigurationTests.java | 21 +- ...ditionalOnEnabledHealthIndicatorTests.java | 93 +++++ ...althContributorAutoConfigurationTests.java | 10 +- .../HealthContributorNameGeneratorTests.java | 72 ++++ ...ributorRegistryAutoConfigurationTests.java | 158 ++++++++ .../AbstractHealthIndicatorTests.java | 13 +- .../AbstractReactiveHealthIndicatorTests.java | 28 +- ...mpositeHealthContributorAdapterTests.java} | 12 +- .../CompositeHealthContributorTests.java | 19 +- .../CompositeHealthContributorsTests.java | 64 +++ ...eactiveHealthContributorAdapterTests.java} | 13 +- ...mpositeReactiveHealthContributorTests.java | 33 +- ...positeReactiveHealthContributorsTests.java | 65 ++++ .../HealthContributorsAdapterTests.java} | 47 ++- .../contributor/HealthContributorsTests.java | 74 ++++ .../HealthIndicatorAdapterTests.java} | 12 +- .../contributor}/HealthIndicatorTests.java | 6 +- .../boot/health/contributor}/HealthTests.java | 2 +- .../MapCompositeHealthContributorTests.java | 69 ++++ ...mpositeReactiveHealthContributorTests.java | 71 ++++ .../contributor/MapCompositeTests.java} | 105 ++--- .../PingHealthIndicatorTests.java | 2 +- .../ReactiveHealthContributorTests.java | 23 +- ...eactiveHealthContributorsAdapterTests.java | 80 ++++ .../ReactiveHealthContributorsTests.java | 94 +++++ .../ReactiveHealthIndicatorAdapterTests.java | 49 +++ .../ReactiveHealthIndicatorTests.java | 12 +- .../boot/health/contributor}/StatusTests.java | 2 +- ...bstractHealthContributorRegistryTests.java | 158 ++++++++ ...DefaultHealthContributorRegistryTests.java | 60 +++ ...eactiveHealthContributorRegistryTests.java | 60 +++ .../spring-boot-jdbc/build.gradle | 2 +- ...rceHealthContributorAutoConfiguration.java | 16 +- .../DataSourceHealthIndicatorProperties.java | 2 +- .../health/DataSourceHealthIndicator.java | 10 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 10 +- .../DataSourceHealthIndicatorTests.java | 6 +- .../spring-boot-jersey/build.gradle | 1 + ...JerseyExtensionAutoConfigurationTests.java | 12 +- ...ndpointAdditionalPathIntegrationTests.java | 2 + .../spring-boot-jms/build.gradle | 2 +- ...JmsHealthContributorAutoConfiguration.java | 8 +- .../health/JmsHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- .../health/JmsHealthIndicatorTests.java | 6 +- .../spring-boot-ldap/build.gradle | 2 +- ...dapHealthContributorAutoConfiguration.java | 8 +- .../health/LdapHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- .../health/LdapHealthIndicatorTests.java | 6 +- .../spring-boot-mail/build.gradle | 2 +- ...ailHealthContributorAutoConfiguration.java | 8 +- .../health/MailHealthIndicator.java | 10 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- .../health/MailHealthIndicatorTests.java | 6 +- .../spring-boot-neo4j/build.gradle | 2 +- ...activeHealthIndicatorIntegrationTests.java | 10 +- ...o4jHealthContributorAutoConfiguration.java | 6 +- .../Neo4jHealthContributorConfigurations.java | 12 +- .../health/Neo4jHealthDetails.java | 2 +- .../health/Neo4jHealthDetailsHandler.java | 8 +- .../health/Neo4jHealthIndicator.java | 8 +- .../health/Neo4jReactiveHealthIndicator.java | 8 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 12 +- .../health/Neo4jHealthIndicatorTests.java | 6 +- .../Neo4jReactiveHealthIndicatorTests.java | 4 +- .../health/ResultSummaryMock.java | 2 +- .../spring-boot-r2dbc/build.gradle | 2 +- ...oryHealthContributorAutoConfiguration.java | 8 +- .../ConnectionFactoryHealthIndicator.java | 19 +- .../{actuate => }/health/package-info.java | 2 +- ...althContributorAutoConfigurationTests.java | 4 +- ...ConnectionFactoryHealthIndicatorTests.java | 6 +- .../spring-boot-security/build.gradle | 1 + ...mentWebSecurityAutoConfigurationTests.java | 12 +- ...mentWebSecurityAutoConfigurationTests.java | 11 +- .../spring-boot-starter-actuator/build.gradle | 1 + .../spring-boot-webflux/build.gradle | 1 + ...lthEndpointExtensionAutoConfiguration.java | 5 +- ...ndpointAdditionalPathIntegrationTests.java | 8 +- ...dpointExtensionAutoConfigurationTests.java | 22 +- .../spring-boot-webmvc/build.gradle | 1 + ...lthEndpointExtensionAutoConfiguration.java | 2 +- ...dpointExtensionAutoConfigurationTests.java | 21 +- ...ndpointAdditionalPathIntegrationTests.java | 3 + .../WebMvcEndpointAccessIntegrationTests.java | 2 +- ...ebMvcEndpointExposureIntegrationTests.java | 8 +- .../actuator/ExampleHealthIndicator.java | 4 +- .../actuator/SampleActuatorApplication.java | 8 +- 310 files changed, 4564 insertions(+), 2765 deletions(-) delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistry.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistry.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/GroupsHealthContributorNameValidator.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/OnEnabledHealthIndicatorCondition.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ReactiveHealthEndpointConfiguration.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistryTests.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistryTests.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapter.java rename spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/{CompositeHealth.java => CompositeHealthDescriptor.java} (53%) create mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Contributor.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultContributorRegistry.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultHealthContributorRegistry.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultReactiveHealthContributorRegistry.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorNameFactory.java rename spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/{HealthComponent.java => HealthDescriptor.java} (78%) create mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptor.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributor.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributors.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapter.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributor.java rename spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/{SystemHealth.java => SystemHealthDescriptor.java} (71%) create mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthDescriptorTests.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthTests.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/DefaultContributorRegistryTests.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthContributorNameFactoryTests.java create mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptorTests.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorTests.java create mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthDescriptorTests.java delete mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthTests.java rename spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/{actuate => }/health/RabbitHealthIndicator.java (86%) rename spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/{actuate => }/health/RabbitHealthIndicatorTests.java (94%) rename spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/{actuate => }/health/CassandraDriverHealthIndicator.java (86%) rename spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/{actuate => }/health/CassandraDriverReactiveHealthIndicator.java (86%) rename spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/{actuate => }/health/CassandraDriverHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/{actuate => }/health/CassandraDriverReactiveHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/{actuate => }/health/CouchbaseHealth.java (92%) rename spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/{actuate => }/health/CouchbaseHealthIndicator.java (85%) rename spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/{actuate => }/health/CouchbaseReactiveHealthIndicator.java (84%) rename spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/{actuate => }/health/CouchbaseHealthIndicatorTests.java (95%) rename spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/{actuate => }/health/CouchbaseReactiveHealthIndicatorTests.java (96%) rename spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/{actuate => }/health/ElasticsearchReactiveHealthIndicator.java (90%) rename spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/{actuate => }/health/ElasticsearchReactiveHealthIndicatorTests.java (96%) rename spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/{actuate => }/health/MongoHealthIndicatorIntegrationTests.java (91%) rename spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/{actuate => }/health/MongoReactiveHealthIndicatorIntegrationTests.java (91%) rename spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/{actuate => }/health/MongoHealthIndicator.java (85%) rename spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/{actuate => }/health/MongoReactiveHealthIndicator.java (86%) rename spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/{actuate => }/health/MongoHealthIndicatorTests.java (92%) rename spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/{actuate => }/health/MongoReactiveHealthIndicatorTests.java (94%) rename spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/{actuate => }/health/RedisHealth.java (80%) rename spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/{actuate => }/health/RedisHealthIndicator.java (89%) rename spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/{actuate => }/health/RedisReactiveHealthIndicator.java (91%) rename spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/{actuate => }/health/RedisHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/{actuate => }/health/RedisReactiveHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/{actuate => }/health/ElasticsearchRestClientHealthIndicator.java (86%) rename spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/{actuate => }/health/ElasticsearchRestClientHealthIndicatorTests.java (95%) rename spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/{actuate => }/health/HazelcastHealthIndicator.java (85%) rename spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/{actuate => }/health/package-info.java (91%) rename spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/{actuate => }/health/HazelcastHealthIndicatorTests.java (94%) create mode 100644 spring-boot-project/spring-boot-health/build.gradle rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor}/AbstractCompositeHealthContributorConfiguration.java (93%) rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor}/CompositeHealthContributorConfiguration.java (84%) rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor}/CompositeReactiveHealthContributorConfiguration.java (83%) rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor}/ConditionalOnEnabledHealthIndicator.java (95%) rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor}/HealthContributorAutoConfiguration.java (75%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/OnEnabledHealthIndicatorCondition.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/package-info.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGenerator.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/package-info.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/AbstractHealthIndicator.java (89%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/AbstractReactiveHealthIndicator.java (97%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/CompositeHealthContributor.java (85%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapter.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributors.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/CompositeReactiveHealthContributor.java (80%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorMapAdapter.java => spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapter.java} (60%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributors.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/Health.java (92%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/HealthContributor.java (67%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributors.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributorsAdapter.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/HealthIndicator.java (76%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapter.java => spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicatorAdapter.java} (83%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeHealthContributor.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributor.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/PingHealthIndicator.java (85%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributor.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributors.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapter.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/ReactiveHealthIndicator.java (75%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorMapAdapter.java => spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapter.java} (53%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health => spring-boot-health/src/main/java/org/springframework/boot/health/contributor}/Status.java (97%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/package-info.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/AbstractRegistry.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistry.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistry.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorNameValidator.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ContributorRegistry.java => spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorRegistry.java} (70%) create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/ReactiveHealthContributorRegistry.java create mode 100644 spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/package-info.java create mode 100644 spring-boot-project/spring-boot-health/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor}/AbstractCompositeHealthContributorConfigurationTests.java (92%) rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor}/CompositeHealthContributorConfigurationTests.java (65%) rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor}/CompositeReactiveHealthContributorConfigurationTests.java (67%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicatorTests.java rename spring-boot-project/{spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health => spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor}/HealthContributorAutoConfigurationTests.java (91%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGeneratorTests.java create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfigurationTests.java rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/AbstractHealthIndicatorTests.java (91%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/AbstractReactiveHealthIndicatorTests.java (88%) rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorRegistry.java => spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapterTests.java} (64%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/CompositeHealthContributorTests.java (71%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorsTests.java rename spring-boot-project/{spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributorRegistry.java => spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapterTests.java} (61%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/CompositeReactiveHealthContributorTests.java (55%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorsTests.java rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapterTests.java => spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsAdapterTests.java} (58%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsTests.java rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapterTests.java => spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorAdapterTests.java} (81%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/HealthIndicatorTests.java (89%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/HealthTests.java (99%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeHealthContributorTests.java create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributorTests.java rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapterTests.java => spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeTests.java} (51%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/PingHealthIndicatorTests.java (95%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/ReactiveHealthContributorTests.java (68%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapterTests.java create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsTests.java create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapterTests.java rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/ReactiveHealthIndicatorTests.java (79%) rename spring-boot-project/{spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health => spring-boot-health/src/test/java/org/springframework/boot/health/contributor}/StatusTests.java (97%) create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/AbstractHealthContributorRegistryTests.java create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistryTests.java create mode 100644 spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistryTests.java rename spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/{actuate => }/health/DataSourceHealthIndicator.java (94%) rename spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/{actuate => }/health/DataSourceHealthIndicatorTests.java (96%) rename spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/{actuate => }/health/JmsHealthIndicator.java (90%) rename spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/{actuate => }/health/JmsHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/{actuate => }/health/LdapHealthIndicator.java (88%) rename spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/{actuate => }/health/LdapHealthIndicatorTests.java (93%) rename spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/{actuate => }/health/MailHealthIndicator.java (82%) rename spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/{actuate => }/health/MailHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/{actuate/neo4j => neo4/health}/Neo4jReactiveHealthIndicatorIntegrationTests.java (88%) rename spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/{actuate => }/health/Neo4jHealthDetails.java (95%) rename spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/{actuate => }/health/Neo4jHealthDetailsHandler.java (86%) rename spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/{actuate => }/health/Neo4jHealthIndicator.java (92%) rename spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/{actuate => }/health/Neo4jReactiveHealthIndicator.java (92%) rename spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/{actuate => }/health/Neo4jHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/{actuate => }/health/Neo4jReactiveHealthIndicatorTests.java (97%) rename spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/{actuate => }/health/ResultSummaryMock.java (96%) rename spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/{actuate => }/health/ConnectionFactoryHealthIndicator.java (85%) rename spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/{actuate => }/health/package-info.java (92%) rename spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/{actuate => }/health/ConnectionFactoryHealthIndicatorTests.java (97%) diff --git a/settings.gradle b/settings.gradle index f049d710109..c0b0f2b017c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -95,6 +95,7 @@ include "spring-boot-project:spring-boot-gson" include "spring-boot-project:spring-boot-h2console" include "spring-boot-project:spring-boot-hateoas" include "spring-boot-project:spring-boot-hazelcast" +include "spring-boot-project:spring-boot-health" include "spring-boot-project:spring-boot-hibernate" include "spring-boot-project:spring-boot-http-client" include "spring-boot-project:spring-boot-http-converter" diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index b2d36b6f9bd..4480ac2e879 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -28,10 +28,11 @@ description = "Spring Boot Actuator AutoConfigure" dependencies { api(project(":spring-boot-project:spring-boot-actuator")) api(project(":spring-boot-project:spring-boot-autoconfigure")) - + implementation("com.fasterxml.jackson.core:jackson-databind") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-web-server")) optional("com.fasterxml.jackson.core:jackson-databind") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityHealthContributorAutoConfiguration.java index 8d4ae371d06..20f9e23fc37 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityHealthContributorAutoConfiguration.java @@ -23,8 +23,10 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.availability.ApplicationAvailability; +import org.springframework.boot.health.contributor.Health; import org.springframework.context.annotation.Bean; /** @@ -35,6 +37,7 @@ import org.springframework.context.annotation.Bean; * @since 2.3.2 */ @AutoConfiguration(after = ApplicationAvailabilityAutoConfiguration.class) +@ConditionalOnClass(Health.class) public class AvailabilityHealthContributorAutoConfiguration { @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfiguration.java index de73c50b6c9..756338c4e78 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfiguration.java @@ -23,10 +23,12 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionMessage; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.cloud.CloudPlatform; +import org.springframework.boot.health.contributor.Health; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; @@ -42,6 +44,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata; */ @AutoConfiguration(after = { AvailabilityHealthContributorAutoConfiguration.class, ApplicationAvailabilityAutoConfiguration.class }) +@ConditionalOnClass(Health.class) @Conditional(AvailabilityProbesAutoConfiguration.ProbesCondition.class) public class AvailabilityProbesAutoConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jackson/JacksonEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jackson/JacksonEndpointAutoConfiguration.java index 39eb56f8dab..9ddc445e0f5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jackson/JacksonEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jackson/JacksonEndpointAutoConfiguration.java @@ -16,6 +16,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.jackson; +import java.util.HashSet; +import java.util.Set; + import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -28,6 +31,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProp import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.util.ClassUtils; /** * {@link EnableAutoConfiguration Auto-configuration} for Endpoint Jackson support. @@ -39,6 +43,8 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @SuppressWarnings("removal") public class JacksonEndpointAutoConfiguration { + private static final String CONTRIBUTED_HEALTH = "org.springframework.boot.health.contributor.ContributedHealth"; + @Bean @ConditionalOnBooleanProperty(name = "management.endpoints.jackson.isolated-object-mapper", matchIfMissing = true) @ConditionalOnClass({ ObjectMapper.class, Jackson2ObjectMapperBuilder.class }) @@ -49,7 +55,24 @@ public class JacksonEndpointAutoConfiguration { SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS) .serializationInclusion(Include.NON_NULL) .build(); - return () -> objectMapper; + Set> supportedTypes = new HashSet<>(EndpointObjectMapper.DEFAULT_SUPPORTED_TYPES); + if (ClassUtils.isPresent(CONTRIBUTED_HEALTH, null)) { + supportedTypes.add(ClassUtils.resolveClassName(CONTRIBUTED_HEALTH, null)); + } + return new EndpointObjectMapper() { + + @Override + public ObjectMapper get() { + return objectMapper; + } + + @Override + public Set> getSupportedTypes() { + return supportedTypes; + } + + }; + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistry.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistry.java deleted file mode 100644 index ad1a2a02ba9..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistry.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.health; - -import java.util.Collection; -import java.util.Map; - -import org.springframework.boot.actuate.health.DefaultHealthContributorRegistry; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthContributorRegistry; -import org.springframework.util.Assert; - -/** - * An auto-configured {@link HealthContributorRegistry} that ensures registered indicators - * do not clash with groups names. - * - * @author Phillip Webb - */ -class AutoConfiguredHealthContributorRegistry extends DefaultHealthContributorRegistry { - - private final Collection groupNames; - - AutoConfiguredHealthContributorRegistry(Map contributors, - Collection groupNames) { - super(contributors); - this.groupNames = groupNames; - contributors.keySet().forEach(this::assertDoesNotClashWithGroup); - } - - @Override - public void registerContributor(String name, HealthContributor contributor) { - assertDoesNotClashWithGroup(name); - super.registerContributor(name, contributor); - } - - private void assertDoesNotClashWithGroup(String name) { - Assert.state(!this.groupNames.contains(name), - () -> "HealthContributor with name \"" + name + "\" clashes with group"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroups.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroups.java index f468f056198..2551811a72e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroups.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroups.java @@ -18,11 +18,11 @@ package org.springframework.boot.actuate.autoconfigure.health; import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.TreeMap; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Stream; @@ -93,7 +93,7 @@ class AutoConfiguredHealthEndpointGroups implements HealthEndpointGroups, Additi private Map createGroups(Map groupProperties, BeanFactory beanFactory, StatusAggregator defaultStatusAggregator, HttpCodeStatusMapper defaultHttpCodeStatusMapper, Show defaultShowComponents, Show defaultShowDetails, Set defaultRoles) { - Map groups = new LinkedHashMap<>(); + Map groups = new TreeMap<>(); groupProperties.forEach((groupName, group) -> { Status status = group.getStatus(); Show showComponents = (group.getShowComponents() != null) ? group.getShowComponents() diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistry.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistry.java deleted file mode 100644 index 463d7e00684..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistry.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.health; - -import java.util.Collection; -import java.util.Map; - -import org.springframework.boot.actuate.health.DefaultReactiveHealthContributorRegistry; -import org.springframework.boot.actuate.health.HealthContributorRegistry; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; -import org.springframework.util.Assert; - -/** - * An auto-configured {@link HealthContributorRegistry} that ensures registered indicators - * do not clash with groups names. - * - * @author Phillip Webb - */ -class AutoConfiguredReactiveHealthContributorRegistry extends DefaultReactiveHealthContributorRegistry { - - private final Collection groupNames; - - AutoConfiguredReactiveHealthContributorRegistry(Map contributors, - Collection groupNames) { - super(contributors); - this.groupNames = groupNames; - contributors.keySet().forEach(this::assertDoesNotClashWithGroup); - } - - @Override - public void registerContributor(String name, ReactiveHealthContributor contributor) { - assertDoesNotClashWithGroup(name); - super.registerContributor(name, contributor); - } - - private void assertDoesNotClashWithGroup(String name) { - Assert.state(!this.groupNames.contains(name), - () -> "ReactiveHealthContributor with name \"" + name + "\" clashes with group"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/GroupsHealthContributorNameValidator.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/GroupsHealthContributorNameValidator.java new file mode 100644 index 00000000000..ef6c05cbdb3 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/GroupsHealthContributorNameValidator.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.health; + +import java.util.Collections; +import java.util.Set; + +import org.springframework.boot.actuate.health.HealthEndpointGroups; +import org.springframework.boot.health.registry.HealthContributorNameValidator; +import org.springframework.util.Assert; + +/** + * {@link HealthContributorNameValidator} to ensure names don't clash with groups. + * + * @author Phillip Webb + */ +class GroupsHealthContributorNameValidator implements HealthContributorNameValidator { + + private final Set groupNames; + + GroupsHealthContributorNameValidator(HealthEndpointGroups groups) { + this.groupNames = (groups != null) ? groups.getNames() : Collections.emptySet(); + } + + @Override + public void validate(String name) throws IllegalStateException { + Assert.state(!this.groupNames.contains(name), + () -> "HealthContributor with name \"" + name + "\" clashes with group"); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfiguration.java index 88ec76e22f1..adf59f9d0e6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfiguration.java @@ -20,7 +20,10 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.condition.Conditi import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.health.contributor.Health; import org.springframework.context.annotation.Import; /** @@ -32,11 +35,14 @@ import org.springframework.context.annotation.Import; * @author Scott Frederick * @since 2.0.0 */ -@AutoConfiguration +@AutoConfiguration( + afterName = "org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration") +@ConditionalOnClass(Health.class) +@ConditionalOnBean(type = "org.springframework.boot.health.registry.HealthContributorRegistry") @ConditionalOnAvailableEndpoint(HealthEndpoint.class) @EnableConfigurationProperties(HealthEndpointProperties.class) -@Import({ HealthEndpointConfiguration.class, ReactiveHealthEndpointConfiguration.class, - HealthEndpointWebExtensionConfiguration.class, HealthEndpointReactiveWebExtensionConfiguration.class }) +@Import({ HealthEndpointConfiguration.class, HealthEndpointWebExtensionConfiguration.class, + HealthEndpointReactiveWebExtensionConfiguration.class }) public class HealthEndpointAutoConfiguration { } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java index 3488eb28390..f9d90869426 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java @@ -16,39 +16,27 @@ package org.springframework.boot.actuate.autoconfigure.health; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.Set; import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.CompositeReactiveHealthContributor; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthContributorRegistry; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroups; import org.springframework.boot.actuate.health.HealthEndpointGroupsPostProcessor; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.HttpCodeStatusMapper; -import org.springframework.boot.actuate.health.NamedContributor; -import org.springframework.boot.actuate.health.NamedContributors; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.actuate.health.SimpleHttpCodeStatusMapper; import org.springframework.boot.actuate.health.SimpleStatusAggregator; import org.springframework.boot.actuate.health.StatusAggregator; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.health.contributor.HealthContributors; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; /** @@ -80,14 +68,9 @@ class HealthEndpointConfiguration { } @Bean - @ConditionalOnMissingBean - HealthContributorRegistry healthContributorRegistry(ApplicationContext applicationContext, - HealthEndpointGroups groups, Map healthContributors, - Map reactiveHealthContributors) { - if (ClassUtils.isPresent("reactor.core.publisher.Flux", applicationContext.getClassLoader())) { - healthContributors.putAll(new AdaptedReactiveHealthContributors(reactiveHealthContributors).get()); - } - return new AutoConfiguredHealthContributorRegistry(healthContributors, groups.getNames()); + GroupsHealthContributorNameValidator groupsHealthContributorNameValidator( + ObjectProvider healthEndpointGroups) { + return new GroupsHealthContributorNameValidator(healthEndpointGroups.getIfAvailable()); } @Bean @@ -99,9 +82,11 @@ class HealthEndpointConfiguration { @Bean @ConditionalOnMissingBean - HealthEndpoint healthEndpoint(HealthContributorRegistry registry, HealthEndpointGroups groups, - HealthEndpointProperties properties) { - return new HealthEndpoint(registry, groups, properties.getLogging().getSlowIndicatorThreshold()); + HealthEndpoint healthEndpoint(HealthContributorRegistry halthContributorRegistry, + ObjectProvider reactiveHealthContributorRegistry, + HealthEndpointGroups groups, HealthEndpointProperties properties) { + return new HealthEndpoint(halthContributorRegistry, reactiveHealthContributorRegistry.getIfAvailable(), groups, + properties.getLogging().getSlowIndicatorThreshold()); } @Bean @@ -140,82 +125,6 @@ class HealthEndpointConfiguration { } - /** - * Adapter to expose {@link ReactiveHealthContributor} beans as - * {@link HealthContributor} instances. - */ - private static class AdaptedReactiveHealthContributors { - - private final Map adapted; - - AdaptedReactiveHealthContributors(Map reactiveContributors) { - Map adapted = new LinkedHashMap<>(); - reactiveContributors.forEach((name, contributor) -> adapted.put(name, adapt(contributor))); - this.adapted = Collections.unmodifiableMap(adapted); - } - - private HealthContributor adapt(ReactiveHealthContributor contributor) { - if (contributor instanceof ReactiveHealthIndicator healthIndicator) { - return adapt(healthIndicator); - } - if (contributor instanceof CompositeReactiveHealthContributor healthContributor) { - return adapt(healthContributor); - } - throw new IllegalStateException("Unsupported ReactiveHealthContributor type " + contributor.getClass()); - } - - private HealthIndicator adapt(ReactiveHealthIndicator indicator) { - return new HealthIndicator() { - - @Override - public Health getHealth(boolean includeDetails) { - return indicator.getHealth(includeDetails).block(); - } - - @Override - public Health health() { - return indicator.health().block(); - } - - }; - } - - private CompositeHealthContributor adapt(CompositeReactiveHealthContributor composite) { - return new CompositeHealthContributor() { - - @Override - public Iterator> iterator() { - Iterator> iterator = composite.iterator(); - return new Iterator<>() { - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public NamedContributor next() { - NamedContributor next = iterator.next(); - return NamedContributor.of(next.getName(), adapt(next.getContributor())); - } - - }; - } - - @Override - public HealthContributor getContributor(String name) { - return adapt(composite.getContributor(name)); - } - - }; - } - - Map get() { - return this.adapted; - } - - } - /** * {@link SmartInitializingSingleton} that validates health endpoint group membership, * throwing a {@link NoSuchHealthContributorException} if an included or excluded @@ -264,10 +173,10 @@ class HealthEndpointConfiguration { int pathOffset = 0; Object contributor = this.registry; while (pathOffset < path.length) { - if (!(contributor instanceof NamedContributors)) { + if (!(contributor instanceof HealthContributors)) { return false; } - contributor = ((NamedContributors) contributor).getContributor(path[pathOffset]); + contributor = ((HealthContributors) contributor).getContributor(path[pathOffset]); pathOffset++; } return (contributor != null); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java index 50c4bdfb28d..c1542c81166 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java @@ -16,16 +16,18 @@ package org.springframework.boot.actuate.autoconfigure.health; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; import org.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroups; -import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -45,9 +47,11 @@ class HealthEndpointReactiveWebExtensionConfiguration { @ConditionalOnMissingBean @ConditionalOnBean(HealthEndpoint.class) ReactiveHealthEndpointWebExtension reactiveHealthEndpointWebExtension( - ReactiveHealthContributorRegistry reactiveHealthContributorRegistry, HealthEndpointGroups groups, + ReactiveHealthContributorRegistry reactiveHealthContributorRegistry, + ObjectProvider healthContributorRegistry, HealthEndpointGroups groups, HealthEndpointProperties properties) { - return new ReactiveHealthEndpointWebExtension(reactiveHealthContributorRegistry, groups, + return new ReactiveHealthEndpointWebExtension(reactiveHealthContributorRegistry, + healthContributorRegistry.getIfAvailable(), groups, properties.getLogging().getSlowIndicatorThreshold()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java index 5dcfa7c2a0d..9b3f6d00794 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java @@ -16,9 +16,9 @@ package org.springframework.boot.actuate.autoconfigure.health; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; import org.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure; -import org.springframework.boot.actuate.health.HealthContributorRegistry; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroups; import org.springframework.boot.actuate.health.HealthEndpointWebExtension; @@ -26,6 +26,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -45,8 +47,10 @@ class HealthEndpointWebExtensionConfiguration { @Bean @ConditionalOnMissingBean HealthEndpointWebExtension healthEndpointWebExtension(HealthContributorRegistry healthContributorRegistry, + ObjectProvider reactiveHealthContributorRegistry, HealthEndpointGroups groups, HealthEndpointProperties properties) { - return new HealthEndpointWebExtension(healthContributorRegistry, groups, + return new HealthEndpointWebExtension(healthContributorRegistry, + reactiveHealthContributorRegistry.getIfAvailable(), groups, properties.getLogging().getSlowIndicatorThreshold()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/OnEnabledHealthIndicatorCondition.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/OnEnabledHealthIndicatorCondition.java deleted file mode 100644 index 308f620e4f9..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/OnEnabledHealthIndicatorCondition.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.health; - -import org.springframework.boot.actuate.autoconfigure.OnEndpointElementCondition; -import org.springframework.context.annotation.Condition; - -/** - * {@link Condition} that checks if a health indicator is enabled. - * - * @author Stephane Nicoll - */ -class OnEnabledHealthIndicatorCondition extends OnEndpointElementCondition { - - OnEnabledHealthIndicatorCondition() { - super("management.health.", ConditionalOnEnabledHealthIndicator.class); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ReactiveHealthEndpointConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ReactiveHealthEndpointConfiguration.java deleted file mode 100644 index 1c1fbffb5a5..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ReactiveHealthEndpointConfiguration.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.health; - -import java.util.LinkedHashMap; -import java.util.Map; - -import reactor.core.publisher.Flux; - -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthEndpoint; -import org.springframework.boot.actuate.health.HealthEndpointGroups; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Configuration for reactive {@link HealthEndpoint} infrastructure beans. - * - * @author Phillip Webb - * @see HealthEndpointAutoConfiguration - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass(Flux.class) -@ConditionalOnBean(HealthEndpoint.class) -class ReactiveHealthEndpointConfiguration { - - @Bean - @ConditionalOnMissingBean - ReactiveHealthContributorRegistry reactiveHealthContributorRegistry( - Map healthContributors, - Map reactiveHealthContributors, HealthEndpointGroups groups) { - Map allContributors = new LinkedHashMap<>(reactiveHealthContributors); - healthContributors.forEach((name, contributor) -> allContributors.computeIfAbsent(name, - (key) -> ReactiveHealthContributor.adapt(contributor))); - return new AutoConfiguredReactiveHealthContributorRegistry(allContributors, groups.getNames()); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfiguration.java index aebba3cba5c..a66595ab34d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfiguration.java @@ -16,13 +16,14 @@ package org.springframework.boot.actuate.autoconfigure.ssl; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.ssl.SslHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.Health; import org.springframework.boot.info.SslInfo; import org.springframework.boot.ssl.SslBundles; import org.springframework.context.annotation.Bean; @@ -33,7 +34,9 @@ import org.springframework.context.annotation.Bean; * @author Jonatan Ivanov * @since 3.4.0 */ -@AutoConfiguration(before = HealthContributorAutoConfiguration.class) +@AutoConfiguration( + beforeName = "org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration") +@ConditionalOnClass(Health.class) @ConditionalOnEnabledHealthIndicator("ssl") @EnableConfigurationProperties(SslHealthIndicatorProperties.class) public class SslHealthContributorAutoConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfiguration.java index 24e5d77c093..59d50cfe047 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfiguration.java @@ -16,13 +16,14 @@ package org.springframework.boot.actuate.autoconfigure.system; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.Health; import org.springframework.context.annotation.Bean; /** @@ -33,7 +34,9 @@ import org.springframework.context.annotation.Bean; * @author Andy Wilkinson * @since 2.0.0 */ -@AutoConfiguration(before = HealthContributorAutoConfiguration.class) +@AutoConfiguration( + beforeName = "org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration") +@ConditionalOnClass(Health.class) @ConditionalOnEnabledHealthIndicator("diskspace") @EnableConfigurationProperties(DiskSpaceHealthIndicatorProperties.class) public class DiskSpaceHealthContributorAutoConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index cf5ae15b4aa..ac80acd90ec 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -11,7 +11,6 @@ org.springframework.boot.actuate.autoconfigure.endpoint.jackson.JacksonEndpointA org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAutoConfiguration -org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfigurationTests.java index 390ce9f778e..f13f1291e09 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfigurationTests.java @@ -23,6 +23,7 @@ import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicat import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration; import org.springframework.boot.availability.ApplicationAvailability; +import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -60,6 +61,13 @@ class AvailabilityProbesAutoConfigurationTests { .run(this::hasProbesBeans); } + @Test + void probesWhenPropertyEnabledButNoHealthDependencyDoesNotAddBeans() { + this.contextRunner.withPropertyValues("management.endpoint.health.probes.enabled=true") + .withClassLoader(new FilteredClassLoader("org.springframework.boot.health")) + .run(this::doesNotHaveProbeBeans); + } + @Test void probesWhenKubernetesAndPropertyDisabledAddsNotBeans() { this.contextRunner diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAccessIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAccessIntegrationTests.java index 2aa0cf90c38..d220a977dce 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAccessIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAccessIntegrationTests.java @@ -25,13 +25,13 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpoint; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.util.StringUtils; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointIntegrationTests.java index 19617908644..7ac74867d91 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointIntegrationTests.java @@ -31,11 +31,12 @@ import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository; import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.context.ShutdownEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.web.exchanges.InMemoryHttpExchangeRepository; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -53,7 +54,8 @@ class JmxEndpointIntegrationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, EndpointAutoConfiguration.class, - JmxEndpointAutoConfiguration.class, HealthContributorAutoConfiguration.class)) + JmxEndpointAutoConfiguration.class, HealthContributorRegistryAutoConfiguration.class, + HealthContributorAutoConfiguration.class)) .withUserConfiguration(HttpExchangeRepositoryConfiguration.class, AuditEventRepositoryConfiguration.class) .withPropertyValues("spring.jmx.enabled=true") .withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class, diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistryTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistryTests.java deleted file mode 100644 index daab69fe6fa..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistryTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.health; - -import java.util.Arrays; -import java.util.Collections; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthContributorRegistry; - -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link AutoConfiguredHealthContributorRegistry}. - * - * @author Phillip Webb - */ -class AutoConfiguredHealthContributorRegistryTests { - - @Test - void createWhenContributorsClashesWithGroupNameThrowsException() { - assertThatIllegalStateException() - .isThrownBy(() -> new AutoConfiguredHealthContributorRegistry( - Collections.singletonMap("boot", mock(HealthContributor.class)), Arrays.asList("spring", "boot"))) - .withMessage("HealthContributor with name \"boot\" clashes with group"); - } - - @Test - void registerContributorWithGroupNameThrowsException() { - HealthContributorRegistry registry = new AutoConfiguredHealthContributorRegistry(Collections.emptyMap(), - Arrays.asList("spring", "boot")); - assertThatIllegalStateException() - .isThrownBy(() -> registry.registerContributor("spring", mock(HealthContributor.class))) - .withMessage("HealthContributor with name \"spring\" clashes with group"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroupsTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroupsTests.java index 169c23fd4b4..5b3715a3356 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroupsTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroupsTests.java @@ -31,10 +31,10 @@ import org.springframework.boot.actuate.health.HealthEndpointGroups; import org.springframework.boot.actuate.health.HttpCodeStatusMapper; import org.springframework.boot.actuate.health.SimpleHttpCodeStatusMapper; import org.springframework.boot.actuate.health.SimpleStatusAggregator; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.actuate.health.StatusAggregator; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistryTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistryTests.java deleted file mode 100644 index 372d29e259b..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredReactiveHealthContributorRegistryTests.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.health; - -import java.util.Arrays; -import java.util.Collections; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.health.ReactiveHealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; - -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link AutoConfiguredReactiveHealthContributorRegistry}. - * - * @author Phillip Webb - */ -class AutoConfiguredReactiveHealthContributorRegistryTests { - - @Test - void createWhenContributorsClashesWithGroupNameThrowsException() { - assertThatIllegalStateException() - .isThrownBy(() -> new AutoConfiguredReactiveHealthContributorRegistry( - Collections.singletonMap("boot", mock(ReactiveHealthContributor.class)), - Arrays.asList("spring", "boot"))) - .withMessage("ReactiveHealthContributor with name \"boot\" clashes with group"); - } - - @Test - void registerContributorWithGroupNameThrowsException() { - ReactiveHealthContributorRegistry registry = new AutoConfiguredReactiveHealthContributorRegistry( - Collections.emptyMap(), Arrays.asList("spring", "boot")); - assertThatIllegalStateException() - .isThrownBy(() -> registry.registerContributor("spring", mock(ReactiveHealthContributor.class))) - .withMessage("ReactiveHealthContributor with name \"spring\" clashes with group"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java index 8fd7325b0c9..f5f20f912ca 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java @@ -30,26 +30,30 @@ import org.springframework.boot.actuate.endpoint.ApiVersion; import org.springframework.boot.actuate.endpoint.SecurityContext; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.DefaultHealthContributorRegistry; -import org.springframework.boot.actuate.health.DefaultReactiveHealthContributorRegistry; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthComponent; -import org.springframework.boot.actuate.health.HealthContributorRegistry; +import org.springframework.boot.actuate.health.CompositeHealthDescriptor; +import org.springframework.boot.actuate.health.HealthDescriptor; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroups; import org.springframework.boot.actuate.health.HealthEndpointGroupsPostProcessor; import org.springframework.boot.actuate.health.HealthEndpointWebExtension; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.HttpCodeStatusMapper; -import org.springframework.boot.actuate.health.NamedContributor; -import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; +import org.springframework.boot.actuate.health.IndicatedHealthDescriptor; import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.actuate.health.StatusAggregator; -import org.springframework.boot.actuate.health.SystemHealth; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributors; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributors; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Status; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.DefaultReactiveHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; @@ -74,14 +78,14 @@ class HealthEndpointAutoConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withUserConfiguration(HealthIndicatorsConfiguration.class) - .withConfiguration( - AutoConfigurations.of(HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HealthContributorAutoConfiguration.class)); private final ReactiveWebApplicationContextRunner reactiveContextRunner = new ReactiveWebApplicationContextRunner() .withUserConfiguration(HealthIndicatorsConfiguration.class) - .withConfiguration( - AutoConfigurations.of(HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HealthContributorAutoConfiguration.class, + WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); @Test void runWhenHealthEndpointIsDisabledDoesNotCreateBeans() { @@ -89,9 +93,7 @@ class HealthEndpointAutoConfigurationTests { assertThat(context).doesNotHaveBean(StatusAggregator.class); assertThat(context).doesNotHaveBean(HttpCodeStatusMapper.class); assertThat(context).doesNotHaveBean(HealthEndpointGroups.class); - assertThat(context).doesNotHaveBean(HealthContributorRegistry.class); assertThat(context).doesNotHaveBean(HealthEndpoint.class); - assertThat(context).doesNotHaveBean(ReactiveHealthContributorRegistry.class); assertThat(context).doesNotHaveBean(HealthEndpointWebExtension.class); assertThat(context).doesNotHaveBean(ReactiveHealthEndpointWebExtension.class); }); @@ -192,8 +194,8 @@ class HealthEndpointAutoConfigurationTests { void runCreatesHealthContributorRegistryContainingHealthBeans() { this.contextRunner.run((context) -> { HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); - Object[] names = registry.stream().map(NamedContributor::getName).toArray(); - assertThat(names).containsExactlyInAnyOrder("simple", "additional", "ping", "reactive"); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); + assertThat(names).containsExactlyInAnyOrder("simple", "additional", "ping"); }); } @@ -202,7 +204,7 @@ class HealthEndpointAutoConfigurationTests { ClassLoader classLoader = new FilteredClassLoader(Mono.class, Flux.class); this.contextRunner.withClassLoader(classLoader).run((context) -> { HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); - Object[] names = registry.stream().map(NamedContributor::getName).toArray(); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); assertThat(names).containsExactlyInAnyOrder("simple", "additional", "ping"); }); } @@ -211,7 +213,7 @@ class HealthEndpointAutoConfigurationTests { void runWhenHasHealthContributorRegistryBeanDoesNotCreateAdditionalRegistry() { this.contextRunner.withUserConfiguration(HealthContributorRegistryConfiguration.class).run((context) -> { HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); - Object[] names = registry.stream().map(NamedContributor::getName).toArray(); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); assertThat(names).isEmpty(); }); } @@ -220,8 +222,8 @@ class HealthEndpointAutoConfigurationTests { void runCreatesHealthEndpoint() { this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> { HealthEndpoint endpoint = context.getBean(HealthEndpoint.class); - Health health = (Health) endpoint.healthForPath("simple"); - assertThat(health.getDetails()).containsEntry("counter", 42); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) endpoint.healthForPath("simple"); + assertThat(descriptor.getDetails()).containsEntry("counter", 42); }); } @@ -234,11 +236,12 @@ class HealthEndpointAutoConfigurationTests { } @Test - void runCreatesReactiveHealthContributorRegistryContainingAdaptedBeans() { + void runCreatesReactiveHealthContributorRegistryContainingReactiveHealthBeans() { this.reactiveContextRunner.run((context) -> { - ReactiveHealthContributorRegistry registry = context.getBean(ReactiveHealthContributorRegistry.class); - Object[] names = registry.stream().map(NamedContributor::getName).toArray(); - assertThat(names).containsExactlyInAnyOrder("simple", "additional", "reactive", "ping"); + ReactiveHealthContributorRegistry reactiveRegistry = context + .getBean(ReactiveHealthContributorRegistry.class); + Object[] names = reactiveRegistry.stream().map(ReactiveHealthContributors.Entry::name).toArray(); + assertThat(names).containsExactlyInAnyOrder("reactive"); }); } @@ -247,7 +250,7 @@ class HealthEndpointAutoConfigurationTests { this.reactiveContextRunner.withUserConfiguration(ReactiveHealthContributorRegistryConfiguration.class) .run((context) -> { ReactiveHealthContributorRegistry registry = context.getBean(ReactiveHealthContributorRegistry.class); - Object[] names = registry.stream().map(NamedContributor::getName).toArray(); + Object[] names = registry.stream().map(ReactiveHealthContributors.Entry::name).toArray(); assertThat(names).isEmpty(); }); } @@ -256,11 +259,11 @@ class HealthEndpointAutoConfigurationTests { void runCreatesHealthEndpointWebExtension() { this.contextRunner.run((context) -> { HealthEndpointWebExtension webExtension = context.getBean(HealthEndpointWebExtension.class); - WebEndpointResponse response = webExtension.health(ApiVersion.V3, + WebEndpointResponse response = webExtension.health(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, true, "simple"); - Health health = (Health) response.getBody(); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) response.getBody(); assertThat(response.getStatus()).isEqualTo(200); - assertThat(health.getDetails()).containsEntry("counter", 42); + assertThat(descriptor.getDetails()).containsEntry("counter", 42); }); } @@ -268,7 +271,7 @@ class HealthEndpointAutoConfigurationTests { void runWhenHasHealthEndpointWebExtensionBeanDoesNotCreateExtraHealthEndpointWebExtension() { this.contextRunner.withUserConfiguration(HealthEndpointWebExtensionConfiguration.class).run((context) -> { HealthEndpointWebExtension webExtension = context.getBean(HealthEndpointWebExtension.class); - WebEndpointResponse response = webExtension.health(ApiVersion.V3, + WebEndpointResponse response = webExtension.health(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, true, "simple"); assertThat(response).isNull(); }); @@ -278,10 +281,10 @@ class HealthEndpointAutoConfigurationTests { void runCreatesReactiveHealthEndpointWebExtension() { this.reactiveContextRunner.run((context) -> { ReactiveHealthEndpointWebExtension webExtension = context.getBean(ReactiveHealthEndpointWebExtension.class); - Mono> response = webExtension.health(ApiVersion.V3, + Mono> response = webExtension.health(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, true, "simple"); - Health health = (Health) (response.block().getBody()); - assertThat(health.getDetails()).containsEntry("counter", 42); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) (response.block().getBody()); + assertThat(descriptor.getDetails()).containsEntry("counter", 42); }); } @@ -291,7 +294,7 @@ class HealthEndpointAutoConfigurationTests { .run((context) -> { ReactiveHealthEndpointWebExtension webExtension = context .getBean(ReactiveHealthEndpointWebExtension.class); - Mono> response = webExtension.health(ApiVersion.V3, + Mono> response = webExtension.health(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, true, "simple"); assertThat(response).isNull(); }); @@ -312,12 +315,12 @@ class HealthEndpointAutoConfigurationTests { void runWithIndicatorsInParentContextFindsIndicators() { new ApplicationContextRunner().withUserConfiguration(HealthIndicatorsConfiguration.class) .run((parent) -> new WebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HealthContributorAutoConfiguration.class)) .withParent(parent) .run((context) -> { - HealthComponent health = context.getBean(HealthEndpoint.class).health(); - Map components = ((SystemHealth) health).getComponents(); + HealthDescriptor descriptor = context.getBean(HealthEndpoint.class).health(); + Map components = ((CompositeHealthDescriptor) descriptor).getComponents(); assertThat(components).containsKeys("additional", "ping", "simple"); })); } @@ -326,17 +329,24 @@ class HealthEndpointAutoConfigurationTests { void runWithReactiveContextAndIndicatorsInParentContextFindsIndicators() { new ApplicationContextRunner().withUserConfiguration(HealthIndicatorsConfiguration.class) .run((parent) -> new ReactiveWebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - EndpointAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HealthContributorAutoConfiguration.class, + WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)) .withParent(parent) .run((context) -> { - HealthComponent health = context.getBean(HealthEndpoint.class).health(); - Map components = ((SystemHealth) health).getComponents(); + HealthDescriptor descriptor = context.getBean(HealthEndpoint.class).health(); + Map components = ((CompositeHealthDescriptor) descriptor).getComponents(); assertThat(components).containsKeys("additional", "ping", "simple"); })); } + @Test + void runWithClashingGroupNameThrowsException() { + this.contextRunner.withPropertyValues("management.endpoint.health.group.ping.include=*") + .run((context) -> assertThat(context).getFailure() + .hasMessageContaining("HealthContributor with name \"ping\" clashes with group")); + } + @Configuration(proxyBeanMethods = false) static class HealthIndicatorsConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/NoSuchHealthContributorFailureAnalyzerTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/NoSuchHealthContributorFailureAnalyzerTests.java index 692c7c85a30..05e55c0a18d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/NoSuchHealthContributorFailureAnalyzerTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/NoSuchHealthContributorFailureAnalyzerTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointConfiguration.HealthEndpointGroupMembershipValidator.NoSuchHealthContributorException; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.diagnostics.FailureAnalysis; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -34,8 +35,8 @@ import static org.assertj.core.api.Assertions.assertThat; */ class NoSuchHealthContributorFailureAnalyzerTests { - private final ApplicationContextRunner runner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)); + private final ApplicationContextRunner runner = new ApplicationContextRunner().withConfiguration(AutoConfigurations + .of(HealthEndpointAutoConfiguration.class, HealthContributorRegistryAutoConfiguration.class)); @Test void analyzesMissingRequiredConfiguration() throws Throwable { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfigurationTests.java index ced8bfcea97..9bb5a9c1a0a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslHealthContributorAutoConfigurationTests.java @@ -22,12 +22,13 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.ssl.SslHealthContributorAutoConfigurationTests.CustomSslInfoConfiguration.CustomSslHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.actuate.ssl.SslHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.info.SslInfo; import org.springframework.boot.info.SslInfo.CertificateChainInfo; import org.springframework.boot.ssl.SslBundles; @@ -47,8 +48,8 @@ import static org.assertj.core.api.Assertions.assertThat; class SslHealthContributorAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(SslHealthContributorAutoConfiguration.class, SslAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(SslHealthContributorAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, SslAutoConfiguration.class)) .withPropertyValues("server.ssl.bundle=ssltest", "spring.ssl.bundle.jks.ssltest.keystore.location=classpath:test.jks"); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfigurationTests.java index 236c83a9abe..5ffe2fc933b 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfigurationTests.java @@ -18,9 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.system; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.util.unit.DataSize; diff --git a/spring-boot-project/spring-boot-actuator-docs/build.gradle b/spring-boot-project/spring-boot-actuator-docs/build.gradle index 1fbd6c2c1c0..12ce9e4274b 100644 --- a/spring-boot-project/spring-boot-actuator-docs/build.gradle +++ b/spring-boot-project/spring-boot-actuator-docs/build.gradle @@ -26,6 +26,7 @@ dependencies { testImplementation(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) testImplementation(project(":spring-boot-project:spring-boot-cache")) testImplementation(project(":spring-boot-project:spring-boot-flyway")) + testImplementation(project(":spring-boot-project:spring-boot-health")) testImplementation(project(":spring-boot-project:spring-boot-http-converter")) testImplementation(project(":spring-boot-project:spring-boot-integration")) testImplementation(project(":spring-boot-project:spring-boot-jackson")) diff --git a/spring-boot-project/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/docs/health/HealthEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/docs/health/HealthEndpointDocumentationTests.java index 67e0521e23a..07a739b23f9 100644 --- a/spring-boot-project/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/docs/health/HealthEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/docs/health/HealthEndpointDocumentationTests.java @@ -29,23 +29,24 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.docs.MockMvcEndpointDocumentationTests; import org.springframework.boot.actuate.endpoint.SecurityContext; import org.springframework.boot.actuate.health.AdditionalHealthEndpointPath; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.DefaultHealthContributorRegistry; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthContributorRegistry; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroup; import org.springframework.boot.actuate.health.HealthEndpointGroups; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.HttpCodeStatusMapper; import org.springframework.boot.actuate.health.SimpleHttpCodeStatusMapper; import org.springframework.boot.actuate.health.SimpleStatusAggregator; import org.springframework.boot.actuate.health.StatusAggregator; import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.jdbc.actuate.health.DataSourceHealthIndicator; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorNameGenerator; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorRegistry; import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; +import org.springframework.boot.jdbc.health.DataSourceHealthIndicator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; @@ -105,11 +106,12 @@ class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentationTests static class TestConfiguration { @Bean - HealthEndpoint healthEndpoint(Map healthContributors) { - HealthContributorRegistry registry = new DefaultHealthContributorRegistry(healthContributors); + HealthEndpoint healthEndpoint(Map contributors) { + HealthContributorRegistry registry = new DefaultHealthContributorRegistry(null, + HealthContributorNameGenerator.withoutStandardSuffixes().registrar(contributors)); HealthEndpointGroup primary = new TestHealthEndpointGroup(); HealthEndpointGroups groups = HealthEndpointGroups.of(primary, Collections.emptyMap()); - return new HealthEndpoint(registry, groups, null); + return new HealthEndpoint(registry, null, groups, null); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-integration-tests/build.gradle b/spring-boot-project/spring-boot-actuator-integration-tests/build.gradle index 82ae64a03de..ec2cda31433 100644 --- a/spring-boot-project/spring-boot-actuator-integration-tests/build.gradle +++ b/spring-boot-project/spring-boot-actuator-integration-tests/build.gradle @@ -25,6 +25,7 @@ description = "Spring Boot Actuator Integration Tests" dependencies { testImplementation(project(":spring-boot-project:spring-boot-actuator")) testImplementation(project(":spring-boot-project:spring-boot-autoconfigure")) + testImplementation(project(":spring-boot-project:spring-boot-health")) testImplementation(project(":spring-boot-project:spring-boot-http-converter")) testImplementation(project(":spring-boot-project:spring-boot-jackson")) testImplementation(project(":spring-boot-project:spring-boot-jersey")) diff --git a/spring-boot-project/spring-boot-actuator-integration-tests/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebIntegrationTests.java b/spring-boot-project/spring-boot-actuator-integration-tests/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebIntegrationTests.java index 1c4dd2d1c75..c221d3ed112 100644 --- a/spring-boot-project/spring-boot-actuator-integration-tests/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-integration-tests/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebIntegrationTests.java @@ -17,16 +17,28 @@ package org.springframework.boot.actuate.health; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.Map; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import reactor.core.publisher.Mono; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.endpoint.ApiVersion; import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorNameGenerator; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.CompositeReactiveHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.DefaultReactiveHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -199,8 +211,7 @@ class HealthEndpointWebIntegrationTests { } } - private > R getContributorRegistry(ApplicationContext context, - Class registryType) { + private R getContributorRegistry(ApplicationContext context, Class registryType) { return context.getBeanProvider(registryType).getIfAvailable(); } @@ -241,41 +252,44 @@ class HealthEndpointWebIntegrationTests { static class TestConfiguration { @Bean - HealthContributorRegistry healthContributorRegistry(Map healthContributorBeans) { - return new DefaultHealthContributorRegistry(healthContributorBeans); + HealthContributorRegistry healthContributorRegistry(Map contributorBeans) { + return new DefaultHealthContributorRegistry(null, + HealthContributorNameGenerator.withoutStandardSuffixes().registrar(contributorBeans)); } @Bean @ConditionalOnWebApplication(type = Type.REACTIVE) ReactiveHealthContributorRegistry reactiveHealthContributorRegistry( - Map healthContributorBeans, - Map reactiveHealthContributorBeans) { - Map allIndicators = new LinkedHashMap<>(reactiveHealthContributorBeans); - healthContributorBeans.forEach((name, contributor) -> allIndicators.computeIfAbsent(name, - (key) -> ReactiveHealthContributor.adapt(contributor))); - return new DefaultReactiveHealthContributorRegistry(allIndicators); + Map contributorBeans) { + return new DefaultReactiveHealthContributorRegistry(null, + HealthContributorNameGenerator.withoutStandardSuffixes().registrar(contributorBeans)); } @Bean HealthEndpoint healthEndpoint(HealthContributorRegistry healthContributorRegistry, + ObjectProvider reactiveHealthContributorRegistry, HealthEndpointGroups healthEndpointGroups) { - return new HealthEndpoint(healthContributorRegistry, healthEndpointGroups, null); + return new HealthEndpoint(healthContributorRegistry, reactiveHealthContributorRegistry.getIfAvailable(), + healthEndpointGroups, null); } @Bean @ConditionalOnWebApplication(type = Type.SERVLET) HealthEndpointWebExtension healthWebEndpointExtension(HealthContributorRegistry healthContributorRegistry, + ObjectProvider reactiveHealthContributorRegistry, HealthEndpointGroups healthEndpointGroups) { - return new HealthEndpointWebExtension(healthContributorRegistry, healthEndpointGroups, null); + return new HealthEndpointWebExtension(healthContributorRegistry, + reactiveHealthContributorRegistry.getIfAvailable(), healthEndpointGroups, null); } @Bean @ConditionalOnWebApplication(type = Type.REACTIVE) ReactiveHealthEndpointWebExtension reactiveHealthWebEndpointExtension( ReactiveHealthContributorRegistry reactiveHealthContributorRegistry, + ObjectProvider healthContributorRegistry, HealthEndpointGroups healthEndpointGroups) { - return new ReactiveHealthEndpointWebExtension(reactiveHealthContributorRegistry, healthEndpointGroups, - null); + return new ReactiveHealthEndpointWebExtension(reactiveHealthContributorRegistry, + healthContributorRegistry.getIfAvailable(), healthEndpointGroups, null); } @Bean diff --git a/spring-boot-project/spring-boot-actuator/build.gradle b/spring-boot-project/spring-boot-actuator/build.gradle index 2cf3010fe7d..1757289a000 100644 --- a/spring-boot-project/spring-boot-actuator/build.gradle +++ b/spring-boot-project/spring-boot-actuator/build.gradle @@ -27,6 +27,7 @@ description = "Spring Boot Actuator" dependencies { api(project(":spring-boot-project:spring-boot")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-http-converter")) optional(project(":spring-boot-project:spring-boot-jsonb")) optional(project(":spring-boot-project:spring-boot-validation")) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java index 8472ae50144..a0660708b54 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java @@ -21,12 +21,12 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.availability.AvailabilityState; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.Assert; /** @@ -76,7 +76,7 @@ public class AvailabilityStateHealthIndicator extends AbstractHealthIndicator { } @Override - protected void doHealthCheck(Builder builder) throws Exception { + protected void doHealthCheck(Health.Builder builder) throws Exception { AvailabilityState state = getState(this.applicationAvailability); Status status = this.statusMappings.get(state); if (status == null) { diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicator.java index 7bbb463c1d9..1b099ff244b 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicator.java @@ -16,11 +16,11 @@ package org.springframework.boot.actuate.availability; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.availability.AvailabilityState; import org.springframework.boot.availability.LivenessState; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; /** * A {@link HealthIndicator} that checks the {@link LivenessState} of the application. diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicator.java index 4e5ef1c879d..0d3b53f88b3 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicator.java @@ -16,11 +16,11 @@ package org.springframework.boot.actuate.availability; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.availability.AvailabilityState; import org.springframework.boot.availability.ReadinessState; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; /** * A {@link HealthIndicator} that checks the {@link ReadinessState} of the application. diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapter.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapter.java deleted file mode 100644 index 18956ee063e..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapter.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Iterator; - -import org.springframework.util.Assert; - -/** - * Adapts a {@link CompositeHealthContributor} to a - * {@link CompositeReactiveHealthContributor} so that it can be safely invoked in a - * reactive environment. - * - * @author Phillip Webb - * @see ReactiveHealthContributor#adapt(HealthContributor) - */ -class CompositeHealthContributorReactiveAdapter implements CompositeReactiveHealthContributor { - - private final CompositeHealthContributor delegate; - - CompositeHealthContributorReactiveAdapter(CompositeHealthContributor delegate) { - Assert.notNull(delegate, "'delegate' must not be null"); - this.delegate = delegate; - } - - @Override - public Iterator> iterator() { - Iterator> iterator = this.delegate.iterator(); - return new Iterator<>() { - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public NamedContributor next() { - NamedContributor namedContributor = iterator.next(); - return NamedContributor.of(namedContributor.getName(), - ReactiveHealthContributor.adapt(namedContributor.getContributor())); - } - - }; - } - - @Override - public ReactiveHealthContributor getContributor(String name) { - HealthContributor contributor = this.delegate.getContributor(name); - return (contributor != null) ? ReactiveHealthContributor.adapt(contributor) : null; - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealth.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthDescriptor.java similarity index 53% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealth.java rename to spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthDescriptor.java index bbfb6c9a82e..aa6650f0ddb 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealth.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthDescriptor.java @@ -21,37 +21,32 @@ import java.util.TreeMap; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.boot.actuate.endpoint.ApiVersion; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.Assert; /** - * A {@link HealthComponent} that is composed of other {@link HealthComponent} instances. - * Used to provide a unified view of related components. For example, a database health - * indicator may be a composite containing the {@link Health} of each datasource - * connection. + * Description of health that is composed of other {@link HealthDescriptor health + * descriptors}. * * @author Phillip Webb - * @since 2.2.0 + * @since 4.0.0 */ -public class CompositeHealth extends HealthComponent { +public sealed class CompositeHealthDescriptor extends HealthDescriptor permits SystemHealthDescriptor { + + private final ApiVersion apiVersion; private final Status status; - private final Map components; + private final Map components; - private final Map details; - - CompositeHealth(ApiVersion apiVersion, Status status, Map components) { + CompositeHealthDescriptor(ApiVersion apiVersion, Status status, Map components) { + Assert.notNull(apiVersion, "'apiVersion' must not be null"); Assert.notNull(status, "'status' must not be null"); + this.apiVersion = apiVersion; this.status = status; - this.components = (apiVersion != ApiVersion.V3) ? null : sort(components); - this.details = (apiVersion != ApiVersion.V2) ? null : sort(components); - } - - private Map sort(Map components) { - return (components != null) ? new TreeMap<>(components) : components; + this.components = (components != null) ? new TreeMap<>(components) : components; } @Override @@ -60,14 +55,13 @@ public class CompositeHealth extends HealthComponent { } @JsonInclude(Include.NON_EMPTY) - public Map getComponents() { - return this.components; + public Map getComponents() { + return (this.apiVersion == ApiVersion.V3) ? this.components : null; } @JsonInclude(Include.NON_EMPTY) - @JsonProperty - public Map getDetails() { - return this.details; + public Map getDetails() { + return (this.apiVersion == ApiVersion.V2) ? this.components : null; } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Contributor.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Contributor.java new file mode 100644 index 00000000000..c7591156126 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Contributor.java @@ -0,0 +1,196 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.health; + +import java.util.Iterator; + +import reactor.core.publisher.Mono; + +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributors; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; +import org.springframework.util.StringUtils; + +/** + * Allows {@link HealthEndpointSupport} to access blocking or reactive contributors and + * registries in a uniform way. + * + * @param the health type + * @param the descriptor type + * @author Phillip Webb + */ +sealed interface Contributor extends Iterable> { + + /** + * Return if this contributor is a composite and may have children. + * @return if the contributor is a composite + */ + boolean isComposite(); + + /** + * Get the child with the given name. Must only be called if {@link #isComposite()} + * returns {@code true}. + * @param name the child name + * @return the child or {@code null} + */ + Contributor getChild(String name); + + /** + * Get the health. Must only be called if {@link #isComposite()} returns + * {@code false}. + * @param includeDetails if details are to be included. + * @return the health + */ + D getDescriptor(boolean includeDetails); + + /** + * Return an identifier for logging purposes. + * @param name the name if known + * @return an identifier + */ + default String getIdentifier(String name) { + String className = getContributorClassName(); + return (!StringUtils.hasLength(name)) ? className : className + " (" + name + ")"; + } + + /** + * Return the class name of the underlying contributor. + * @return the contributor class name + */ + String getContributorClassName(); + + /** + * Factory method to create a blocking {@link Contributor} from the given registries. + * @param registry the source registry + * @param fallbackRegistry the fallback registry or {@code null} + * @return a new {@link Contributor} + */ + static Blocking blocking(HealthContributorRegistry registry, ReactiveHealthContributorRegistry fallbackRegistry) { + return new Blocking((fallbackRegistry != null) + ? HealthContributors.of(registry, fallbackRegistry.asHealthContributors()) : registry); + } + + /** + * Factory method to create a reactive {@link Contributor} from the given registries. + * @param registry the registry + * @param fallbackRegistry the fallback registry or {@code null} + * @return a new {@link Contributor} + */ + static Reactive reactive(ReactiveHealthContributorRegistry registry, HealthContributorRegistry fallbackRegistry) { + return new Reactive((fallbackRegistry != null) + ? ReactiveHealthContributors.of(registry, ReactiveHealthContributors.adapt(fallbackRegistry)) + : registry); + } + + /** + * A child consisting of a name and a contributor. + * + * @param the health type + * @param the descriptor type + * @param name the child name + * @param contributor the contributor + */ + record Child(String name, Contributor contributor) { + + } + + /** + * {@link Contributor} to adapt the blocking {@link HealthContributor} and + * {@link HealthContributors} types. + * + * @param contributor the underlying contributor + */ + record Blocking(Object contributor) implements Contributor { + + @Override + public boolean isComposite() { + return contributor() instanceof HealthContributors; + } + + @Override + public Blocking getChild(String name) { + HealthContributor child = ((HealthContributors) contributor()).getContributor(name); + return (child != null) ? new Blocking(child) : null; + } + + @Override + public Iterator> iterator() { + return ((HealthContributors) contributor()).stream() + .map((entry) -> new Child<>(entry.name(), new Blocking(entry.contributor()))) + .iterator(); + } + + @Override + public HealthDescriptor getDescriptor(boolean includeDetails) { + Health health = ((HealthIndicator) contributor()).health(includeDetails); + return (health != null) ? new IndicatedHealthDescriptor(health) : null; + } + + @Override + public String getContributorClassName() { + return contributor().getClass().getName(); + } + + } + + /** + * {@link Contributor} to adapt the reactive {@link ReactiveHealthContributor} and + * {@link ReactiveHealthContributors} types. + * + * @param contributor the underlying contributor + */ + record Reactive( + Object contributor) implements Contributor, Mono> { + + @Override + public boolean isComposite() { + return contributor() instanceof ReactiveHealthContributors; + } + + @Override + public Reactive getChild(String name) { + ReactiveHealthContributor child = ((ReactiveHealthContributors) contributor()).getContributor(name); + return (child != null) ? new Reactive(child) : null; + } + + @Override + public Iterator, Mono>> iterator() { + return ((ReactiveHealthContributors) contributor()).stream() + .map((entry) -> new Child<>(entry.name(), new Reactive(entry.contributor()))) + .iterator(); + } + + @Override + public Mono getDescriptor(boolean includeDetails) { + Mono health = ((ReactiveHealthIndicator) this.contributor).health(includeDetails); + return health.map(IndicatedHealthDescriptor::new); + } + + @Override + public String getContributorClassName() { + return contributor().getClass().getName(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultContributorRegistry.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultContributorRegistry.java deleted file mode 100644 index 9bff84dd6db..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultContributorRegistry.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Function; - -import org.springframework.util.Assert; - -/** - * Default {@link ContributorRegistry} implementation. - * - * @param the health contributor type - * @author Phillip Webb - * @see DefaultHealthContributorRegistry - * @see DefaultReactiveHealthContributorRegistry - */ -class DefaultContributorRegistry implements ContributorRegistry { - - private final Function nameFactory; - - private final Object monitor = new Object(); - - private volatile Map contributors; - - DefaultContributorRegistry() { - this(Collections.emptyMap()); - } - - DefaultContributorRegistry(Map contributors) { - this(contributors, HealthContributorNameFactory.INSTANCE); - } - - DefaultContributorRegistry(Map contributors, Function nameFactory) { - Assert.notNull(contributors, "'contributors' must not be null"); - Assert.notNull(nameFactory, "'nameFactory' must not be null"); - this.nameFactory = nameFactory; - Map namedContributors = new LinkedHashMap<>(); - contributors.forEach((name, contributor) -> namedContributors.put(nameFactory.apply(name), contributor)); - this.contributors = Collections.unmodifiableMap(namedContributors); - } - - @Override - public void registerContributor(String name, C contributor) { - Assert.notNull(name, "'name' must not be null"); - Assert.notNull(contributor, "'contributor' must not be null"); - String adaptedName = this.nameFactory.apply(name); - synchronized (this.monitor) { - Assert.state(!this.contributors.containsKey(adaptedName), - () -> "A contributor named \"" + adaptedName + "\" has already been registered"); - Map contributors = new LinkedHashMap<>(this.contributors); - contributors.put(adaptedName, contributor); - this.contributors = Collections.unmodifiableMap(contributors); - } - } - - @Override - public C unregisterContributor(String name) { - Assert.notNull(name, "'name' must not be null"); - String adaptedName = this.nameFactory.apply(name); - synchronized (this.monitor) { - C unregistered = this.contributors.get(adaptedName); - if (unregistered != null) { - Map contributors = new LinkedHashMap<>(this.contributors); - contributors.remove(adaptedName); - this.contributors = Collections.unmodifiableMap(contributors); - } - return unregistered; - } - } - - @Override - public C getContributor(String name) { - return this.contributors.get(name); - } - - @Override - public Iterator> iterator() { - Iterator> iterator = this.contributors.entrySet().iterator(); - return new Iterator<>() { - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public NamedContributor next() { - Entry entry = iterator.next(); - return NamedContributor.of(entry.getKey(), entry.getValue()); - } - - }; - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultHealthContributorRegistry.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultHealthContributorRegistry.java deleted file mode 100644 index fa09a8b1327..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultHealthContributorRegistry.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Map; -import java.util.function.Function; - -/** - * Default {@link HealthContributorRegistry} implementation. - * - * @author Phillip Webb - * @since 2.2.0 - */ -public class DefaultHealthContributorRegistry extends DefaultContributorRegistry - implements HealthContributorRegistry { - - public DefaultHealthContributorRegistry() { - } - - public DefaultHealthContributorRegistry(Map contributors) { - super(contributors); - } - - public DefaultHealthContributorRegistry(Map contributors, - Function nameFactory) { - super(contributors, nameFactory); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultReactiveHealthContributorRegistry.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultReactiveHealthContributorRegistry.java deleted file mode 100644 index 469c784a215..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultReactiveHealthContributorRegistry.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Map; -import java.util.function.Function; - -/** - * Default {@link ReactiveHealthContributorRegistry} implementation. - * - * @author Phillip Webb - * @since 2.0.0 - */ -public class DefaultReactiveHealthContributorRegistry extends DefaultContributorRegistry - implements ReactiveHealthContributorRegistry { - - public DefaultReactiveHealthContributorRegistry() { - } - - public DefaultReactiveHealthContributorRegistry(Map contributors) { - super(contributors); - } - - public DefaultReactiveHealthContributorRegistry(Map contributors, - Function nameFactory) { - super(contributors, nameFactory); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorNameFactory.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorNameFactory.java deleted file mode 100644 index aba7b67733b..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorNameFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Locale; -import java.util.function.Function; - -/** - * Generate a sensible health indicator name based on its bean name. - * - * @author Stephane Nicoll - * @author Phillip Webb - * @since 2.0.0 - */ -public class HealthContributorNameFactory implements Function { - - private static final String[] SUFFIXES = { "healthindicator", "healthcontributor" }; - - /** - * A shared singleton {@link HealthContributorNameFactory} instance. - */ - public static final HealthContributorNameFactory INSTANCE = new HealthContributorNameFactory(); - - @Override - public String apply(String name) { - for (String suffix : SUFFIXES) { - if (name != null && name.toLowerCase(Locale.ENGLISH).endsWith(suffix)) { - return name.substring(0, name.length() - suffix.length()); - } - } - return name; - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthComponent.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthDescriptor.java similarity index 78% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthComponent.java rename to spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthDescriptor.java index bd3b3ca766c..1e3db93165e 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthComponent.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthDescriptor.java @@ -19,19 +19,16 @@ package org.springframework.boot.actuate.health; import com.fasterxml.jackson.annotation.JsonUnwrapped; import org.springframework.boot.actuate.endpoint.OperationResponseBody; +import org.springframework.boot.health.contributor.Status; /** - * A component that contributes data to results returned from the {@link HealthEndpoint}. + * Description of health including a status. * * @author Phillip Webb - * @since 2.2.0 - * @see Health - * @see CompositeHealth + * @since 4.0.0 */ -public abstract class HealthComponent implements OperationResponseBody { - - HealthComponent() { - } +public abstract sealed class HealthDescriptor implements OperationResponseBody + permits IndicatedHealthDescriptor, CompositeHealthDescriptor { /** * Return the status of the component. diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java index bede8fb8d37..d140d66df96 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java @@ -27,6 +27,9 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.Selector; import org.springframework.boot.actuate.endpoint.annotation.Selector.Match; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; /** * {@link Endpoint @Endpoint} to expose application health information. @@ -39,53 +42,47 @@ import org.springframework.boot.actuate.endpoint.annotation.Selector.Match; * @since 2.0.0 */ @Endpoint(id = "health") -public class HealthEndpoint extends HealthEndpointSupport { +public class HealthEndpoint extends HealthEndpointSupport { /** * Health endpoint id. */ public static final EndpointId ID = EndpointId.of("health"); - private static final String[] EMPTY_PATH = {}; - /** * Create a new {@link HealthEndpoint} instance. * @param registry the health contributor registry + * @param fallbackRegistry the fallback registry or {@code null} * @param groups the health endpoint groups - * @param slowIndicatorLoggingThreshold duration after which slow health indicator + * @param slowContributorLoggingThreshold duration after which slow health indicator * logging should occur - * @since 2.6.9 + * @since 4.0.0 */ - public HealthEndpoint(HealthContributorRegistry registry, HealthEndpointGroups groups, - Duration slowIndicatorLoggingThreshold) { - super(registry, groups, slowIndicatorLoggingThreshold); + public HealthEndpoint(HealthContributorRegistry registry, ReactiveHealthContributorRegistry fallbackRegistry, + HealthEndpointGroups groups, Duration slowContributorLoggingThreshold) { + super(Contributor.blocking(registry, fallbackRegistry), groups, slowContributorLoggingThreshold); } @ReadOperation - public HealthComponent health() { - HealthComponent health = health(ApiVersion.V3, EMPTY_PATH); - return (health != null) ? health : DEFAULT_HEALTH; + public HealthDescriptor health() { + HealthDescriptor health = health(ApiVersion.V3, EMPTY_PATH); + return (health != null) ? health : IndicatedHealthDescriptor.UP; } @ReadOperation - public HealthComponent healthForPath(@Selector(match = Match.ALL_REMAINING) String... path) { + public HealthDescriptor healthForPath(@Selector(match = Match.ALL_REMAINING) String... path) { return health(ApiVersion.V3, path); } - private HealthComponent health(ApiVersion apiVersion, String... path) { - HealthResult result = getHealth(apiVersion, null, SecurityContext.NONE, true, path); - return (result != null) ? result.getHealth() : null; + private HealthDescriptor health(ApiVersion apiVersion, String... path) { + Result result = getResult(apiVersion, null, SecurityContext.NONE, true, path); + return (result != null) ? result.descriptor() : null; } @Override - protected HealthComponent getHealth(HealthContributor contributor, boolean includeDetails) { - return ((HealthIndicator) contributor).getHealth(includeDetails); - } - - @Override - protected HealthComponent aggregateContributions(ApiVersion apiVersion, Map contributions, + protected HealthDescriptor aggregateDescriptors(ApiVersion apiVersion, Map contributions, StatusAggregator statusAggregator, boolean showComponents, Set groupNames) { - return getCompositeHealth(apiVersion, contributions, statusAggregator, showComponents, groupNames); + return getCompositeDescriptor(apiVersion, contributions, statusAggregator, showComponents, groupNames); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointGroup.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointGroup.java index eba86844db4..ff43c66a89a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointGroup.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointGroup.java @@ -17,6 +17,8 @@ package org.springframework.boot.actuate.health; import org.springframework.boot.actuate.endpoint.SecurityContext; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; /** * A logical grouping of {@link HealthContributor health contributors} that can be exposed @@ -36,8 +38,8 @@ public interface HealthEndpointGroup { boolean isMember(String name); /** - * Returns if {@link CompositeHealth#getComponents() health components} should be - * shown in the response. + * Returns if {@link CompositeHealthDescriptor#getComponents() health components} + * should be shown in the response. * @param securityContext the endpoint security context * @return {@code true} to shown details or {@code false} to hide them */ diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointSupport.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointSupport.java index 82477575d6f..ca94d213815 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointSupport.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointSupport.java @@ -21,6 +21,7 @@ import java.time.Instant; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import java.util.stream.Collectors; import org.apache.commons.logging.Log; @@ -30,6 +31,7 @@ import org.springframework.boot.actuate.endpoint.ApiVersion; import org.springframework.boot.actuate.endpoint.SecurityContext; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; import org.springframework.boot.convert.DurationStyle; +import org.springframework.boot.health.contributor.Status; import org.springframework.core.log.LogMessage; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -37,62 +39,59 @@ import org.springframework.util.StringUtils; /** * Base class for health endpoints and health endpoint extensions. * - * @param the contributor type - * @param the contributed health component type + * @param the health type + * @param the descriptor type * @author Phillip Webb * @author Scott Frederick */ -abstract class HealthEndpointSupport { +abstract class HealthEndpointSupport { + + static final String[] EMPTY_PATH = {}; private static final Log logger = LogFactory.getLog(HealthEndpointSupport.class); - static final Health DEFAULT_HEALTH = Health.up().build(); - - private final ContributorRegistry registry; + private final Contributor rootContributor; private final HealthEndpointGroups groups; - private final Duration slowIndicatorLoggingThreshold; + private final Duration slowContributorLoggingThreshold; /** * Create a new {@link HealthEndpointSupport} instance. - * @param registry the health contributor registry + * @param rootContributor the health contributor registry * @param groups the health endpoint groups - * @param slowIndicatorLoggingThreshold duration after which slow health indicator + * @param slowContributorLoggingThreshold duration after which slow health contributor * logging should occur */ - HealthEndpointSupport(ContributorRegistry registry, HealthEndpointGroups groups, - Duration slowIndicatorLoggingThreshold) { - Assert.notNull(registry, "'registry' must not be null"); + HealthEndpointSupport(Contributor rootContributor, HealthEndpointGroups groups, + Duration slowContributorLoggingThreshold) { + Assert.notNull(rootContributor, "'rootContributor' must not be null"); Assert.notNull(groups, "'groups' must not be null"); - this.registry = registry; + this.rootContributor = rootContributor; this.groups = groups; - this.slowIndicatorLoggingThreshold = slowIndicatorLoggingThreshold; + this.slowContributorLoggingThreshold = slowContributorLoggingThreshold; } - HealthResult getHealth(ApiVersion apiVersion, WebServerNamespace serverNamespace, - SecurityContext securityContext, boolean showAll, String... path) { - if (path.length > 0) { - HealthEndpointGroup group = getHealthGroup(serverNamespace, path); - if (group != null) { - return getHealth(apiVersion, group, securityContext, showAll, path, 1); - } + Result getResult(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext, + boolean showAll, String... path) { + HealthEndpointGroup group = (path.length > 0) ? getGroup(serverNamespace, path) : null; + if (group != null) { + return getResult(apiVersion, group, securityContext, showAll, path, 1); } - return getHealth(apiVersion, this.groups.getPrimary(), securityContext, showAll, path, 0); + return getResult(apiVersion, this.groups.getPrimary(), securityContext, showAll, path, 0); } - private HealthEndpointGroup getHealthGroup(WebServerNamespace serverNamespace, String... path) { + private HealthEndpointGroup getGroup(WebServerNamespace serverNamespace, String... path) { if (this.groups.get(path[0]) != null) { return this.groups.get(path[0]); } if (serverNamespace != null) { - AdditionalHealthEndpointPath additionalPath = AdditionalHealthEndpointPath.of(serverNamespace, path[0]); - return this.groups.get(additionalPath); + return this.groups.get(AdditionalHealthEndpointPath.of(serverNamespace, path[0])); } return null; } - private HealthResult getHealth(ApiVersion apiVersion, HealthEndpointGroup group, SecurityContext securityContext, + private Result getResult(ApiVersion apiVersion, HealthEndpointGroup group, SecurityContext securityContext, boolean showAll, String[] path, int pathOffset) { boolean showComponents = showAll || group.showComponents(securityContext); boolean showDetails = showAll || group.showDetails(securityContext); @@ -101,24 +100,23 @@ abstract class HealthEndpointSupport { if (!showComponents && !isRoot) { return null; } - Object contributor = getContributor(path, pathOffset); + Contributor contributor = getContributor(path, pathOffset); if (contributor == null) { return null; } String name = getName(path, pathOffset); - Set groupNames = isSystemHealth ? this.groups.getNames() : null; - T health = getContribution(apiVersion, group, name, contributor, showComponents, showDetails, groupNames); - return (health != null) ? new HealthResult<>(health, group) : null; + Set groupNames = (!isSystemHealth) ? null : new TreeSet<>(this.groups.getNames()); + D descriptor = getDescriptor(apiVersion, group, name, contributor, showComponents, showDetails, groupNames); + return (descriptor != null) ? new Result<>(descriptor, group) : null; } - @SuppressWarnings("unchecked") - private Object getContributor(String[] path, int pathOffset) { - Object contributor = this.registry; + private Contributor getContributor(String[] path, int pathOffset) { + Contributor contributor = this.rootContributor; while (pathOffset < path.length) { - if (!(contributor instanceof NamedContributors)) { + if (!contributor.isComposite()) { return null; } - contributor = ((NamedContributors) contributor).getContributor(path[pathOffset]); + contributor = contributor.getChild(path[pathOffset]); pathOffset++; } return contributor; @@ -134,100 +132,77 @@ abstract class HealthEndpointSupport { return name.toString(); } - @SuppressWarnings("unchecked") - private T getContribution(ApiVersion apiVersion, HealthEndpointGroup group, String name, Object contributor, - boolean showComponents, boolean showDetails, Set groupNames) { - if (contributor instanceof NamedContributors) { - return getAggregateContribution(apiVersion, group, name, (NamedContributors) contributor, showComponents, - showDetails, groupNames); + private D getDescriptor(ApiVersion apiVersion, HealthEndpointGroup group, String name, + Contributor contributor, boolean showComponents, boolean showDetails, Set groupNames) { + if (contributor.isComposite()) { + return getAggregateDescriptor(apiVersion, group, name, contributor, showComponents, showDetails, + groupNames); } - if (contributor != null && (name.isEmpty() || group.isMember(name))) { - return getLoggedHealth((C) contributor, name, showDetails); + if (name.isEmpty() || group.isMember(name)) { + return getDescriptorAndLogIfSlow(contributor, name, showDetails); } return null; } - private T getAggregateContribution(ApiVersion apiVersion, HealthEndpointGroup group, String name, - NamedContributors namedContributors, boolean showComponents, boolean showDetails, - Set groupNames) { + private D getAggregateDescriptor(ApiVersion apiVersion, HealthEndpointGroup group, String name, + Contributor contributor, boolean showComponents, boolean showDetails, Set groupNames) { String prefix = (StringUtils.hasText(name)) ? name + "/" : ""; - Map contributions = new LinkedHashMap<>(); - for (NamedContributor child : namedContributors) { - T contribution = getContribution(apiVersion, group, prefix + child.getName(), child.getContributor(), - showComponents, showDetails, null); - if (contribution != null) { - contributions.put(child.getName(), contribution); + Map descriptors = new LinkedHashMap<>(); + for (Contributor.Child child : contributor) { + String childName = child.name(); + D descriptor = getDescriptor(apiVersion, group, prefix + childName, child.contributor(), showComponents, + showDetails, null); + if (descriptor != null) { + descriptors.put(childName, descriptor); } } - if (contributions.isEmpty()) { + if (descriptors.isEmpty()) { return null; } - return aggregateContributions(apiVersion, contributions, group.getStatusAggregator(), showComponents, - groupNames); + return aggregateDescriptors(apiVersion, descriptors, group.getStatusAggregator(), showComponents, groupNames); } - private T getLoggedHealth(C contributor, String name, boolean showDetails) { + private D getDescriptorAndLogIfSlow(Contributor contributor, String name, boolean showDetails) { Instant start = Instant.now(); try { - return getHealth(contributor, showDetails); + return contributor.getDescriptor(showDetails); } finally { - if (logger.isWarnEnabled() && this.slowIndicatorLoggingThreshold != null) { + if (logger.isWarnEnabled() && this.slowContributorLoggingThreshold != null) { Duration duration = Duration.between(start, Instant.now()); - if (duration.compareTo(this.slowIndicatorLoggingThreshold) > 0) { - String contributorClassName = contributor.getClass().getName(); - Object contributorIdentifier = (!StringUtils.hasLength(name)) ? contributorClassName - : contributorClassName + " (" + name + ")"; - logger.warn(LogMessage.format("Health contributor %s took %s to respond", contributorIdentifier, - DurationStyle.SIMPLE.print(duration))); + if (duration.compareTo(this.slowContributorLoggingThreshold) > 0) { + logger.warn(LogMessage.format("Health contributor %s took %s to respond", + contributor.getIdentifier(name), DurationStyle.SIMPLE.print(duration))); } } } } - protected abstract T getHealth(C contributor, boolean includeDetails); - - protected abstract T aggregateContributions(ApiVersion apiVersion, Map contributions, + abstract D aggregateDescriptors(ApiVersion apiVersion, Map descriptors, StatusAggregator statusAggregator, boolean showComponents, Set groupNames); - protected final CompositeHealth getCompositeHealth(ApiVersion apiVersion, Map components, - StatusAggregator statusAggregator, boolean showComponents, Set groupNames) { + final CompositeHealthDescriptor getCompositeDescriptor(ApiVersion apiVersion, + Map descriptors, StatusAggregator statusAggregator, boolean showComponents, + Set groupNames) { Status status = statusAggregator - .getAggregateStatus(components.values().stream().map(this::getStatus).collect(Collectors.toSet())); - Map instances = showComponents ? components : null; - if (groupNames != null) { - return new SystemHealth(apiVersion, status, instances, groupNames); - } - return new CompositeHealth(apiVersion, status, instances); + .getAggregateStatus(descriptors.values().stream().map(this::getStatus).collect(Collectors.toSet())); + descriptors = (!showComponents) ? null : descriptors; + return (groupNames != null) ? new SystemHealthDescriptor(apiVersion, status, descriptors, groupNames) + : new CompositeHealthDescriptor(apiVersion, status, descriptors); } - private Status getStatus(HealthComponent component) { + private Status getStatus(HealthDescriptor component) { return (component != null) ? component.getStatus() : Status.UNKNOWN; } /** - * A health result containing health and the group that created it. + * A health result containing descriptor and the group that created it. * - * @param the contributed health component + * @param descriptor the health descriptor + * @param group the group used to create the health + * @param the details type */ - static class HealthResult { - - private final T health; - - private final HealthEndpointGroup group; - - HealthResult(T health, HealthEndpointGroup group) { - this.health = health; - this.group = group; - } - - T getHealth() { - return this.health; - } - - HealthEndpointGroup getGroup() { - return this.group; - } + record Result(D descriptor, HealthEndpointGroup group) { } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtension.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtension.java index 0214692fb10..763561a747b 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtension.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtension.java @@ -29,6 +29,9 @@ import org.springframework.boot.actuate.endpoint.annotation.Selector.Match; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.context.annotation.ImportRuntimeHints; /** @@ -46,58 +49,53 @@ import org.springframework.context.annotation.ImportRuntimeHints; */ @EndpointWebExtension(endpoint = HealthEndpoint.class) @ImportRuntimeHints(HealthEndpointWebExtensionRuntimeHints.class) -public class HealthEndpointWebExtension extends HealthEndpointSupport { - - private static final String[] NO_PATH = {}; +public class HealthEndpointWebExtension extends HealthEndpointSupport { /** * Create a new {@link HealthEndpointWebExtension} instance. * @param registry the health contributor registry + * @param fallbackRegistry the fallback registry or {@code null} * @param groups the health endpoint groups - * @param slowIndicatorLoggingThreshold duration after which slow health indicator + * @param slowContributorLoggingThreshold duration after which slow health indicator * logging should occur - * @since 2.6.9 + * @since 4.0.0 */ - public HealthEndpointWebExtension(HealthContributorRegistry registry, HealthEndpointGroups groups, - Duration slowIndicatorLoggingThreshold) { - super(registry, groups, slowIndicatorLoggingThreshold); + public HealthEndpointWebExtension(HealthContributorRegistry registry, + ReactiveHealthContributorRegistry fallbackRegistry, HealthEndpointGroups groups, + Duration slowContributorLoggingThreshold) { + super(Contributor.blocking(registry, fallbackRegistry), groups, slowContributorLoggingThreshold); } @ReadOperation - public WebEndpointResponse health(ApiVersion apiVersion, WebServerNamespace serverNamespace, + public WebEndpointResponse health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext) { - return health(apiVersion, serverNamespace, securityContext, false, NO_PATH); + return health(apiVersion, serverNamespace, securityContext, false, EMPTY_PATH); } @ReadOperation - public WebEndpointResponse health(ApiVersion apiVersion, WebServerNamespace serverNamespace, + public WebEndpointResponse health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext, @Selector(match = Match.ALL_REMAINING) String... path) { return health(apiVersion, serverNamespace, securityContext, false, path); } - public WebEndpointResponse health(ApiVersion apiVersion, WebServerNamespace serverNamespace, + public WebEndpointResponse health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext, boolean showAll, String... path) { - HealthResult result = getHealth(apiVersion, serverNamespace, securityContext, showAll, path); + Result result = getResult(apiVersion, serverNamespace, securityContext, showAll, path); if (result == null) { - return (Arrays.equals(path, NO_PATH)) - ? new WebEndpointResponse<>(DEFAULT_HEALTH, WebEndpointResponse.STATUS_OK) + return (Arrays.equals(path, EMPTY_PATH)) + ? new WebEndpointResponse<>(IndicatedHealthDescriptor.UP, WebEndpointResponse.STATUS_OK) : new WebEndpointResponse<>(WebEndpointResponse.STATUS_NOT_FOUND); } - HealthComponent health = result.getHealth(); - HealthEndpointGroup group = result.getGroup(); - int statusCode = group.getHttpCodeStatusMapper().getStatusCode(health.getStatus()); - return new WebEndpointResponse<>(health, statusCode); + HealthDescriptor descriptor = result.descriptor(); + HealthEndpointGroup group = result.group(); + int statusCode = group.getHttpCodeStatusMapper().getStatusCode(descriptor.getStatus()); + return new WebEndpointResponse<>(descriptor, statusCode); } @Override - protected HealthComponent getHealth(HealthContributor contributor, boolean includeDetails) { - return ((HealthIndicator) contributor).getHealth(includeDetails); - } - - @Override - protected HealthComponent aggregateContributions(ApiVersion apiVersion, Map contributions, + protected HealthDescriptor aggregateDescriptors(ApiVersion apiVersion, Map contributions, StatusAggregator statusAggregator, boolean showComponents, Set groupNames) { - return getCompositeHealth(apiVersion, contributions, statusAggregator, showComponents, groupNames); + return getCompositeDescriptor(apiVersion, contributions, statusAggregator, showComponents, groupNames); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHints.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHints.java index dca55a047fd..9cf2ec2637a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHints.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHints.java @@ -32,8 +32,8 @@ class HealthEndpointWebExtensionRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - this.bindingRegistrar.registerReflectionHints(hints.reflection(), Health.class, SystemHealth.class, - CompositeHealth.class); + this.bindingRegistrar.registerReflectionHints(hints.reflection(), IndicatedHealthDescriptor.class, + CompositeHealthDescriptor.class, SystemHealthDescriptor.class); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HttpCodeStatusMapper.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HttpCodeStatusMapper.java index 53af03e03cb..22e85966a4e 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HttpCodeStatusMapper.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HttpCodeStatusMapper.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.health; +import org.springframework.boot.health.contributor.Status; + /** * Strategy used to map a {@link Status health status} to an HTTP status code. * diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptor.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptor.java new file mode 100644 index 00000000000..1cf439ddffd --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptor.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.health; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Status; + +/** + * Description of health obtained from a {@link HealthIndicator} or + * {@link ReactiveHealthIndicator}. + * + * @author Phillip Webb + * @since 4.0.0 + */ +public final class IndicatedHealthDescriptor extends HealthDescriptor { + + static final IndicatedHealthDescriptor UP = new IndicatedHealthDescriptor(Health.up().build()); + + private final Health health; + + IndicatedHealthDescriptor(Health health) { + this.health = health; + } + + @Override + public Status getStatus() { + return this.health.getStatus(); + } + + @JsonInclude(Include.NON_EMPTY) + public Map getDetails() { + return this.health.getDetails(); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributor.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributor.java deleted file mode 100644 index 3acb5b9192b..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributor.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import org.springframework.util.Assert; - -/** - * A single named health endpoint contributors (either {@link HealthContributor} or - * {@link ReactiveHealthContributor}). - * - * @param the contributor type - * @author Phillip Webb - * @since 2.0.0 - * @see NamedContributors - */ -public interface NamedContributor { - - /** - * Returns the name of the contributor. - * @return the contributor name - */ - String getName(); - - /** - * Returns the contributor instance. - * @return the contributor instance - */ - C getContributor(); - - static NamedContributor of(String name, C contributor) { - Assert.notNull(name, "'name' must not be null"); - Assert.notNull(contributor, "'contributor' must not be null"); - return new NamedContributor<>() { - - @Override - public String getName() { - return name; - } - - @Override - public C getContributor() { - return contributor; - } - - }; - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributors.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributors.java deleted file mode 100644 index bc945df5c9e..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributors.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * A collection of named health endpoint contributors (either {@link HealthContributor} or - * {@link ReactiveHealthContributor}). - * - * @param the contributor type - * @author Phillip Webb - * @since 2.0.0 - * @see NamedContributor - */ -public interface NamedContributors extends Iterable> { - - /** - * Return the contributor with the given name. - * @param name the name of the contributor - * @return a contributor instance or {@code null} - */ - C getContributor(String name); - - /** - * Return a stream of the {@link NamedContributor named contributors}. - * @return the stream of named contributors - */ - default Stream> stream() { - return StreamSupport.stream(spliterator(), false); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapter.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapter.java deleted file mode 100644 index 2b0a6c149b4..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapter.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Function; - -import org.springframework.util.Assert; - -/** - * {@link NamedContributors} backed by a map with values adapted as necessary. - * - * @param the value type - * @param the contributor type - * @author Phillip Webb - * @author Guirong Hu - * @see CompositeHealthContributorMapAdapter - * @see CompositeReactiveHealthContributorMapAdapter - */ -abstract class NamedContributorsMapAdapter implements NamedContributors { - - private final Map map; - - NamedContributorsMapAdapter(Map map, Function valueAdapter) { - Assert.notNull(map, "'map' must not be null"); - Assert.notNull(valueAdapter, "'valueAdapter' must not be null"); - map.keySet().forEach(this::validateMapKey); - this.map = Collections.unmodifiableMap(map.entrySet().stream().collect(LinkedHashMap::new, (result, entry) -> { - String key = entry.getKey(); - C value = adaptMapValue(entry.getValue(), valueAdapter); - result.put(key, value); - }, Map::putAll)); - - } - - private void validateMapKey(String value) { - Assert.notNull(value, "'map' must not contain null keys"); - Assert.isTrue(!value.contains("/"), "'map' keys must not contain a '/'"); - } - - private C adaptMapValue(V value, Function valueAdapter) { - C contributor = (value != null) ? valueAdapter.apply(value) : null; - Assert.notNull(contributor, "'map' must not contain null values"); - return contributor; - } - - @Override - public Iterator> iterator() { - Iterator> iterator = this.map.entrySet().iterator(); - return new Iterator<>() { - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public NamedContributor next() { - Entry entry = iterator.next(); - return NamedContributor.of(entry.getKey(), entry.getValue()); - } - - }; - } - - @Override - public C getContributor(String name) { - return this.map.get(name); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributor.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributor.java deleted file mode 100644 index 84e1331ef0c..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import org.springframework.util.Assert; - -/** - * Tagging interface for classes that contribute to {@link HealthComponent health - * components} to the results returned from the {@link HealthEndpoint}. A contributor must - * be either a {@link ReactiveHealthIndicator} or a - * {@link CompositeReactiveHealthContributor}. - * - * @author Phillip Webb - * @since 2.2.0 - * @see ReactiveHealthIndicator - * @see CompositeReactiveHealthContributor - */ -public interface ReactiveHealthContributor { - - static ReactiveHealthContributor adapt(HealthContributor healthContributor) { - Assert.notNull(healthContributor, "'healthContributor' must not be null"); - if (healthContributor instanceof HealthIndicator healthIndicator) { - return new HealthIndicatorReactiveAdapter(healthIndicator); - } - if (healthContributor instanceof CompositeHealthContributor compositeHealthContributor) { - return new CompositeHealthContributorReactiveAdapter(compositeHealthContributor); - } - throw new IllegalStateException("Unknown HealthContributor type"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtension.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtension.java index 34d480192c0..8bc5e3a73ac 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtension.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtension.java @@ -32,6 +32,9 @@ import org.springframework.boot.actuate.endpoint.annotation.Selector.Match; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import org.springframework.context.annotation.ImportRuntimeHints; /** @@ -46,94 +49,76 @@ import org.springframework.context.annotation.ImportRuntimeHints; @EndpointWebExtension(endpoint = HealthEndpoint.class) @ImportRuntimeHints(HealthEndpointWebExtensionRuntimeHints.class) public class ReactiveHealthEndpointWebExtension - extends HealthEndpointSupport> { - - private static final String[] NO_PATH = {}; + extends HealthEndpointSupport, Mono> { /** * Create a new {@link ReactiveHealthEndpointWebExtension} instance. * @param registry the health contributor registry + * @param fallbackRegistry the fallback registry or {@code null} * @param groups the health endpoint groups - * @param slowIndicatorLoggingThreshold duration after which slow health indicator + * @param slowContributorLoggingThreshold duration after which slow health indicator * logging should occur - * @since 2.6.9 + * @since 4.0.0 */ - public ReactiveHealthEndpointWebExtension(ReactiveHealthContributorRegistry registry, HealthEndpointGroups groups, - Duration slowIndicatorLoggingThreshold) { - super(registry, groups, slowIndicatorLoggingThreshold); + public ReactiveHealthEndpointWebExtension(ReactiveHealthContributorRegistry registry, + HealthContributorRegistry fallbackRegistry, HealthEndpointGroups groups, + Duration slowContributorLoggingThreshold) { + super(Contributor.reactive(registry, fallbackRegistry), groups, slowContributorLoggingThreshold); } @ReadOperation - public Mono> health(ApiVersion apiVersion, + public Mono> health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext) { - return health(apiVersion, serverNamespace, securityContext, false, NO_PATH); + return health(apiVersion, serverNamespace, securityContext, false, EMPTY_PATH); } @ReadOperation - public Mono> health(ApiVersion apiVersion, + public Mono> health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext, @Selector(match = Match.ALL_REMAINING) String... path) { return health(apiVersion, serverNamespace, securityContext, false, path); } - public Mono> health(ApiVersion apiVersion, + public Mono> health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext, boolean showAll, String... path) { - HealthResult> result = getHealth(apiVersion, serverNamespace, securityContext, + Result> result = getResult(apiVersion, serverNamespace, securityContext, showAll, path); if (result == null) { - return (Arrays.equals(path, NO_PATH)) - ? Mono.just(new WebEndpointResponse<>(DEFAULT_HEALTH, WebEndpointResponse.STATUS_OK)) + return (Arrays.equals(path, EMPTY_PATH)) + ? Mono.just(new WebEndpointResponse<>(IndicatedHealthDescriptor.UP, WebEndpointResponse.STATUS_OK)) : Mono.just(new WebEndpointResponse<>(WebEndpointResponse.STATUS_NOT_FOUND)); } - HealthEndpointGroup group = result.getGroup(); - return result.getHealth().map((health) -> { + HealthEndpointGroup group = result.group(); + return result.descriptor().map((health) -> { int statusCode = group.getHttpCodeStatusMapper().getStatusCode(health.getStatus()); return new WebEndpointResponse<>(health, statusCode); }); } @Override - protected Mono getHealth(ReactiveHealthContributor contributor, boolean includeDetails) { - return ((ReactiveHealthIndicator) contributor).getHealth(includeDetails); - } - - @Override - protected Mono aggregateContributions(ApiVersion apiVersion, - Map> contributions, StatusAggregator statusAggregator, + protected Mono aggregateDescriptors(ApiVersion apiVersion, + Map> contributions, StatusAggregator statusAggregator, boolean showComponents, Set groupNames) { return Flux.fromIterable(contributions.entrySet()) - .flatMap(NamedHealthComponent::create) - .collectMap(NamedHealthComponent::getName, NamedHealthComponent::getHealth) - .map((components) -> this.getCompositeHealth(apiVersion, components, statusAggregator, showComponents, + .flatMap(NamedHealthDescriptor::create) + .collectMap(NamedHealthDescriptor::name, NamedHealthDescriptor::descriptor) + .map((components) -> this.getCompositeDescriptor(apiVersion, components, statusAggregator, showComponents, groupNames)); } /** - * A named {@link HealthComponent}. + * A named {@link HealthDescriptor}. */ - private static final class NamedHealthComponent { + private record NamedHealthDescriptor(String name, HealthDescriptor descriptor) { - private final String name; - - private final HealthComponent health; - - private NamedHealthComponent(Object... pair) { - this.name = (String) pair[0]; - this.health = (HealthComponent) pair[1]; - } - - String getName() { - return this.name; - } - - HealthComponent getHealth() { - return this.health; - } - - static Mono create(Map.Entry> entry) { + static Mono create(Map.Entry> entry) { Mono name = Mono.just(entry.getKey()); - Mono health = entry.getValue(); - return Mono.zip(NamedHealthComponent::new, name, health); + Mono health = entry.getValue(); + return Mono.zip(NamedHealthDescriptor::ofPair, name, health); + } + + private static NamedHealthDescriptor ofPair(Object... pair) { + return new NamedHealthDescriptor((String) pair[0], (HealthDescriptor) pair[1]); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapper.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapper.java index ed2ad52c363..db29e4211e0 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapper.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapper.java @@ -22,6 +22,7 @@ import java.util.LinkedHashMap; import java.util.Map; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.CollectionUtils; /** diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java index 1ef94c29620..a864d15eb33 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Stream; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java index 91eaf63b4fd..f22e3543c09 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java @@ -20,6 +20,9 @@ import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; + /** * Strategy used to aggregate {@link Status} instances. *

diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SystemHealth.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SystemHealthDescriptor.java similarity index 71% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SystemHealth.java rename to spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SystemHealthDescriptor.java index 6d79915cfc3..6326bff36de 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SystemHealth.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SystemHealthDescriptor.java @@ -18,27 +18,27 @@ package org.springframework.boot.actuate.health; import java.util.Map; import java.util.Set; -import java.util.TreeSet; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import org.springframework.boot.actuate.endpoint.ApiVersion; +import org.springframework.boot.health.contributor.Status; /** - * A {@link HealthComponent} that represents the overall system health and the available - * groups. + * Description of overall system health. * * @author Phillip Webb - * @since 2.2.0 + * @since 4.0.0 */ -public final class SystemHealth extends CompositeHealth { +public final class SystemHealthDescriptor extends CompositeHealthDescriptor { private final Set groups; - SystemHealth(ApiVersion apiVersion, Status status, Map instances, Set groups) { - super(apiVersion, status, instances); - this.groups = (groups != null) ? new TreeSet<>(groups) : null; + SystemHealthDescriptor(ApiVersion apiVersion, Status status, Map components, + Set groups) { + super(apiVersion, status, components); + this.groups = groups; } @JsonInclude(Include.NON_EMPTY) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ssl/SslHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ssl/SslHealthIndicator.java index 7c8a0ee6249..e2c4ec6a17b 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ssl/SslHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ssl/SslHealthIndicator.java @@ -22,10 +22,10 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.info.SslInfo; import org.springframework.boot.info.SslInfo.BundleInfo; import org.springframework.boot.info.SslInfo.CertificateChainInfo; @@ -54,7 +54,7 @@ public class SslHealthIndicator extends AbstractHealthIndicator { } @Override - protected void doHealthCheck(Builder builder) throws Exception { + protected void doHealthCheck(Health.Builder builder) throws Exception { List validCertificateChains = new ArrayList<>(); List invalidCertificateChains = new ArrayList<>(); List expiringCerificateChains = new ArrayList<>(); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java index 2699a12004d..7a2494ad3fa 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java @@ -21,10 +21,10 @@ import java.io.File; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.core.log.LogMessage; import org.springframework.util.unit.DataSize; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicatorTests.java index e6b63f311c2..8a882f2411a 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicatorTests.java @@ -21,10 +21,10 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.availability.AvailabilityState; import org.springframework.boot.availability.LivenessState; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -82,7 +82,7 @@ class AvailabilityStateHealthIndicatorTests { statusMappings.add(LivenessState.BROKEN, Status.DOWN); }); given(this.applicationAvailability.getState(LivenessState.class)).willReturn(LivenessState.BROKEN); - assertThat(indicator.getHealth(false).getStatus()).isEqualTo(Status.DOWN); + assertThat(indicator.health(false).getStatus()).isEqualTo(Status.DOWN); } @Test @@ -93,7 +93,7 @@ class AvailabilityStateHealthIndicatorTests { statusMappings.addDefaultStatus(Status.UNKNOWN); }); given(this.applicationAvailability.getState(LivenessState.class)).willReturn(LivenessState.BROKEN); - assertThat(indicator.getHealth(false).getStatus()).isEqualTo(Status.UNKNOWN); + assertThat(indicator.health(false).getStatus()).isEqualTo(Status.UNKNOWN); } @Test @@ -104,7 +104,7 @@ class AvailabilityStateHealthIndicatorTests { statusMappings.addDefaultStatus(Status.DOWN); }); given(this.applicationAvailability.getState(TestAvailabilityState.class)).willReturn(TestAvailabilityState.TWO); - assertThat(indicator.getHealth(false).getStatus()).isEqualTo(Status.DOWN); + assertThat(indicator.health(false).getStatus()).isEqualTo(Status.DOWN); } static class TestAvailabilityState implements AvailabilityState { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicatorTests.java index 4f936f21f4a..ac83a47ef88 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicatorTests.java @@ -19,9 +19,9 @@ package org.springframework.boot.actuate.availability; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.availability.LivenessState; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicatorTests.java index c0a4615d752..69ab89b1500 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicatorTests.java @@ -19,9 +19,9 @@ package org.springframework.boot.actuate.availability; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.availability.ApplicationAvailability; import org.springframework.boot.availability.ReadinessState; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthDescriptorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthDescriptorTests.java new file mode 100644 index 00000000000..06df5e7fc2d --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthDescriptorTests.java @@ -0,0 +1,95 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.health; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.actuate.endpoint.ApiVersion; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +/** + * Tests for {@link CompositeHealthDescriptor}. + * + * @author Phillip Webb + */ +class CompositeHealthDescriptorTests { + + @Test + void createWhenApiVersionIsNullThrowsException() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new CompositeHealthDescriptor(null, Status.UP, Collections.emptyMap())) + .withMessage("'apiVersion' must not be null"); + } + + @Test + void createWhenStatusIsNullThrowsException() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new CompositeHealthDescriptor(ApiVersion.V3, null, Collections.emptyMap())) + .withMessage("'status' must not be null"); + } + + @Test + void getStatusReturnsStatus() { + CompositeHealthDescriptor descriptor = new CompositeHealthDescriptor(ApiVersion.V3, Status.UP, + Collections.emptyMap()); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + } + + @Test + void getComponentReturnsComponents() { + Map components = new LinkedHashMap<>(); + components.put("a", new IndicatedHealthDescriptor(Health.up().build())); + CompositeHealthDescriptor descriptor = new CompositeHealthDescriptor(ApiVersion.V3, Status.UP, components); + assertThat(descriptor.getComponents()).isEqualTo(components); + } + + @Test + void serializeV3WithJacksonReturnsValidJson() throws Exception { + Map components = new LinkedHashMap<>(); + components.put("db1", new IndicatedHealthDescriptor(Health.up().build())); + components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build())); + CompositeHealthDescriptor descriptor = new CompositeHealthDescriptor(ApiVersion.V3, Status.UP, components); + ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo(""" + {"components":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}"""); + } + + @Test + void serializeV2WithJacksonReturnsValidJson() throws Exception { + Map components = new LinkedHashMap<>(); + components.put("db1", new IndicatedHealthDescriptor(Health.up().build())); + components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build())); + CompositeHealthDescriptor descriptor = new CompositeHealthDescriptor(ApiVersion.V2, Status.UP, components); + ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo(""" + {"details":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}"""); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthTests.java deleted file mode 100644 index b8804691436..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthTests.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.endpoint.ApiVersion; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Test for {@link CompositeHealth}. - * - * @author Phillip Webb - */ -class CompositeHealthTests { - - @Test - void createWhenStatusIsNullThrowsException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new CompositeHealth(ApiVersion.V3, null, Collections.emptyMap())) - .withMessage("'status' must not be null"); - } - - @Test - void getStatusReturnsStatus() { - CompositeHealth health = new CompositeHealth(ApiVersion.V3, Status.UP, Collections.emptyMap()); - assertThat(health.getStatus()).isEqualTo(Status.UP); - } - - @Test - void getComponentReturnsComponents() { - Map components = new LinkedHashMap<>(); - components.put("a", Health.up().build()); - CompositeHealth health = new CompositeHealth(ApiVersion.V3, Status.UP, components); - assertThat(health.getComponents()).isEqualTo(components); - } - - @Test - void serializeV3WithJacksonReturnsValidJson() throws Exception { - Map components = new LinkedHashMap<>(); - components.put("db1", Health.up().build()); - components.put("db2", Health.down().withDetail("a", "b").build()); - CompositeHealth health = new CompositeHealth(ApiVersion.V3, Status.UP, components); - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(health); - assertThat(json).isEqualTo("{\"status\":\"UP\",\"components\":{\"db1\":{\"status\":\"UP\"}," - + "\"db2\":{\"status\":\"DOWN\",\"details\":{\"a\":\"b\"}}}}"); - } - - @Test - void serializeV2WithJacksonReturnsValidJson() throws Exception { - Map components = new LinkedHashMap<>(); - components.put("db1", Health.up().build()); - components.put("db2", Health.down().withDetail("a", "b").build()); - CompositeHealth health = new CompositeHealth(ApiVersion.V2, Status.UP, components); - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(health); - assertThat(json).isEqualTo("{\"status\":\"UP\",\"details\":{\"db1\":{\"status\":\"UP\"}," - + "\"db2\":{\"status\":\"DOWN\",\"details\":{\"a\":\"b\"}}}}"); - } - - @Test // gh-26797 - void serializeV2WithJacksonAndDisabledCanOverrideAccessModifiersReturnsValidJson() throws Exception { - Map components = new LinkedHashMap<>(); - components.put("db1", Health.up().build()); - components.put("db2", Health.down().withDetail("a", "b").build()); - CompositeHealth health = new CompositeHealth(ApiVersion.V2, Status.UP, components); - JsonMapper mapper = JsonMapper.builder().disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS).build(); - String json = mapper.writeValueAsString(health); - assertThat(json).isEqualTo("{\"status\":\"UP\",\"details\":{\"db1\":{\"status\":\"UP\"}," - + "\"db2\":{\"status\":\"DOWN\",\"details\":{\"a\":\"b\"}}}}"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/DefaultContributorRegistryTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/DefaultContributorRegistryTests.java deleted file mode 100644 index 59a373915b5..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/DefaultContributorRegistryTests.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Collections; -import java.util.Iterator; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link DefaultContributorRegistry}. - * - * @author Phillip Webb - * @author Vedran Pavic - * @author Stephane Nicoll - */ -abstract class DefaultContributorRegistryTests { - - private final HealthIndicator one = mock(HealthIndicator.class); - - private final HealthIndicator two = mock(HealthIndicator.class); - - private ContributorRegistry registry; - - @BeforeEach - void setUp() { - given(this.one.health()).willReturn(new Health.Builder().unknown().withDetail("1", "1").build()); - given(this.two.health()).willReturn(new Health.Builder().unknown().withDetail("2", "2").build()); - this.registry = new DefaultContributorRegistry<>(); - } - - @Test - void createWhenContributorsIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> new DefaultContributorRegistry<>(null)) - .withMessage("Contributors must not be null"); - } - - @Test - void createWhenNameFactoryIsNullThrowsException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new DefaultContributorRegistry<>(Collections.emptyMap(), null)) - .withMessage("NameFactory must not be null"); - } - - @Test - void createUsesHealthIndicatorNameFactoryByDefault() { - this.registry = new DefaultContributorRegistry<>(Collections.singletonMap("oneHealthIndicator", this.one)); - assertThat(this.registry.getContributor("oneHealthIndicator")).isNull(); - assertThat(this.registry.getContributor("one")).isNotNull(); - } - - @Test - void createWithCustomNameFactoryAppliesFunctionToName() { - this.registry = new DefaultContributorRegistry<>(Collections.singletonMap("one", this.one), this::reverse); - assertThat(this.registry.getContributor("one")).isNull(); - assertThat(this.registry.getContributor("eno")).isNotNull(); - } - - @Test - void registerContributorWhenNameIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> this.registry.registerContributor(null, this.one)) - .withMessage("Name must not be null"); - } - - @Test - void registerContributorWhenContributorIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> this.registry.registerContributor("one", null)) - .withMessage("Contributor must not be null"); - } - - @Test - void registerContributorRegistersContributors() { - this.registry.registerContributor("one", this.one); - this.registry.registerContributor("two", this.two); - assertThat(this.registry).hasSize(2); - assertThat(this.registry.getContributor("one")).isSameAs(this.one); - assertThat(this.registry.getContributor("two")).isSameAs(this.two); - } - - @Test - void registerContributorWhenNameAlreadyUsedThrowsException() { - this.registry.registerContributor("one", this.one); - assertThatIllegalStateException().isThrownBy(() -> this.registry.registerContributor("one", this.two)) - .withMessageContaining("A contributor named \"one\" has already been registered"); - } - - @Test - void registerContributorUsesNameFactory() { - this.registry.registerContributor("oneHealthIndicator", this.one); - assertThat(this.registry.getContributor("oneHealthIndicator")).isNull(); - assertThat(this.registry.getContributor("one")).isNotNull(); - } - - @Test - void unregisterContributorUnregistersContributor() { - this.registry.registerContributor("one", this.one); - this.registry.registerContributor("two", this.two); - assertThat(this.registry).hasSize(2); - HealthIndicator two = this.registry.unregisterContributor("two"); - assertThat(two).isSameAs(this.two); - assertThat(this.registry).hasSize(1); - } - - @Test - void unregisterContributorWhenUnknownReturnsNull() { - this.registry.registerContributor("one", this.one); - assertThat(this.registry).hasSize(1); - HealthIndicator two = this.registry.unregisterContributor("two"); - assertThat(two).isNull(); - assertThat(this.registry).hasSize(1); - } - - @Test - void unregisterContributorUsesNameFactory() { - this.registry.registerContributor("oneHealthIndicator", this.one); - assertThat(this.registry.getContributor("oneHealthIndicator")).isNull(); - assertThat(this.registry.getContributor("one")).isNotNull(); - } - - @Test - void getContributorReturnsContributor() { - this.registry.registerContributor("one", this.one); - assertThat(this.registry.getContributor("one")).isEqualTo(this.one); - } - - @Test - void iteratorIteratesContributors() { - this.registry.registerContributor("one", this.one); - this.registry.registerContributor("two", this.two); - Iterator> iterator = this.registry.iterator(); - NamedContributor first = iterator.next(); - NamedContributor second = iterator.next(); - assertThat(iterator.hasNext()).isFalse(); - assertThat(first.getName()).isEqualTo("one"); - assertThat(first.getContributor()).isEqualTo(this.one); - assertThat(second.getName()).isEqualTo("two"); - assertThat(second.getContributor()).isEqualTo(this.two); - } - - private String reverse(String name) { - return new StringBuilder(name).reverse().toString(); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthContributorNameFactoryTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthContributorNameFactoryTests.java deleted file mode 100644 index d94a6ecc6b4..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthContributorNameFactoryTests.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link HealthContributorNameFactory}. - * - * @author Phillip Webb - */ -class HealthContributorNameFactoryTests { - - @Test - void applyWhenNameDoesNotEndWithSuffixReturnsName() { - assertThat(HealthContributorNameFactory.INSTANCE.apply("test")).isEqualTo("test"); - } - - @Test - void applyWhenNameEndsWithSuffixReturnsNewName() { - assertThat(HealthContributorNameFactory.INSTANCE.apply("testHealthIndicator")).isEqualTo("test"); - assertThat(HealthContributorNameFactory.INSTANCE.apply("testHealthContributor")).isEqualTo("test"); - } - - @Test - void applyWhenNameEndsWithSuffixInDifferentReturnsNewName() { - assertThat(HealthContributorNameFactory.INSTANCE.apply("testHEALTHindicator")).isEqualTo("test"); - assertThat(HealthContributorNameFactory.INSTANCE.apply("testHEALTHcontributor")).isEqualTo("test"); - } - - @Test - void applyWhenNameContainsSuffixReturnsName() { - assertThat(HealthContributorNameFactory.INSTANCE.apply("testHealthIndicatorTest")) - .isEqualTo("testHealthIndicatorTest"); - assertThat(HealthContributorNameFactory.INSTANCE.apply("testHealthContributorTest")) - .isEqualTo("testHealthContributorTest"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointSupportTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointSupportTests.java index 800d8dccb98..6295f01c8f6 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointSupportTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointSupportTests.java @@ -20,6 +20,8 @@ import java.time.Duration; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -27,24 +29,24 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.endpoint.ApiVersion; import org.springframework.boot.actuate.endpoint.SecurityContext; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; -import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult; +import org.springframework.boot.actuate.health.HealthEndpointSupport.Result; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** * Base class for {@link HealthEndpointSupport} tests. * - * @param the support type + * @param the endpoint type; + * @param the health type + * @param the descriptor type * @param the registry type * @param the contributor type - * @param the contributed health component type * @author Phillip Webb * @author Madhura Bhave */ -abstract class HealthEndpointSupportTests, R extends ContributorRegistry, C, T> { - - final R registry; +abstract class HealthEndpointSupportTests, H, D, R, C> { final Health up = Health.up().withDetail("spring", "boot").build(); @@ -54,217 +56,227 @@ abstract class HealthEndpointSupportTests, final TestHealthEndpointGroup allTheAs = new TestHealthEndpointGroup((name) -> name.startsWith("a")); - final HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("alltheas", this.allTheAs)); + final HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("alltheas", this.allTheAs)); - HealthEndpointSupportTests() { - this.registry = createRegistry(); + @Test + void getResultWhenPathIsEmptyUsesPrimaryGroup() { + R registry = createRegistry("test", createContributor(this.up)); + E support = create(registry, this.groups); + Result result = support.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); + assertThat(result.group()).isEqualTo(this.primaryGroup); + SystemHealthDescriptor descriptor = (SystemHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor.getComponents()).containsKey("test"); + assertThat(descriptor.getDetails()).isNull(); } @Test - void createWhenRegistryIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> create(null, this.groups)) - .withMessage("'registry' must not be null"); + void getResultWhenPathIsNotGroupReturnsResultFromPrimaryGroup() { + R registry = createRegistry("test", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); + assertThat(result.group()).isEqualTo(this.primaryGroup); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); } @Test - void createWhenGroupsIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> create(this.registry, null)) - .withMessage("'groups' must not be null"); + void getResultWhenPathIsGroupReturnsResultFromGroup() { + R registry = createRegistry("atest", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "alltheas", "atest"); + assertThat(result.group()).isEqualTo(this.allTheAs); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); } @Test - void getHealthWhenPathIsEmptyUsesPrimaryGroup() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false); - assertThat(result.getGroup()).isEqualTo(this.primaryGroup); - assertThat(getHealth(result)).isNotSameAs(this.up); - assertThat(getHealth(result).getStatus()).isEqualTo(Status.UP); - } - - @Test - void getHealthWhenPathIsNotGroupReturnsResultFromPrimaryGroup() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "test"); - assertThat(result.getGroup()).isEqualTo(this.primaryGroup); - assertThat(getHealth(result)).isEqualTo(this.up); - - } - - @Test - void getHealthWhenPathIsGroupReturnsResultFromGroup() { - this.registry.registerContributor("atest", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "alltheas", "atest"); - assertThat(result.getGroup()).isEqualTo(this.allTheAs); - assertThat(getHealth(result)).isEqualTo(this.up); - } - - @Test - void getHealthWhenAlwaysShowIsFalseAndGroupIsTrueShowsComponents() { + void getResultWhenAlwaysShowIsFalseAndGroupIsTrueShowsComponents() { C contributor = createContributor(this.up); - C compositeContributor = createCompositeContributor(Collections.singletonMap("spring", contributor)); - this.registry.registerContributor("test", compositeContributor); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "test"); - CompositeHealth health = (CompositeHealth) getHealth(result); - assertThat(health.getComponents()).containsKey("spring"); + C compositeContributor = createCompositeContributor(Map.of("spring", contributor)); + R registry = createRegistry("test", compositeContributor); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); + CompositeHealthDescriptor descriptor = (CompositeHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getComponents()).containsKey("spring"); } @Test - void getHealthWhenAlwaysShowIsFalseAndGroupIsFalseCannotAccessComponent() { + void getResultWhenAlwaysShowIsFalseAndGroupIsFalseCannotAccessComponent() { this.primaryGroup.setShowComponents(false); C contributor = createContributor(this.up); - C compositeContributor = createCompositeContributor(Collections.singletonMap("spring", contributor)); - this.registry.registerContributor("test", compositeContributor); - HealthEndpointSupport endpoint = create(this.registry, this.groups); - HealthResult rootResult = endpoint.getHealth(ApiVersion.V3, null, SecurityContext.NONE, false); - assertThat(((CompositeHealth) getHealth(rootResult)).getComponents()).isNullOrEmpty(); - HealthResult componentResult = endpoint.getHealth(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); + C compositeContributor = createCompositeContributor(Map.of("spring", contributor)); + R registry = createRegistry("test", compositeContributor); + E endpoint = create(registry, this.groups); + Result rootResult = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); + CompositeHealthDescriptor rootDescriptor = (CompositeHealthDescriptor) getDescriptor(rootResult); + assertThat(rootDescriptor.getComponents()).isNullOrEmpty(); + Result componentResult = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); assertThat(componentResult).isNull(); } @Test - void getHealthWhenAlwaysShowIsTrueShowsComponents() { + void getResultWhenAlwaysShowIsTrueShowsComponents() { this.primaryGroup.setShowComponents(true); C contributor = createContributor(this.up); - C compositeContributor = createCompositeContributor(Collections.singletonMap("spring", contributor)); - this.registry.registerContributor("test", compositeContributor); - HealthEndpointSupport endpoint = create(this.registry, this.groups); - HealthResult rootResult = endpoint.getHealth(ApiVersion.V3, null, SecurityContext.NONE, false); - assertThat(((CompositeHealth) getHealth(rootResult)).getComponents()).containsKey("test"); - HealthResult componentResult = endpoint.getHealth(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); - assertThat(((CompositeHealth) getHealth(componentResult)).getComponents()).containsKey("spring"); + C compositeContributor = createCompositeContributor(Map.of("spring", contributor)); + R registry = createRegistry("test", compositeContributor); + E endpoint = create(registry, this.groups); + Result rootResult = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); + CompositeHealthDescriptor rootDescriptor = (CompositeHealthDescriptor) getDescriptor(rootResult); + assertThat(rootDescriptor.getComponents()).containsKey("test"); + Result componentResult = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); + CompositeHealthDescriptor componentDescriptor = (CompositeHealthDescriptor) getDescriptor(componentResult); + assertThat(componentDescriptor.getComponents()).containsKey("spring"); } @Test - void getHealthWhenAlwaysShowIsFalseAndGroupIsTrueShowsDetails() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "test"); - assertThat(((Health) getHealth(result)).getDetails()).containsEntry("spring", "boot"); + void getResultWhenAlwaysShowIsFalseAndGroupIsTrueShowsDetails() { + R registry = createRegistry("test", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); } @Test - void getHealthWhenAlwaysShowIsFalseAndGroupIsFalseShowsNoDetails() { + void getResultWhenAlwaysShowIsFalseAndGroupIsFalseShowsNoDetails() { this.primaryGroup.setShowDetails(false); - this.registry.registerContributor("test", createContributor(this.up)); - HealthEndpointSupport endpoint = create(this.registry, this.groups); - HealthResult rootResult = endpoint.getHealth(ApiVersion.V3, null, SecurityContext.NONE, false); - HealthResult componentResult = endpoint.getHealth(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); - assertThat(((CompositeHealth) getHealth(rootResult)).getStatus()).isEqualTo(Status.UP); + R registry = createRegistry("test", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result rootResult = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); + Result componentResult = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "test"); + assertThat(getDescriptor(rootResult).getStatus()).isEqualTo(Status.UP); assertThat(componentResult).isNull(); } @Test - void getHealthWhenAlwaysShowIsTrueShowsDetails() { + void getResultWhenAlwaysShowIsTrueShowsDetails() { this.primaryGroup.setShowDetails(false); - this.registry.registerContributor("test", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - true, "test"); - assertThat(((Health) getHealth(result)).getDetails()).containsEntry("spring", "boot"); + R registry = createRegistry("test", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, true, "test"); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); } @Test - void getHealthWhenCompositeReturnsAggregateResult() { + void getResultWhenCompositeReturnsAggregateResult() { Map contributors = new LinkedHashMap<>(); contributors.put("a", createContributor(this.up)); contributors.put("b", createContributor(this.down)); - this.registry.registerContributor("test", createCompositeContributor(contributors)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false); - CompositeHealth root = (CompositeHealth) getHealth(result); - CompositeHealth component = (CompositeHealth) root.getComponents().get("test"); + R registry = createRegistry("test", createCompositeContributor(contributors)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); + CompositeHealthDescriptor root = (CompositeHealthDescriptor) getDescriptor(result); + CompositeHealthDescriptor component = (CompositeHealthDescriptor) root.getComponents().get("test"); assertThat(root.getStatus()).isEqualTo(Status.DOWN); assertThat(component.getStatus()).isEqualTo(Status.DOWN); assertThat(component.getComponents()).containsOnlyKeys("a", "b"); } @Test - void getHealthWhenPathDoesNotExistReturnsNull() { - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "missing"); + void getResultWhenPathDoesNotExistReturnsNull() { + R registry = createRegistry("test", createCompositeContributor(Collections.emptyMap())); + Result result = create(registry, this.groups).getResult(ApiVersion.V3, null, SecurityContext.NONE, false, + "missing"); assertThat(result).isNull(); } @Test - void getHealthWhenPathIsEmptyIncludesGroups() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false); - assertThat(((SystemHealth) getHealth(result)).getGroups()).containsOnly("alltheas"); + void getResultWhenPathIsEmptyIncludesGroups() { + R registry = createRegistry("test", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); + SystemHealthDescriptor descriptor = (SystemHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getGroups()).containsOnly("alltheas"); } @Test - void getHealthWhenPathIsGroupDoesNotIncludesGroups() { - this.registry.registerContributor("atest", createContributor(this.up)); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "alltheas"); - assertThat(getHealth(result)).isNotInstanceOf(SystemHealth.class); + void getResultWhenPathIsGroupDoesNotIncludesGroups() { + R registry = createRegistry("atest", createContributor(this.up)); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "alltheas"); + HealthDescriptor descriptor = getDescriptor(result); + assertThat(descriptor).isInstanceOf(CompositeHealthDescriptor.class); + assertThat(descriptor).isNotInstanceOf(SystemHealthDescriptor.class); } @Test - void getHealthWithEmptyCompositeReturnsNullResult() { // gh-18687 - this.registry.registerContributor("test", createCompositeContributor(Collections.emptyMap())); - HealthResult result = create(this.registry, this.groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false); + void getResultWithEmptyCompositeReturnsNullResult() { // gh-18687 + R registry = createRegistry("test", createCompositeContributor(Collections.emptyMap())); + E endpoint = create(registry, this.groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false); assertThat(result).isNull(); } @Test - void getHealthWhenGroupContainsCompositeContributorReturnsHealth() { + void getResultWhenGroupContainsCompositeContributorReturnsHealth() { C contributor = createContributor(this.up); - C compositeContributor = createCompositeContributor(Collections.singletonMap("spring", contributor)); - this.registry.registerContributor("test", compositeContributor); + C compositeContributor = createCompositeContributor(Map.of("spring", contributor)); + R registry = createRegistry("test", compositeContributor); TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup((name) -> name.startsWith("test")); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "testGroup"); - CompositeHealth health = (CompositeHealth) getHealth(result); - assertThat(health.getComponents()).containsKey("test"); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "testGroup"); + CompositeHealthDescriptor descriptor = (CompositeHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getComponents()).containsKey("test"); } @Test - void getHealthWhenGroupContainsComponentOfCompositeContributorReturnsHealth() { - CompositeHealth health = getCompositeHealth((name) -> name.equals("test/spring-1")); - assertThat(health.getComponents()).containsKey("test"); - CompositeHealth test = (CompositeHealth) health.getComponents().get("test"); + void getResultWhenGroupContainsComponentOfCompositeContributorReturnsHealth() { + CompositeHealthDescriptor descriptor = getCompositeHealthDescriptor((name) -> name.equals("test/spring-1")); + assertThat(descriptor.getComponents()).containsKey("test"); + CompositeHealthDescriptor test = (CompositeHealthDescriptor) descriptor.getComponents().get("test"); assertThat(test.getComponents()).containsKey("spring-1"); assertThat(test.getComponents()).doesNotContainKey("spring-2"); assertThat(test.getComponents()).doesNotContainKey("test"); } @Test - void getHealthWhenGroupExcludesComponentOfCompositeContributorReturnsHealth() { - CompositeHealth health = getCompositeHealth( + void getResultWhenGroupExcludesComponentOfCompositeContributorReturnsHealth() { + CompositeHealthDescriptor descriptor = getCompositeHealthDescriptor( (name) -> name.startsWith("test/") && !name.equals("test/spring-2")); - assertThat(health.getComponents()).containsKey("test"); - CompositeHealth test = (CompositeHealth) health.getComponents().get("test"); + assertThat(descriptor.getComponents()).containsKey("test"); + CompositeHealthDescriptor test = (CompositeHealthDescriptor) descriptor.getComponents().get("test"); assertThat(test.getComponents()).containsKey("spring-1"); assertThat(test.getComponents()).doesNotContainKey("spring-2"); } + private CompositeHealthDescriptor getCompositeHealthDescriptor(Predicate memberPredicate) { + C contributor1 = createContributor(this.up); + C contributor2 = createContributor(this.down); + Map contributors = new LinkedHashMap<>(); + contributors.put("spring-1", contributor1); + contributors.put("spring-2", contributor2); + C compositeContributor = createCompositeContributor(contributors); + R registry = createRegistry("test", compositeContributor); + TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup(memberPredicate); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "testGroup"); + return (CompositeHealthDescriptor) getDescriptor(result); + } + @Test - void getHealthForPathWhenGroupContainsComponentOfCompositeContributorReturnsHealth() { + void getResultForPathWhenGroupContainsComponentOfCompositeContributorReturnsHealth() { Map contributors = new LinkedHashMap<>(); contributors.put("spring-1", createNestedHealthContributor("spring-1")); contributors.put("spring-2", createNestedHealthContributor("spring-2")); C compositeContributor = createCompositeContributor(contributors); - this.registry.registerContributor("test", compositeContributor); + R registry = createRegistry("test", compositeContributor); TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup( (name) -> name.startsWith("test") && !name.equals("test/spring-1/b")); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "testGroup", "test"); - CompositeHealth health = (CompositeHealth) getHealth(result); - assertThat(health.getComponents()).containsKey("spring-1"); - assertThat(health.getComponents()).containsKey("spring-2"); - CompositeHealth spring1 = (CompositeHealth) health.getComponents().get("spring-1"); - CompositeHealth spring2 = (CompositeHealth) health.getComponents().get("spring-2"); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "testGroup", "test"); + CompositeHealthDescriptor descriptor = (CompositeHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getComponents()).containsKey("spring-1"); + assertThat(descriptor.getComponents()).containsKey("spring-2"); + CompositeHealthDescriptor spring1 = (CompositeHealthDescriptor) descriptor.getComponents().get("spring-1"); + CompositeHealthDescriptor spring2 = (CompositeHealthDescriptor) descriptor.getComponents().get("spring-2"); assertThat(spring1.getComponents()).containsKey("a"); assertThat(spring1.getComponents()).containsKey("c"); assertThat(spring1.getComponents()).doesNotContainKey("b"); @@ -274,37 +286,21 @@ abstract class HealthEndpointSupportTests, } @Test - void getHealthForComponentPathWhenNotPartOfGroup() { + void getResultForComponentPathWhenNotPartOfGroup() { Map contributors = new LinkedHashMap<>(); contributors.put("spring-1", createNestedHealthContributor("spring-1")); contributors.put("spring-2", createNestedHealthContributor("spring-2")); C compositeContributor = createCompositeContributor(contributors); - this.registry.registerContributor("test", compositeContributor); + R registry = createRegistry("test", compositeContributor); TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup( (name) -> name.startsWith("test") && !name.equals("test/spring-1/b")); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "testGroup", "test", "spring-1", "b"); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, null, SecurityContext.NONE, false, "testGroup", "test", + "spring-1", "b"); assertThat(result).isNull(); } - private CompositeHealth getCompositeHealth(Predicate memberPredicate) { - C contributor1 = createContributor(this.up); - C contributor2 = createContributor(this.down); - Map contributors = new LinkedHashMap<>(); - contributors.put("spring-1", contributor1); - contributors.put("spring-2", contributor2); - C compositeContributor = createCompositeContributor(contributors); - this.registry.registerContributor("test", compositeContributor); - TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup(memberPredicate); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, null, SecurityContext.NONE, - false, "testGroup"); - return (CompositeHealth) getHealth(result); - } - private C createNestedHealthContributor(String name) { Map map = new LinkedHashMap<>(); map.put("a", createContributor(Health.up().withDetail("hello", name + "-a").build())); @@ -314,58 +310,62 @@ abstract class HealthEndpointSupportTests, } @Test - void getHealthWhenGroupHasAdditionalPath() { - this.registry.registerContributor("test", createContributor(this.up)); + void getResultWhenGroupHasAdditionalPath() { + R registry = createRegistry("test", createContributor(this.up)); TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup((name) -> name.startsWith("test")); testGroup.setAdditionalPath(AdditionalHealthEndpointPath.from("server:/healthz")); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, WebServerNamespace.SERVER, - SecurityContext.NONE, false, "healthz"); - CompositeHealth health = (CompositeHealth) getHealth(result); - assertThat(health.getComponents()).containsKey("test"); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, false, + "healthz"); + CompositeHealthDescriptor descriptor = (CompositeHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getComponents()).containsKey("test"); } @Test - void getHealthWhenGroupHasAdditionalPathAndShowComponentsFalse() { - this.registry.registerContributor("test", createContributor(this.up)); + void getResultWhenGroupHasAdditionalPathAndShowComponentsFalse() { + R registry = createRegistry("test", createContributor(this.up)); TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup((name) -> name.startsWith("test")); testGroup.setAdditionalPath(AdditionalHealthEndpointPath.from("server:/healthz")); testGroup.setShowComponents(false); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, WebServerNamespace.SERVER, - SecurityContext.NONE, false, "healthz"); - CompositeHealth health = (CompositeHealth) getHealth(result); - assertThat(health.getStatus().getCode()).isEqualTo("UP"); - assertThat(health.getComponents()).isNull(); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, false, + "healthz"); + CompositeHealthDescriptor descriptor = (CompositeHealthDescriptor) getDescriptor(result); + assertThat(descriptor.getStatus().getCode()).isEqualTo("UP"); + assertThat(descriptor.getComponents()).isNull(); } @Test - void getComponentHealthWhenGroupHasAdditionalPathAndShowComponentsFalse() { - this.registry.registerContributor("test", createContributor(this.up)); + void getResultWithPathWhenGroupHasAdditionalPathAndShowComponentsFalse() { + R registry = createRegistry("test", createContributor(this.up)); TestHealthEndpointGroup testGroup = new TestHealthEndpointGroup((name) -> name.startsWith("test")); testGroup.setAdditionalPath(AdditionalHealthEndpointPath.from("server:/healthz")); testGroup.setShowComponents(false); - HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, - Collections.singletonMap("testGroup", testGroup)); - HealthResult result = create(this.registry, groups).getHealth(ApiVersion.V3, WebServerNamespace.SERVER, - SecurityContext.NONE, false, "healthz", "test"); + HealthEndpointGroups groups = HealthEndpointGroups.of(this.primaryGroup, Map.of("testGroup", testGroup)); + E endpoint = create(registry, groups); + Result result = endpoint.getResult(ApiVersion.V3, WebServerNamespace.SERVER, SecurityContext.NONE, false, + "healthz", "test"); assertThat(result).isNull(); } - protected final S create(R registry, HealthEndpointGroups groups) { + protected final E create(R registry, HealthEndpointGroups groups) { return create(registry, groups, null); } - protected abstract S create(R registry, HealthEndpointGroups groups, Duration slowIndicatorLoggingThreshold); + protected abstract E create(R registry, HealthEndpointGroups groups, Duration slowContributorLoggingThreshold); - protected abstract R createRegistry(); + protected final R createRegistry(String name, C contributor) { + return createRegistry((registrations) -> registrations.accept(name, contributor)); + } + + protected abstract R createRegistry(Consumer> intialRegistrations); protected abstract C createContributor(Health health); protected abstract C createCompositeContributor(Map contributors); - protected abstract HealthComponent getHealth(HealthResult result); + protected abstract HealthDescriptor getDescriptor(Result result); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java index e545a5ccb52..70147e00a5f 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java @@ -19,11 +19,20 @@ package org.springframework.boot.actuate.health; import java.time.Duration; import java.util.Collections; import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult; +import org.springframework.boot.actuate.health.HealthEndpointSupport.Result; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorRegistry; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -38,38 +47,42 @@ import static org.mockito.Mockito.mock; */ @ExtendWith(OutputCaptureExtension.class) class HealthEndpointTests extends - HealthEndpointSupportTests { + HealthEndpointSupportTests { @Test void healthReturnsSystemHealth() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthComponent health = create(this.registry, this.groups).health(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health).isInstanceOf(SystemHealth.class); + HealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + HealthEndpoint endpoint = create(registry, this.groups); + HealthDescriptor descriptor = endpoint.health(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor).isInstanceOf(SystemHealthDescriptor.class); } @Test void healthWithNoContributorReturnsUp() { - assertThat(this.registry).isEmpty(); - HealthComponent health = create(this.registry, - HealthEndpointGroups.of(mock(HealthEndpointGroup.class), Collections.emptyMap())) - .health(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health).isInstanceOf(Health.class); + HealthContributorRegistry registry = createRegistry(null); + HealthEndpointGroups groups = HealthEndpointGroups.of(mock(HealthEndpointGroup.class), Collections.emptyMap()); + HealthEndpoint endpoint = create(registry, groups); + HealthDescriptor descriptor = endpoint.health(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor).isInstanceOf(IndicatedHealthDescriptor.class); } @Test void healthWhenPathDoesNotExistReturnsNull() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthComponent health = create(this.registry, this.groups).healthForPath("missing"); - assertThat(health).isNull(); + HealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + HealthEndpoint endpoint = create(registry, this.groups); + HealthDescriptor descriptor = endpoint.healthForPath("missing"); + assertThat(descriptor).isNull(); } @Test void healthWhenPathExistsReturnsHealth() { - this.registry.registerContributor("test", createContributor(this.up)); - HealthComponent health = create(this.registry, this.groups).healthForPath("test"); - assertThat(health).isEqualTo(this.up); + HealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + HealthEndpoint endpoint = create(registry, this.groups); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) endpoint.healthForPath("test"); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); } @Test @@ -83,22 +96,23 @@ class HealthEndpointTests extends } return this.up; }; - this.registry.registerContributor("test", indicator); - create(this.registry, this.groups, Duration.ofMillis(10)).health(); + HealthContributorRegistry registry = createRegistry("test", indicator); + HealthEndpoint endpoint = create(registry, this.groups, Duration.ofMillis(10)); + endpoint.health(); assertThat(output).contains("Health contributor"); assertThat(output).contains("to respond"); - } @Override protected HealthEndpoint create(HealthContributorRegistry registry, HealthEndpointGroups groups, - Duration slowIndicatorLoggingThreshold) { - return new HealthEndpoint(registry, groups, slowIndicatorLoggingThreshold); + Duration slowContributorLoggingThreshold) { + return new HealthEndpoint(registry, null, groups, slowContributorLoggingThreshold); } @Override - protected HealthContributorRegistry createRegistry() { - return new DefaultHealthContributorRegistry(); + protected HealthContributorRegistry createRegistry( + Consumer> intialRegistrations) { + return new DefaultHealthContributorRegistry(Collections.emptyList(), intialRegistrations); } @Override @@ -112,8 +126,8 @@ class HealthEndpointTests extends } @Override - protected HealthComponent getHealth(HealthResult result) { - return result.getHealth(); + protected HealthDescriptor getDescriptor(Result result) { + return result.descriptor(); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHintsTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHintsTests.java index b975a3b8ce2..5db66f055c3 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHintsTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionRuntimeHintsTests.java @@ -37,7 +37,8 @@ class HealthEndpointWebExtensionRuntimeHintsTests { void shouldRegisterHints() { RuntimeHints runtimeHints = new RuntimeHints(); new HealthEndpointWebExtensionRuntimeHints().registerHints(runtimeHints, getClass().getClassLoader()); - Set> bindingTypes = Set.of(Health.class, SystemHealth.class, CompositeHealth.class); + Set> bindingTypes = Set.of(IndicatedHealthDescriptor.class, SystemHealthDescriptor.class, + CompositeHealthDescriptor.class); for (Class bindingType : bindingTypes) { assertThat(RuntimeHintsPredicates.reflection() .onType(bindingType) diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionTests.java index 4df9986571b..00021702a57 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointWebExtensionTests.java @@ -19,6 +19,8 @@ package org.springframework.boot.actuate.health; import java.time.Duration; import java.util.Collections; import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; @@ -26,7 +28,14 @@ import org.springframework.boot.actuate.endpoint.ApiVersion; import org.springframework.boot.actuate.endpoint.SecurityContext; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; -import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult; +import org.springframework.boot.actuate.health.HealthEndpointSupport.Result; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorRegistry; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -38,58 +47,65 @@ import static org.mockito.Mockito.mock; * @author Scott Frederick */ class HealthEndpointWebExtensionTests extends - HealthEndpointSupportTests { + HealthEndpointSupportTests { @Test void healthReturnsSystemHealth() { - this.registry.registerContributor("test", createContributor(this.up)); - WebEndpointResponse response = create(this.registry, this.groups).health(ApiVersion.LATEST, - WebServerNamespace.SERVER, SecurityContext.NONE); - HealthComponent health = response.getBody(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health).isInstanceOf(SystemHealth.class); + HealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + HealthEndpointWebExtension endpoint = create(registry, this.groups); + WebEndpointResponse response = endpoint.health(ApiVersion.LATEST, WebServerNamespace.SERVER, + SecurityContext.NONE); + HealthDescriptor descriptor = response.getBody(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor).isInstanceOf(SystemHealthDescriptor.class); assertThat(response.getStatus()).isEqualTo(200); } @Test void healthWithNoContributorReturnsUp() { - assertThat(this.registry).isEmpty(); - WebEndpointResponse response = create(this.registry, - HealthEndpointGroups.of(mock(HealthEndpointGroup.class), Collections.emptyMap())) - .health(ApiVersion.LATEST, WebServerNamespace.SERVER, SecurityContext.NONE); + HealthContributorRegistry registry = createRegistry(null); + HealthEndpointGroups groups = HealthEndpointGroups.of(mock(HealthEndpointGroup.class), Collections.emptyMap()); + HealthEndpointWebExtension endpoint = create(registry, groups); + WebEndpointResponse response = endpoint.health(ApiVersion.LATEST, WebServerNamespace.SERVER, + SecurityContext.NONE); assertThat(response.getStatus()).isEqualTo(200); - HealthComponent health = response.getBody(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health).isInstanceOf(Health.class); + HealthDescriptor descriptor = response.getBody(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor).isInstanceOf(IndicatedHealthDescriptor.class); } @Test void healthWhenPathDoesNotExistReturnsHttp404() { - this.registry.registerContributor("test", createContributor(this.up)); - WebEndpointResponse response = create(this.registry, this.groups).health(ApiVersion.LATEST, - WebServerNamespace.SERVER, SecurityContext.NONE, "missing"); + HealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + HealthEndpointWebExtension endpoint = create(registry, this.groups); + WebEndpointResponse response = endpoint.health(ApiVersion.LATEST, WebServerNamespace.SERVER, + SecurityContext.NONE, "missing"); assertThat(response.getBody()).isNull(); assertThat(response.getStatus()).isEqualTo(404); } @Test void healthWhenPathExistsReturnsHealth() { - this.registry.registerContributor("test", createContributor(this.up)); - WebEndpointResponse response = create(this.registry, this.groups).health(ApiVersion.LATEST, - WebServerNamespace.SERVER, SecurityContext.NONE, "test"); - assertThat(response.getBody()).isEqualTo(this.up); + HealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + HealthEndpointWebExtension endpoint = create(registry, this.groups); + WebEndpointResponse response = endpoint.health(ApiVersion.LATEST, WebServerNamespace.SERVER, + SecurityContext.NONE, "test"); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) response.getBody(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); assertThat(response.getStatus()).isEqualTo(200); } @Override protected HealthEndpointWebExtension create(HealthContributorRegistry registry, HealthEndpointGroups groups, Duration slowIndicatorLoggingThreshold) { - return new HealthEndpointWebExtension(registry, groups, slowIndicatorLoggingThreshold); + return new HealthEndpointWebExtension(registry, null, groups, slowIndicatorLoggingThreshold); } @Override - protected HealthContributorRegistry createRegistry() { - return new DefaultHealthContributorRegistry(); + protected HealthContributorRegistry createRegistry( + Consumer> intialRegistrations) { + return new DefaultHealthContributorRegistry(Collections.emptyList(), intialRegistrations); } @Override @@ -103,8 +119,8 @@ class HealthEndpointWebExtensionTests extends } @Override - protected HealthComponent getHealth(HealthResult result) { - return result.getHealth(); + protected HealthDescriptor getDescriptor(Result result) { + return result.descriptor(); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptorTests.java new file mode 100644 index 00000000000..1d7cd12a72b --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/IndicatedHealthDescriptorTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.health; + +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.health.contributor.Health; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link IndicatedHealthDescriptor}. + * + * @author Phillip Webb + */ +class IndicatedHealthDescriptorTests { + + @Test + void serializeWithJacksonReturnsValidJson() throws Exception { + IndicatedHealthDescriptor descriptor = new IndicatedHealthDescriptor( + Health.outOfService().withDetail("spring", "boot").build()); + ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo(""" + {"details":{"spring":"boot"},"status":"OUT_OF_SERVICE"}"""); + } + + @Test + void serializeWithJacksonWhenEmptyDetailsReturnsValidJson() throws Exception { + IndicatedHealthDescriptor descriptor = new IndicatedHealthDescriptor(Health.outOfService().build()); + ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo(""" + {"status":"OUT_OF_SERVICE"}"""); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorTests.java deleted file mode 100644 index c4dc797feb3..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorTests.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Tests for {@link NamedContributor}. - * - * @author Phillip Webb - */ -class NamedContributorTests { - - @Test - void ofNameAndContributorCreatesContributor() { - NamedContributor contributor = NamedContributor.of("one", "two"); - assertThat(contributor.getName()).isEqualTo("one"); - assertThat(contributor.getContributor()).isEqualTo("two"); - } - - @Test - void ofWhenNameIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> NamedContributor.of(null, "two")) - .withMessage("'name' must not be null"); - } - - @Test - void ofWhenContributorIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> NamedContributor.of("one", null)) - .withMessage("'contributor' must not be null"); - - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtensionTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtensionTests.java index ae7f07a3501..b99e4d616d5 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtensionTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthEndpointWebExtensionTests.java @@ -19,6 +19,8 @@ package org.springframework.boot.actuate.health; import java.time.Duration; import java.util.Collections; import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; @@ -26,7 +28,14 @@ import reactor.core.publisher.Mono; import org.springframework.boot.actuate.endpoint.ApiVersion; import org.springframework.boot.actuate.endpoint.SecurityContext; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; -import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult; +import org.springframework.boot.actuate.health.HealthEndpointSupport.Result; +import org.springframework.boot.health.contributor.CompositeReactiveHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Status; +import org.springframework.boot.health.registry.DefaultReactiveHealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -38,37 +47,40 @@ import static org.mockito.Mockito.mock; * @author Scott Frederick */ class ReactiveHealthEndpointWebExtensionTests extends - HealthEndpointSupportTests> { + HealthEndpointSupportTests, Mono, ReactiveHealthContributorRegistry, ReactiveHealthContributor> { @Test void healthReturnsSystemHealth() { - this.registry.registerContributor("test", createContributor(this.up)); - WebEndpointResponse response = create(this.registry, this.groups) + ReactiveHealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + ReactiveHealthEndpointWebExtension endpoint = create(registry, this.groups); + WebEndpointResponse response = endpoint .health(ApiVersion.LATEST, null, SecurityContext.NONE) .block(); - HealthComponent health = response.getBody(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health).isInstanceOf(SystemHealth.class); + HealthDescriptor descriptor = response.getBody(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor).isInstanceOf(SystemHealthDescriptor.class); assertThat(response.getStatus()).isEqualTo(200); } @Test void healthWithNoContributorReturnsUp() { - assertThat(this.registry).isEmpty(); - WebEndpointResponse response = create(this.registry, - HealthEndpointGroups.of(mock(HealthEndpointGroup.class), Collections.emptyMap())) + ReactiveHealthContributorRegistry registry = createRegistry(null); + HealthEndpointGroups groups = HealthEndpointGroups.of(mock(HealthEndpointGroup.class), Collections.emptyMap()); + ReactiveHealthEndpointWebExtension endpoint = create(registry, groups); + WebEndpointResponse response = endpoint .health(ApiVersion.LATEST, null, SecurityContext.NONE) .block(); assertThat(response.getStatus()).isEqualTo(200); - HealthComponent health = response.getBody(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health).isInstanceOf(Health.class); + HealthDescriptor descriptor = response.getBody(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor).isInstanceOf(IndicatedHealthDescriptor.class); } @Test void healthWhenPathDoesNotExistReturnsHttp404() { - this.registry.registerContributor("test", createContributor(this.up)); - WebEndpointResponse response = create(this.registry, this.groups) + ReactiveHealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + ReactiveHealthEndpointWebExtension endpoint = create(registry, this.groups); + WebEndpointResponse response = endpoint .health(ApiVersion.LATEST, null, SecurityContext.NONE, "missing") .block(); assertThat(response.getBody()).isNull(); @@ -77,23 +89,27 @@ class ReactiveHealthEndpointWebExtensionTests extends @Test void healthWhenPathExistsReturnsHealth() { - this.registry.registerContributor("test", createContributor(this.up)); - WebEndpointResponse response = create(this.registry, this.groups) + ReactiveHealthContributorRegistry registry = createRegistry("test", createContributor(this.up)); + ReactiveHealthEndpointWebExtension endpoint = create(registry, this.groups); + WebEndpointResponse response = endpoint .health(ApiVersion.LATEST, null, SecurityContext.NONE, "test") .block(); - assertThat(response.getBody()).isEqualTo(this.up); + IndicatedHealthDescriptor descriptor = (IndicatedHealthDescriptor) response.getBody(); + assertThat(descriptor.getStatus()).isEqualTo(Status.UP); + assertThat(descriptor.getDetails()).containsEntry("spring", "boot"); assertThat(response.getStatus()).isEqualTo(200); } @Override protected ReactiveHealthEndpointWebExtension create(ReactiveHealthContributorRegistry registry, - HealthEndpointGroups groups, Duration slowIndicatorLoggingThreshold) { - return new ReactiveHealthEndpointWebExtension(registry, groups, slowIndicatorLoggingThreshold); + HealthEndpointGroups groups, Duration slowContributorLoggingThreshold) { + return new ReactiveHealthEndpointWebExtension(registry, null, groups, slowContributorLoggingThreshold); } @Override - protected ReactiveHealthContributorRegistry createRegistry() { - return new DefaultReactiveHealthContributorRegistry(); + protected ReactiveHealthContributorRegistry createRegistry( + Consumer> intialRegistrations) { + return new DefaultReactiveHealthContributorRegistry(Collections.emptyList(), intialRegistrations); } @Override @@ -108,8 +124,8 @@ class ReactiveHealthEndpointWebExtensionTests extends } @Override - protected HealthComponent getHealth(HealthResult> result) { - return result.getHealth().block(); + protected HealthDescriptor getDescriptor(Result> result) { + return result.descriptor().block(); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorImplementationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorImplementationTests.java index 8f63de4ef9c..5e4da2143c3 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorImplementationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorImplementationTests.java @@ -23,7 +23,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.boot.actuate.health.Health.Builder; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -73,7 +74,7 @@ class ReactiveHealthIndicatorImplementationTests { } @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.just(builder.up().build()); } @@ -86,7 +87,7 @@ class ReactiveHealthIndicatorImplementationTests { } @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.error(new UnsupportedOperationException()); } @@ -100,7 +101,7 @@ class ReactiveHealthIndicatorImplementationTests { } @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { throw new RuntimeException(); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapperTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapperTests.java index 4b7ce60d03c..37ad794fbf0 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapperTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleHttpCodeStatusMapperTests.java @@ -22,6 +22,7 @@ import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java index a1735af69d5..64c5233125a 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java @@ -18,6 +18,8 @@ package org.springframework.boot.actuate.health; import org.junit.jupiter.api.Test; +import org.springframework.boot.health.contributor.Status; + import static org.assertj.core.api.Assertions.assertThat; /** diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthDescriptorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthDescriptorTests.java new file mode 100644 index 00000000000..0d1f039c4d3 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthDescriptorTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.health; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.actuate.endpoint.ApiVersion; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SystemHealthDescriptor}. + * + * @author Phillip Webb + */ +class SystemHealthDescriptorTests { + + @Test + void serializeWithJacksonReturnsValidJson() throws Exception { + Map components = new LinkedHashMap<>(); + components.put("db1", new IndicatedHealthDescriptor(Health.up().build())); + components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build())); + Set groups = new LinkedHashSet<>(Arrays.asList("liveness", "readiness")); + SystemHealthDescriptor descriptor = new SystemHealthDescriptor(ApiVersion.V3, Status.UP, components, groups); + ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo( + """ + {"components":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"groups":["liveness","readiness"],"status":"UP"}"""); + } + + @Test + void serializeWhenNoGroupsWithJacksonReturnsValidJson() throws Exception { + Map components = new LinkedHashMap<>(); + components.put("db1", new IndicatedHealthDescriptor(Health.up().build())); + components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build())); + SystemHealthDescriptor descriptor = new SystemHealthDescriptor(ApiVersion.V3, Status.UP, components, null); + ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo(""" + {"components":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}"""); + } + + @Test // gh-26797 + void serializeV2WithJacksonAndDisabledCanOverrideAccessModifiersReturnsValidJson() throws Exception { + Map components = new LinkedHashMap<>(); + components.put("db1", new IndicatedHealthDescriptor(Health.up().build())); + components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build())); + SystemHealthDescriptor descriptor = new SystemHealthDescriptor(ApiVersion.V2, Status.UP, components, null); + ObjectMapper mapper = JsonMapper.builder() + .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY) + .disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS) + .build(); + String json = mapper.writeValueAsString(descriptor); + assertThat(json).isEqualTo(""" + {"details":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}"""); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthTests.java deleted file mode 100644 index 8779b4a9304..00000000000 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SystemHealthTests.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.health; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.endpoint.ApiVersion; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SystemHealth}. - * - * @author Phillip Webb - */ -class SystemHealthTests { - - @Test - void serializeWithJacksonReturnsValidJson() throws Exception { - Map components = new LinkedHashMap<>(); - components.put("db1", Health.up().build()); - components.put("db2", Health.down().withDetail("a", "b").build()); - Set groups = new LinkedHashSet<>(Arrays.asList("liveness", "readiness")); - CompositeHealth health = new SystemHealth(ApiVersion.V3, Status.UP, components, groups); - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(health); - assertThat(json).isEqualTo("{\"status\":\"UP\",\"components\":{\"db1\":{\"status\":\"UP\"}," - + "\"db2\":{\"status\":\"DOWN\",\"details\":{\"a\":\"b\"}}}," - + "\"groups\":[\"liveness\",\"readiness\"]}"); - } - -} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/ssl/SslHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/ssl/SslHealthIndicatorTests.java index 31ddbaa339a..82977a144ba 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/ssl/SslHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/ssl/SslHealthIndicatorTests.java @@ -23,8 +23,8 @@ import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.info.SslInfo; import org.springframework.boot.info.SslInfo.BundleInfo; import org.springframework.boot.info.SslInfo.CertificateChainInfo; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java index 3cb3219359e..a6931783431 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java @@ -24,9 +24,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.unit.DataSize; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-amqp/build.gradle b/spring-boot-project/spring-boot-amqp/build.gradle index 0b46195fd2b..c2ef2a194c5 100644 --- a/spring-boot-project/spring-boot-amqp/build.gradle +++ b/spring-boot-project/spring-boot-amqp/build.gradle @@ -35,9 +35,9 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-tx")) - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("io.micrometer:micrometer-core") diff --git a/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java index 55e78d11d92..689e176dc30 100644 --- a/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java @@ -18,16 +18,16 @@ package org.springframework.boot.amqp.autoconfigure.health; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.amqp.actuate.health.RabbitHealthIndicator; import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration; +import org.springframework.boot.amqp.health.RabbitHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/actuate/health/RabbitHealthIndicator.java b/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/RabbitHealthIndicator.java similarity index 86% rename from spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/actuate/health/RabbitHealthIndicator.java rename to spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/RabbitHealthIndicator.java index 80367b8cad5..8f0b9a91165 100644 --- a/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/actuate/health/RabbitHealthIndicator.java +++ b/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/RabbitHealthIndicator.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.springframework.boot.amqp.actuate.health; +package org.springframework.boot.amqp.health; import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/actuate/health/package-info.java b/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/actuate/health/package-info.java rename to spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/package-info.java index fc4ddefeb30..cacab20fb2a 100644 --- a/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for AMQP and RabbitMQ. */ -package org.springframework.boot.amqp.actuate.health; +package org.springframework.boot.amqp.health; diff --git a/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java index f90395233ed..8739399d0aa 100644 --- a/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java @@ -18,10 +18,10 @@ package org.springframework.boot.amqp.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; -import org.springframework.boot.amqp.actuate.health.RabbitHealthIndicator; import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration; +import org.springframework.boot.amqp.health.RabbitHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/actuate/health/RabbitHealthIndicatorTests.java b/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/health/RabbitHealthIndicatorTests.java similarity index 94% rename from spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/actuate/health/RabbitHealthIndicatorTests.java rename to spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/health/RabbitHealthIndicatorTests.java index 215122061ff..780f6826009 100644 --- a/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/actuate/health/RabbitHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/health/RabbitHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.amqp.actuate.health; +package org.springframework.boot.amqp.health; import java.util.Collections; @@ -27,8 +27,8 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.amqp.rabbit.core.ChannelCallback; import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; diff --git a/spring-boot-project/spring-boot-cassandra/build.gradle b/spring-boot-project/spring-boot-cassandra/build.gradle index beea9d88d78..e0c460a8755 100644 --- a/spring-boot-project/spring-boot-cassandra/build.gradle +++ b/spring-boot-project/spring-boot-cassandra/build.gradle @@ -30,9 +30,9 @@ dependencies { api(project(":spring-boot-project:spring-boot")) api("org.apache.cassandra:java-driver-core") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("io.projectreactor:reactor-core") optional("org.testcontainers:cassandra") diff --git a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfiguration.java index 5a339212ed2..af22206d0a5 100644 --- a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfiguration.java @@ -18,13 +18,13 @@ package org.springframework.boot.cassandra.autoconfigure.health; import com.datastax.oss.driver.api.core.CqlSession; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.cassandra.actuate.health.CassandraDriverHealthIndicator; import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration; import org.springframework.boot.cassandra.autoconfigure.health.CassandraHealthContributorConfigurations.CassandraDriverConfiguration; +import org.springframework.boot.cassandra.health.CassandraDriverHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; import org.springframework.context.annotation.Import; /** diff --git a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorConfigurations.java b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorConfigurations.java index 6a65bbac67d..582d775145e 100644 --- a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorConfigurations.java +++ b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorConfigurations.java @@ -21,14 +21,14 @@ import java.util.Map; import com.datastax.oss.driver.api.core.CqlSession; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.cassandra.actuate.health.CassandraDriverHealthIndicator; -import org.springframework.boot.cassandra.actuate.health.CassandraDriverReactiveHealthIndicator; +import org.springframework.boot.cassandra.health.CassandraDriverHealthIndicator; +import org.springframework.boot.cassandra.health.CassandraDriverReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfiguration.java index 9f2fd6c6c89..4d80185751e 100644 --- a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfiguration.java @@ -19,13 +19,13 @@ package org.springframework.boot.cassandra.autoconfigure.health; import com.datastax.oss.driver.api.core.CqlSession; import reactor.core.publisher.Flux; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.cassandra.actuate.health.CassandraDriverReactiveHealthIndicator; import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration; import org.springframework.boot.cassandra.autoconfigure.health.CassandraHealthContributorConfigurations.CassandraReactiveDriverConfiguration; +import org.springframework.boot.cassandra.health.CassandraDriverReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; import org.springframework.context.annotation.Import; /** diff --git a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverHealthIndicator.java b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/CassandraDriverHealthIndicator.java similarity index 86% rename from spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverHealthIndicator.java rename to spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/CassandraDriverHealthIndicator.java index bd1bd68297d..a83e1d0cd8b 100644 --- a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverHealthIndicator.java +++ b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/CassandraDriverHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.cassandra.actuate.health; +package org.springframework.boot.cassandra.health; import java.util.Collection; import java.util.Optional; @@ -23,10 +23,10 @@ import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.metadata.NodeState; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverReactiveHealthIndicator.java b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/CassandraDriverReactiveHealthIndicator.java similarity index 86% rename from spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/CassandraDriverReactiveHealthIndicator.java index 953b0bbcbdb..3be8d4637a4 100644 --- a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/CassandraDriverReactiveHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.cassandra.actuate.health; +package org.springframework.boot.cassandra.health; import java.util.Collection; import java.util.Optional; @@ -24,10 +24,10 @@ import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.metadata.NodeState; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/package-info.java b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/package-info.java rename to spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/package-info.java index 7f8c28ee91f..a50479056a4 100644 --- a/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-cassandra/src/main/java/org/springframework/boot/cassandra/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for Cassandra. */ -package org.springframework.boot.cassandra.actuate.health; +package org.springframework.boot.cassandra.health; diff --git a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfigurationTests.java index d6f2af09dda..019ffb76d0c 100644 --- a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraHealthContributorAutoConfigurationTests.java @@ -19,9 +19,9 @@ package org.springframework.boot.cassandra.autoconfigure.health; import com.datastax.oss.driver.api.core.CqlSession; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.cassandra.actuate.health.CassandraDriverHealthIndicator; +import org.springframework.boot.cassandra.health.CassandraDriverHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfigurationTests.java index 55cb01fc044..f8011ab7be0 100644 --- a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/autoconfigure/health/CassandraReactiveHealthContributorAutoConfigurationTests.java @@ -19,9 +19,9 @@ package org.springframework.boot.cassandra.autoconfigure.health; import com.datastax.oss.driver.api.core.CqlSession; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.cassandra.actuate.health.CassandraDriverReactiveHealthIndicator; +import org.springframework.boot.cassandra.health.CassandraDriverReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverHealthIndicatorTests.java b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/health/CassandraDriverHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverHealthIndicatorTests.java rename to spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/health/CassandraDriverHealthIndicatorTests.java index b3378ebbcd8..fe6ac9ea725 100644 --- a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/health/CassandraDriverHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.cassandra.actuate.health; +package org.springframework.boot.cassandra.health; import java.util.ArrayList; import java.util.Collections; @@ -31,8 +31,8 @@ import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.metadata.NodeState; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; diff --git a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/health/CassandraDriverReactiveHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/health/CassandraDriverReactiveHealthIndicatorTests.java index 6020f36622c..c8472006b27 100644 --- a/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/actuate/health/CassandraDriverReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-cassandra/src/test/java/org/springframework/boot/cassandra/health/CassandraDriverReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.cassandra.actuate.health; +package org.springframework.boot.cassandra.health; import java.time.Duration; import java.util.ArrayList; @@ -34,8 +34,8 @@ import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; diff --git a/spring-boot-project/spring-boot-cloudfoundry/build.gradle b/spring-boot-project/spring-boot-cloudfoundry/build.gradle index 820c7c79578..af39ade1506 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/build.gradle +++ b/spring-boot-project/spring-boot-cloudfoundry/build.gradle @@ -31,6 +31,7 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-security")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-restclient")) optional(project(":spring-boot-project:spring-boot-webclient")) optional(project(":spring-boot-project:spring-boot-webflux")) diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtension.java b/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtension.java index 92a632992e7..911b5f6529e 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtension.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtension.java @@ -25,7 +25,7 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.Selector; import org.springframework.boot.actuate.endpoint.annotation.Selector.Match; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; -import org.springframework.boot.actuate.health.HealthComponent; +import org.springframework.boot.actuate.health.HealthDescriptor; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.EndpointCloudFoundryExtension; @@ -47,12 +47,12 @@ public class CloudFoundryReactiveHealthEndpointWebExtension { } @ReadOperation - public Mono> health(ApiVersion apiVersion) { + public Mono> health(ApiVersion apiVersion) { return this.delegate.health(apiVersion, null, SecurityContext.NONE, true); } @ReadOperation - public Mono> health(ApiVersion apiVersion, + public Mono> health(ApiVersion apiVersion, @Selector(match = Match.ALL_REMAINING) String... path) { return this.delegate.health(apiVersion, null, SecurityContext.NONE, true, path); } diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtension.java b/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtension.java index ccb09758761..2ccc2a11353 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtension.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtension.java @@ -23,7 +23,7 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.Selector; import org.springframework.boot.actuate.endpoint.annotation.Selector.Match; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; -import org.springframework.boot.actuate.health.HealthComponent; +import org.springframework.boot.actuate.health.HealthDescriptor; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointWebExtension; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.EndpointCloudFoundryExtension; @@ -45,12 +45,12 @@ public class CloudFoundryHealthEndpointWebExtension { } @ReadOperation - public WebEndpointResponse health(ApiVersion apiVersion) { + public WebEndpointResponse health(ApiVersion apiVersion) { return this.delegate.health(apiVersion, null, SecurityContext.NONE, true); } @ReadOperation - public WebEndpointResponse health(ApiVersion apiVersion, + public WebEndpointResponse health(ApiVersion apiVersion, @Selector(match = Match.ALL_REMAINING) String... path) { return this.delegate.health(apiVersion, null, SecurityContext.NONE, true, path); } diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/CloudFoundryWebEndpointDiscovererTests.java b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/CloudFoundryWebEndpointDiscovererTests.java index d92c8b41508..50ee5c21d47 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/CloudFoundryWebEndpointDiscovererTests.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/CloudFoundryWebEndpointDiscovererTests.java @@ -38,10 +38,10 @@ import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint; import org.springframework.boot.actuate.endpoint.web.PathMapper; import org.springframework.boot.actuate.endpoint.web.WebOperation; import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension; -import org.springframework.boot.actuate.health.HealthContributorRegistry; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroups; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.CloudFoundryWebEndpointDiscoverer.CloudFoundryWebEndpointDiscovererRuntimeHints; +import org.springframework.boot.health.registry.HealthContributorRegistry; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -128,7 +128,7 @@ class CloudFoundryWebEndpointDiscovererTests { HealthEndpoint healthEndpoint() { HealthContributorRegistry registry = mock(HealthContributorRegistry.class); HealthEndpointGroups groups = mock(HealthEndpointGroups.class); - return new HealthEndpoint(registry, groups, null); + return new HealthEndpoint(registry, null, groups, null); } @Bean diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtensionTests.java b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtensionTests.java index a03cbd88c9b..766f13d3586 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtensionTests.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/CloudFoundryReactiveHealthEndpointWebExtensionTests.java @@ -22,16 +22,18 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.actuate.endpoint.ApiVersion; -import org.springframework.boot.actuate.health.CompositeHealth; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthComponent; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.actuate.health.CompositeHealthDescriptor; +import org.springframework.boot.actuate.health.HealthDescriptor; +import org.springframework.boot.actuate.health.IndicatedHealthDescriptor; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.security.autoconfigure.reactive.ReactiveSecurityAutoConfiguration; @@ -61,7 +63,7 @@ class CloudFoundryReactiveHealthEndpointWebExtensionTests { WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class, - ReactiveCloudFoundryActuatorAutoConfiguration.class)) + HealthContributorRegistryAutoConfiguration.class)) .withUserConfiguration(TestHealthIndicator.class, UserDetailsServiceConfiguration.class); @Test @@ -69,9 +71,13 @@ class CloudFoundryReactiveHealthEndpointWebExtensionTests { this.contextRunner.run((context) -> { CloudFoundryReactiveHealthEndpointWebExtension extension = context .getBean(CloudFoundryReactiveHealthEndpointWebExtension.class); - HealthComponent body = extension.health(ApiVersion.V3).block(Duration.ofSeconds(30)).getBody(); - HealthComponent health = ((CompositeHealth) body).getComponents().entrySet().iterator().next().getValue(); - assertThat(((Health) health).getDetails()).containsEntry("spring", "boot"); + HealthDescriptor descriptor = extension.health(ApiVersion.V3).block(Duration.ofSeconds(30)).getBody(); + HealthDescriptor component = ((CompositeHealthDescriptor) descriptor).getComponents() + .entrySet() + .iterator() + .next() + .getValue(); + assertThat(((IndicatedHealthDescriptor) component).getDetails()).containsEntry("spring", "boot"); }); } diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java index 476fe752906..6daaad18e9e 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java @@ -34,7 +34,6 @@ import reactor.netty.http.HttpResources; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration; @@ -50,6 +49,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.servlet.CloudFoundryInfoEndpointWebExtension; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.security.autoconfigure.reactive.ReactiveSecurityAutoConfiguration; @@ -95,15 +96,15 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests { private static final String V3_JSON = ApiVersion.V3.getProducedMimeType().toString(); private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class, WebFluxAutoConfiguration.class, - JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, WebClientCustomizerConfig.class, - WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class, - EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class, - InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class, - ProjectInfoAutoConfiguration.class, ReactiveCloudFoundryActuatorAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class, + WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, + WebClientCustomizerConfig.class, WebClientAutoConfiguration.class, + ManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class, + WebEndpointAutoConfiguration.class, HealthContributorAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class, + ProjectInfoAutoConfiguration.class, ReactiveCloudFoundryActuatorAutoConfiguration.class)) .withUserConfiguration(UserDetailsServiceConfiguration.class); private static final String BASE_PATH = "/cloudfoundryapplication"; diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryActuatorAutoConfigurationTests.java b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryActuatorAutoConfigurationTests.java index bacedb515a7..709390a0b1c 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryActuatorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryActuatorAutoConfigurationTests.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.actuate.endpoint.ApiVersion; @@ -39,6 +38,8 @@ import org.springframework.boot.actuate.endpoint.web.WebOperation; import org.springframework.boot.actuate.endpoint.web.WebOperationRequestPredicate; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.restclient.autoconfigure.RestTemplateAutoConfiguration; @@ -290,7 +291,7 @@ class CloudFoundryActuatorAutoConfigurationTests { .withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com") .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class)) + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class)) .run((context) -> { Collection endpoints = context .getBean("cloudFoundryWebEndpointServletHandlerMapping", diff --git a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtensionTests.java b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtensionTests.java index 1865ab3c1eb..129c1497081 100644 --- a/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtensionTests.java +++ b/spring-boot-project/spring-boot-cloudfoundry/src/test/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/servlet/CloudFoundryHealthEndpointWebExtensionTests.java @@ -20,16 +20,18 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.actuate.endpoint.ApiVersion; -import org.springframework.boot.actuate.health.CompositeHealth; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthComponent; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.actuate.health.CompositeHealthDescriptor; +import org.springframework.boot.actuate.health.HealthDescriptor; +import org.springframework.boot.actuate.health.IndicatedHealthDescriptor; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.restclient.autoconfigure.RestTemplateAutoConfiguration; @@ -56,7 +58,8 @@ class CloudFoundryHealthEndpointWebExtensionTests { RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class)) + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + CloudFoundryActuatorAutoConfiguration.class)) .withUserConfiguration(TestHealthIndicator.class); @Test @@ -64,9 +67,13 @@ class CloudFoundryHealthEndpointWebExtensionTests { this.contextRunner.run((context) -> { CloudFoundryHealthEndpointWebExtension extension = context .getBean(CloudFoundryHealthEndpointWebExtension.class); - HealthComponent body = extension.health(ApiVersion.V3).getBody(); - HealthComponent health = ((CompositeHealth) body).getComponents().entrySet().iterator().next().getValue(); - assertThat(((Health) health).getDetails()).containsEntry("spring", "boot"); + HealthDescriptor descriptor = extension.health(ApiVersion.V3).getBody(); + HealthDescriptor component = ((CompositeHealthDescriptor) descriptor).getComponents() + .entrySet() + .iterator() + .next() + .getValue(); + assertThat(((IndicatedHealthDescriptor) component).getDetails()).containsEntry("spring", "boot"); }); } diff --git a/spring-boot-project/spring-boot-couchbase/build.gradle b/spring-boot-project/spring-boot-couchbase/build.gradle index 0461841fc6e..adc43a90fbf 100644 --- a/spring-boot-project/spring-boot-couchbase/build.gradle +++ b/spring-boot-project/spring-boot-couchbase/build.gradle @@ -30,8 +30,8 @@ dependencies { api(project(":spring-boot-project:spring-boot")) api("com.couchbase.client:java-client") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional(project(":spring-boot-project:spring-boot-jackson")) optional("org.testcontainers:couchbase") diff --git a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfiguration.java index 7f3528369f7..8db89256eb9 100644 --- a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.couchbase.autoconfigure.health; import com.couchbase.client.java.Cluster; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.couchbase.actuate.health.CouchbaseHealthIndicator; import org.springframework.boot.couchbase.autoconfigure.CouchbaseAutoConfiguration; +import org.springframework.boot.couchbase.health.CouchbaseHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfiguration.java index 1506467ea3d..a56a87ec511 100644 --- a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfiguration.java @@ -20,16 +20,16 @@ import com.couchbase.client.java.Cluster; import reactor.core.publisher.Flux; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.couchbase.actuate.health.CouchbaseReactiveHealthIndicator; import org.springframework.boot.couchbase.autoconfigure.CouchbaseAutoConfiguration; +import org.springframework.boot.couchbase.health.CouchbaseReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealth.java b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseHealth.java similarity index 92% rename from spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealth.java rename to spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseHealth.java index e4045d9807d..c8cc6d6bc17 100644 --- a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealth.java +++ b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseHealth.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.couchbase.actuate.health; +package org.springframework.boot.couchbase.health; import java.util.Collection; import java.util.HashMap; @@ -24,7 +24,7 @@ import com.couchbase.client.core.diagnostics.ClusterState; import com.couchbase.client.core.diagnostics.DiagnosticsResult; import com.couchbase.client.core.diagnostics.EndpointDiagnostics; -import org.springframework.boot.actuate.health.Health.Builder; +import org.springframework.boot.health.contributor.Health; /** * Details of Couchbase's health. @@ -39,7 +39,7 @@ class CouchbaseHealth { this.diagnostics = diagnostics; } - void applyTo(Builder builder) { + void applyTo(Health.Builder builder) { builder = isCouchbaseUp(this.diagnostics) ? builder.up() : builder.down(); builder.withDetail("sdk", this.diagnostics.sdk()); builder.withDetail("endpoints", diff --git a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealthIndicator.java b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseHealthIndicator.java similarity index 85% rename from spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealthIndicator.java rename to spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseHealthIndicator.java index 454cb1d277a..545ff120b01 100644 --- a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealthIndicator.java +++ b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseHealthIndicator.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.couchbase.actuate.health; +package org.springframework.boot.couchbase.health; import com.couchbase.client.core.diagnostics.DiagnosticsResult; import com.couchbase.client.java.Cluster; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseReactiveHealthIndicator.java b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseReactiveHealthIndicator.java similarity index 84% rename from spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseReactiveHealthIndicator.java index c86c3b5c180..31b103543ca 100644 --- a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/CouchbaseReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/CouchbaseReactiveHealthIndicator.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.couchbase.actuate.health; +package org.springframework.boot.couchbase.health; import com.couchbase.client.java.Cluster; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; /** * A {@link ReactiveHealthIndicator} for Couchbase. diff --git a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/package-info.java b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/package-info.java rename to spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/package-info.java index fefbe96a39f..04ad2ba4da0 100644 --- a/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-couchbase/src/main/java/org/springframework/boot/couchbase/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for Couchbase. */ -package org.springframework.boot.couchbase.actuate.health; +package org.springframework.boot.couchbase.health; diff --git a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfigurationTests.java index fe8a682f326..02e94ac0885 100644 --- a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseHealthContributorAutoConfigurationTests.java @@ -19,10 +19,10 @@ package org.springframework.boot.couchbase.autoconfigure.health; import com.couchbase.client.java.Cluster; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.couchbase.actuate.health.CouchbaseHealthIndicator; -import org.springframework.boot.couchbase.actuate.health.CouchbaseReactiveHealthIndicator; +import org.springframework.boot.couchbase.health.CouchbaseHealthIndicator; +import org.springframework.boot.couchbase.health.CouchbaseReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfigurationTests.java index 7115397480f..a6bb1bc0ebf 100644 --- a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/autoconfigure/health/CouchbaseReactiveHealthContributorAutoConfigurationTests.java @@ -19,10 +19,10 @@ package org.springframework.boot.couchbase.autoconfigure.health; import com.couchbase.client.java.Cluster; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.couchbase.actuate.health.CouchbaseHealthIndicator; -import org.springframework.boot.couchbase.actuate.health.CouchbaseReactiveHealthIndicator; +import org.springframework.boot.couchbase.health.CouchbaseHealthIndicator; +import org.springframework.boot.couchbase.health.CouchbaseReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealthIndicatorTests.java b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/health/CouchbaseHealthIndicatorTests.java similarity index 95% rename from spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealthIndicatorTests.java rename to spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/health/CouchbaseHealthIndicatorTests.java index 9f0191ed472..299a9f07c5c 100644 --- a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/actuate/health/CouchbaseHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/health/CouchbaseHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.couchbase.actuate.health; +package org.springframework.boot.couchbase.health; import java.util.Arrays; import java.util.Collections; @@ -30,8 +30,8 @@ import com.couchbase.client.core.service.ServiceType; import com.couchbase.client.java.Cluster; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; diff --git a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/actuate/health/CouchbaseReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/health/CouchbaseReactiveHealthIndicatorTests.java similarity index 96% rename from spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/actuate/health/CouchbaseReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/health/CouchbaseReactiveHealthIndicatorTests.java index 84d52244ad7..2e6732c14a8 100644 --- a/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/actuate/health/CouchbaseReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-couchbase/src/test/java/org/springframework/boot/couchbase/health/CouchbaseReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.couchbase.actuate.health; +package org.springframework.boot.couchbase.health; import java.time.Duration; import java.util.Arrays; @@ -33,8 +33,8 @@ import com.couchbase.client.java.ReactiveCluster; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; diff --git a/spring-boot-project/spring-boot-data-elasticsearch/build.gradle b/spring-boot-project/spring-boot-data-elasticsearch/build.gradle index db848b08c7b..2d662f9a236 100644 --- a/spring-boot-project/spring-boot-data-elasticsearch/build.gradle +++ b/spring-boot-project/spring-boot-data-elasticsearch/build.gradle @@ -31,8 +31,8 @@ dependencies { api(project(":spring-boot-project:spring-boot-elasticsearch")) api("org.springframework.data:spring-data-elasticsearch") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-reactor")) dockerTestImplementation(project(":spring-boot-project:spring-boot-test")) diff --git a/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfiguration.java index a1d473f59ef..f0fe02398f0 100644 --- a/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.data.elasticsearch.autoconfigure.health; import reactor.core.publisher.Flux; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.data.elasticsearch.actuate.health.ElasticsearchReactiveHealthIndicator; +import org.springframework.boot.data.elasticsearch.health.ElasticsearchReactiveHealthIndicator; import org.springframework.boot.elasticsearch.autoconfigure.ReactiveElasticsearchClientAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; import org.springframework.context.annotation.Bean; import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient; diff --git a/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/actuate/health/ElasticsearchReactiveHealthIndicator.java b/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/health/ElasticsearchReactiveHealthIndicator.java similarity index 90% rename from spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/actuate/health/ElasticsearchReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/health/ElasticsearchReactiveHealthIndicator.java index a12f770c94c..d5a2c41695e 100644 --- a/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/actuate/health/ElasticsearchReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/health/ElasticsearchReactiveHealthIndicator.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package org.springframework.boot.data.elasticsearch.actuate.health; +package org.springframework.boot.data.elasticsearch.health; import co.elastic.clients.elasticsearch._types.HealthStatus; import co.elastic.clients.elasticsearch.cluster.HealthResponse; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient; /** diff --git a/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/actuate/health/package-info.java b/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/actuate/health/package-info.java rename to spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/health/package-info.java index d71a3580ca9..baeb5f437b8 100644 --- a/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-data-elasticsearch/src/main/java/org/springframework/boot/data/elasticsearch/health/package-info.java @@ -17,4 +17,4 @@ /** * Elasticsearch health integration using Spring Data Elasticsearch. */ -package org.springframework.boot.data.elasticsearch.actuate.health; +package org.springframework.boot.data.elasticsearch.health; diff --git a/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfigurationTests.java index 77ddce2f82b..b6c27411705 100644 --- a/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/autoconfigure/health/ElasticsearchReactiveHealthContributorAutoConfigurationTests.java @@ -18,14 +18,14 @@ package org.springframework.boot.data.elasticsearch.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.data.elasticsearch.actuate.health.ElasticsearchReactiveHealthIndicator; import org.springframework.boot.data.elasticsearch.autoconfigure.ElasticsearchDataAutoConfiguration; -import org.springframework.boot.elasticsearch.actuate.health.ElasticsearchRestClientHealthIndicator; +import org.springframework.boot.data.elasticsearch.health.ElasticsearchReactiveHealthIndicator; import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration; import org.springframework.boot.elasticsearch.autoconfigure.ReactiveElasticsearchClientAutoConfiguration; import org.springframework.boot.elasticsearch.autoconfigure.health.ElasticsearchRestHealthContributorAutoConfiguration; +import org.springframework.boot.elasticsearch.health.ElasticsearchRestClientHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/actuate/health/ElasticsearchReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/health/ElasticsearchReactiveHealthIndicatorTests.java similarity index 96% rename from spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/actuate/health/ElasticsearchReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/health/ElasticsearchReactiveHealthIndicatorTests.java index 03283cda059..b284cb75f33 100644 --- a/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/actuate/health/ElasticsearchReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-data-elasticsearch/src/test/java/org/springframework/boot/data/elasticsearch/health/ElasticsearchReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.data.elasticsearch.actuate.health; +package org.springframework.boot.data.elasticsearch.health; import java.time.Duration; import java.util.Map; @@ -30,8 +30,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.testsupport.junit.EnabledOnLocale; import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient; import org.springframework.http.HttpHeaders; diff --git a/spring-boot-project/spring-boot-data-mongodb/build.gradle b/spring-boot-project/spring-boot-data-mongodb/build.gradle index b83a9e711f8..d9d94cdc10c 100644 --- a/spring-boot-project/spring-boot-data-mongodb/build.gradle +++ b/spring-boot-project/spring-boot-data-mongodb/build.gradle @@ -33,8 +33,8 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-reactor")) optional("org.mongodb:mongodb-driver-reactivestreams") optional("org.mongodb:mongodb-driver-sync") diff --git a/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicatorIntegrationTests.java b/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicatorIntegrationTests.java similarity index 91% rename from spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicatorIntegrationTests.java rename to spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicatorIntegrationTests.java index 77f154be63f..a016aa7a44c 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicatorIntegrationTests.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicatorIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; @@ -28,8 +28,8 @@ import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.testsupport.container.TestImage; import org.springframework.data.mongodb.core.MongoTemplate; @@ -71,7 +71,7 @@ class MongoHealthIndicatorIntegrationTests { MongoClientSettings settings = settingsBuilder.build(); MongoClient mongoClient = MongoClients.create(settings); MongoHealthIndicator healthIndicator = new MongoHealthIndicator(new MongoTemplate(mongoClient, "db")); - return healthIndicator.getHealth(true); + return healthIndicator.health(true); } } diff --git a/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicatorIntegrationTests.java b/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicatorIntegrationTests.java similarity index 91% rename from spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicatorIntegrationTests.java rename to spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicatorIntegrationTests.java index 078c209a496..71e89f0a5b5 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicatorIntegrationTests.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/dockerTest/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicatorIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; import java.time.Duration; @@ -30,8 +30,8 @@ import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.testsupport.container.TestImage; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; @@ -74,7 +74,7 @@ class MongoReactiveHealthIndicatorIntegrationTests { MongoClient mongoClient = MongoClients.create(settings); MongoReactiveHealthIndicator healthIndicator = new MongoReactiveHealthIndicator( new ReactiveMongoTemplate(mongoClient, "db")); - return healthIndicator.getHealth(true).block(Duration.ofSeconds(30)); + return healthIndicator.health(true).block(Duration.ofSeconds(30)); } } diff --git a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfiguration.java index 2614188b8e9..de4fb38408b 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfiguration.java @@ -17,16 +17,16 @@ package org.springframework.boot.data.mongodb.autoconfigure.health; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.data.mongodb.actuate.health.MongoHealthIndicator; import org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration; +import org.springframework.boot.data.mongodb.health.MongoHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.core.MongoTemplate; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfiguration.java index b3864a5de72..576caaa4fd0 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.data.mongodb.autoconfigure.health; import reactor.core.publisher.Flux; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.data.mongodb.actuate.health.MongoReactiveHealthIndicator; import org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveDataAutoConfiguration; +import org.springframework.boot.data.mongodb.health.MongoReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicator.java b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicator.java similarity index 85% rename from spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicator.java rename to spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicator.java index 2c1067a1bb8..1d8a0db3fda 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicator.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicator.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; import org.bson.Document; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.util.Assert; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicator.java b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicator.java similarity index 86% rename from spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicator.java index 90b6bb3317f..bdee9e13dd0 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicator.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; import org.bson.Document; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.util.Assert; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/package-info.java b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/package-info.java rename to spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/package-info.java index 28e37040aa9..b3404379a9d 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/main/java/org/springframework/boot/data/mongodb/health/package-info.java @@ -17,4 +17,4 @@ /** * MongoDB health integration using Spring Data MongoDB. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfigurationTests.java index 354b69f26f7..bdaa586ccc9 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoHealthContributorAutoConfigurationTests.java @@ -18,10 +18,10 @@ package org.springframework.boot.data.mongodb.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.data.mongodb.actuate.health.MongoHealthIndicator; import org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration; +import org.springframework.boot.data.mongodb.health.MongoHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfigurationTests.java index d3b2dc105a8..e5624565d85 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/autoconfigure/health/MongoReactiveHealthContributorAutoConfigurationTests.java @@ -18,12 +18,12 @@ package org.springframework.boot.data.mongodb.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.data.mongodb.actuate.health.MongoHealthIndicator; -import org.springframework.boot.data.mongodb.actuate.health.MongoReactiveHealthIndicator; import org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration; import org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveDataAutoConfiguration; +import org.springframework.boot.data.mongodb.health.MongoHealthIndicator; +import org.springframework.boot.data.mongodb.health.MongoReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration; import org.springframework.boot.mongodb.autoconfigure.MongoReactiveAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicatorTests.java b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicatorTests.java similarity index 92% rename from spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicatorTests.java rename to spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicatorTests.java index a08dc3f869a..45dd1be26a5 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/actuate/health/MongoHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/health/MongoHealthIndicatorTests.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; import com.mongodb.MongoException; import org.bson.Document; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.data.mongodb.core.MongoTemplate; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicatorTests.java similarity index 94% rename from spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicatorTests.java index 3c5c0f4fae9..5c956f6ff4e 100644 --- a/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/actuate/health/MongoReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-data-mongodb/src/test/java/org/springframework/boot/data/mongodb/health/MongoReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.data.mongodb.actuate.health; +package org.springframework.boot.data.mongodb.health; import java.time.Duration; @@ -24,8 +24,8 @@ import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-data-redis/build.gradle b/spring-boot-project/spring-boot-data-redis/build.gradle index 0fbc930ec28..500c7555399 100644 --- a/spring-boot-project/spring-boot-data-redis/build.gradle +++ b/spring-boot-project/spring-boot-data-redis/build.gradle @@ -36,9 +36,9 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-netty")) - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("com.redis:testcontainers-redis") diff --git a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfiguration.java index 64e08407376..49f986202ad 100644 --- a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfiguration.java @@ -17,17 +17,17 @@ package org.springframework.boot.data.redis.autoconfigure.health; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.data.redis.actuate.health.RedisHealthIndicator; import org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration; +import org.springframework.boot.data.redis.health.RedisHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.RedisConnectionFactory; diff --git a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfiguration.java index 2202ccd18eb..de29b2c1587 100644 --- a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfiguration.java @@ -19,17 +19,17 @@ package org.springframework.boot.data.redis.autoconfigure.health; import reactor.core.publisher.Flux; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.data.redis.actuate.health.RedisReactiveHealthIndicator; import org.springframework.boot.data.redis.autoconfigure.RedisReactiveAutoConfiguration; +import org.springframework.boot.data.redis.health.RedisReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; diff --git a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisHealth.java b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisHealth.java similarity index 80% rename from spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisHealth.java rename to spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisHealth.java index 1c9a2703c88..6cb22ce5bb8 100644 --- a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisHealth.java +++ b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisHealth.java @@ -14,12 +14,11 @@ * limitations under the License. */ -package org.springframework.boot.data.redis.actuate.health; +package org.springframework.boot.data.redis.health; import java.util.Properties; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Health.Builder; +import org.springframework.boot.health.contributor.Health; import org.springframework.data.redis.connection.ClusterInfo; /** @@ -33,12 +32,12 @@ final class RedisHealth { private RedisHealth() { } - static Builder up(Health.Builder builder, Properties info) { + static Health.Builder up(Health.Builder builder, Properties info) { builder.withDetail("version", info.getProperty("redis_version")); return builder.up(); } - static Builder fromClusterInfo(Health.Builder builder, ClusterInfo clusterInfo) { + static Health.Builder fromClusterInfo(Health.Builder builder, ClusterInfo clusterInfo) { builder.withDetail("cluster_size", clusterInfo.getClusterSize()); builder.withDetail("slots_up", clusterInfo.getSlotsOk()); builder.withDetail("slots_fail", clusterInfo.getSlotsFail()); diff --git a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisHealthIndicator.java b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisHealthIndicator.java similarity index 89% rename from spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisHealthIndicator.java rename to spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisHealthIndicator.java index b6d883b0bb6..a218a8607ba 100644 --- a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisHealthIndicator.java +++ b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisHealthIndicator.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.springframework.boot.data.redis.actuate.health; +package org.springframework.boot.data.redis.health; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.data.redis.connection.RedisClusterConnection; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; diff --git a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisReactiveHealthIndicator.java b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisReactiveHealthIndicator.java similarity index 91% rename from spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisReactiveHealthIndicator.java index 4f5ce945688..900c2d29965 100644 --- a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/RedisReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/RedisReactiveHealthIndicator.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package org.springframework.boot.data.redis.actuate.health; +package org.springframework.boot.data.redis.health; import java.util.Properties; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; import org.springframework.data.redis.connection.ClusterInfo; import org.springframework.data.redis.connection.ReactiveRedisClusterConnection; import org.springframework.data.redis.connection.ReactiveRedisConnection; diff --git a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/package-info.java b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/package-info.java rename to spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/package-info.java index 2b758724e26..52c54ba4b9b 100644 --- a/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/health/package-info.java @@ -17,4 +17,4 @@ /** * Redis health integration using Spring Data Redis. */ -package org.springframework.boot.data.redis.actuate.health; +package org.springframework.boot.data.redis.health; diff --git a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfigurationTests.java index 1a24b4fd6ea..561cb395002 100644 --- a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisHealthContributorAutoConfigurationTests.java @@ -18,11 +18,11 @@ package org.springframework.boot.data.redis.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.data.redis.actuate.health.RedisHealthIndicator; -import org.springframework.boot.data.redis.actuate.health.RedisReactiveHealthIndicator; import org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration; +import org.springframework.boot.data.redis.health.RedisHealthIndicator; +import org.springframework.boot.data.redis.health.RedisReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.testsupport.classpath.ClassPathExclusions; diff --git a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfigurationTests.java index 7afb894f54d..879fddc92c5 100644 --- a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/health/RedisReactiveHealthContributorAutoConfigurationTests.java @@ -18,11 +18,11 @@ package org.springframework.boot.data.redis.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.data.redis.actuate.health.RedisHealthIndicator; -import org.springframework.boot.data.redis.actuate.health.RedisReactiveHealthIndicator; import org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration; +import org.springframework.boot.data.redis.health.RedisHealthIndicator; +import org.springframework.boot.data.redis.health.RedisReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/actuate/health/RedisHealthIndicatorTests.java b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/health/RedisHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/actuate/health/RedisHealthIndicatorTests.java rename to spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/health/RedisHealthIndicatorTests.java index 8323b6d0e94..6c6ccc98527 100644 --- a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/actuate/health/RedisHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/health/RedisHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.data.redis.actuate.health; +package org.springframework.boot.data.redis.health; import java.util.Arrays; import java.util.List; @@ -22,8 +22,8 @@ import java.util.Properties; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.data.redis.RedisConnectionFailureException; import org.springframework.data.redis.connection.ClusterInfo; import org.springframework.data.redis.connection.RedisClusterConnection; diff --git a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/actuate/health/RedisReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/health/RedisReactiveHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/actuate/health/RedisReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/health/RedisReactiveHealthIndicatorTests.java index 8b0dd64c57d..7f0a3112907 100644 --- a/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/actuate/health/RedisReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/health/RedisReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.data.redis.actuate.health; +package org.springframework.boot.data.redis.health; import java.time.Duration; import java.util.Properties; @@ -24,8 +24,8 @@ import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.data.redis.RedisConnectionFailureException; import org.springframework.data.redis.connection.ClusterInfo; import org.springframework.data.redis.connection.ReactiveRedisClusterConnection; diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 9f74905334a..a06986a1125 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2022,6 +2022,7 @@ bom { "spring-boot-h2console", "spring-boot-hateoas", "spring-boot-hazelcast", + "spring-boot-health", "spring-boot-hibernate", "spring-boot-http-client", "spring-boot-http-codec", diff --git a/spring-boot-project/spring-boot-docs/build.gradle b/spring-boot-project/spring-boot-docs/build.gradle index 35690aaa12a..1ff7165908a 100644 --- a/spring-boot-project/spring-boot-docs/build.gradle +++ b/spring-boot-project/spring-boot-docs/build.gradle @@ -255,6 +255,7 @@ dependencies { implementation(project(path: ":spring-boot-project:spring-boot-data-neo4j")) implementation(project(path: ":spring-boot-project:spring-boot-devtools")) implementation(project(path: ":spring-boot-project:spring-boot-docker-compose")) + implementation(project(path: ":spring-boot-project:spring-boot-health")) implementation(project(path: ":spring-boot-project:spring-boot-hibernate")) implementation(project(path: ":spring-boot-project:spring-boot-http-converter")) implementation(project(path: ":spring-boot-project:spring-boot-http-codec")) diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc index ee76e5df1d6..d9fd2e0cb22 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc @@ -581,7 +581,7 @@ You can configure the roles by using the configprop:management.endpoint.health.r NOTE: If you have secured your application and wish to use `always`, your security configuration must permit access to the health endpoint for both authenticated and unauthenticated users. -Health information is collected from the content of a javadoc:org.springframework.boot.actuate.health.HealthContributorRegistry[] (by default, all javadoc:org.springframework.boot.actuate.health.HealthContributor[] instances defined in your javadoc:org.springframework.context.ApplicationContext[]). +Health information is collected from the content of a javadoc:org.springframework.boot.health.registry.HealthContributorRegistry[] (by default, all javadoc:org.springframework.boot.actuate.health.HealthContributor[] instances defined in your javadoc:org.springframework.context.ApplicationContext[]). Spring Boot includes a number of auto-configured javadoc:org.springframework.boot.actuate.health.HealthContributor[] beans, and you can also write your own. A javadoc:org.springframework.boot.actuate.health.HealthContributor[] can be either a javadoc:org.springframework.boot.actuate.health.HealthIndicator[] or a javadoc:org.springframework.boot.actuate.health.CompositeHealthContributor[]. @@ -593,7 +593,7 @@ By default, the final system health is derived by a javadoc:org.springframework. The first status in the sorted list is used as the overall health status. If no javadoc:org.springframework.boot.actuate.health.HealthIndicator[] returns a status that is known to the javadoc:org.springframework.boot.actuate.health.StatusAggregator[], an `UNKNOWN` status is used. -TIP: You can use the javadoc:org.springframework.boot.actuate.health.HealthContributorRegistry[] to register and unregister health indicators at runtime. +TIP: You can use the javadoc:org.springframework.boot.health.registry.HealthContributorRegistry[] to register and unregister health indicators at runtime. @@ -653,7 +653,7 @@ with the `key` listed in the following table: | Checks that a Neo4j database is up. | `ping` -| javadoc:org.springframework.boot.actuate.health.PingHealthIndicator[] +| javadoc:org.springframework.boot.health.contributor.PingHealthIndicator[] | Always responds with `UP`. | `rabbit` @@ -771,10 +771,10 @@ The following table shows the default status mappings for the built-in statuses: === Reactive Health Indicators For reactive applications, such as those that use Spring WebFlux, javadoc:org.springframework.boot.actuate.health.ReactiveHealthContributor[] provides a non-blocking contract for getting application health. -Similar to a traditional javadoc:org.springframework.boot.actuate.health.HealthContributor[], health information is collected from the content of a javadoc:org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry[] (by default, all javadoc:org.springframework.boot.actuate.health.HealthContributor[] and javadoc:org.springframework.boot.actuate.health.ReactiveHealthContributor[] instances defined in your javadoc:org.springframework.context.ApplicationContext[]). +Similar to a traditional javadoc:org.springframework.boot.actuate.health.HealthContributor[], health information is collected from the content of a javadoc:org.springframework.boot.health.registry.ReactiveHealthContributorRegistry[] (by default, all javadoc:org.springframework.boot.actuate.health.HealthContributor[] and javadoc:org.springframework.boot.actuate.health.ReactiveHealthContributor[] instances defined in your javadoc:org.springframework.context.ApplicationContext[]). Regular javadoc:org.springframework.boot.actuate.health.HealthContributor[] instances that do not check against a reactive API are executed on the elastic scheduler. -TIP: In a reactive application, you should use the javadoc:org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry[] to register and unregister health indicators at runtime. +TIP: In a reactive application, you should use the javadoc:org.springframework.boot.health.registry.ReactiveHealthContributorRegistry[] to register and unregister health indicators at runtime. If you need to register a regular javadoc:org.springframework.boot.actuate.health.HealthContributor[], you should wrap it with `ReactiveHealthContributor#adapt`. To provide custom health information from a reactive API, you can register Spring beans that implement the javadoc:org.springframework.boot.actuate.health.ReactiveHealthIndicator[] interface. diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.java index e464cddc41a..40673f4257c 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.java @@ -18,8 +18,8 @@ package org.springframework.boot.docs.actuator.endpoints.health.reactivehealthin import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.java index 0e275f73c81..f2d6d35dfcc 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.java @@ -16,8 +16,8 @@ package org.springframework.boot.docs.actuator.endpoints.health.writingcustomhealthindicators; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.java index 19af53f53e4..57cc3e2f3c0 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.java @@ -20,7 +20,7 @@ import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.boot.actuate.health.HealthEndpoint; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Status; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.kt index fb7c9a07eef..b9c18e2b980 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/reactivehealthindicators/MyReactiveHealthIndicator.kt @@ -16,8 +16,8 @@ package org.springframework.boot.docs.actuator.endpoints.health.reactivehealthindicators -import org.springframework.boot.actuate.health.Health -import org.springframework.boot.actuate.health.ReactiveHealthIndicator +import org.springframework.boot.health.contributor.Health +import org.springframework.boot.health.contributor.ReactiveHealthIndicator import org.springframework.stereotype.Component import reactor.core.publisher.Mono diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.kt index d9453f00b91..39287249804 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/endpoints/health/writingcustomhealthindicators/MyHealthIndicator.kt @@ -16,8 +16,8 @@ package org.springframework.boot.docs.actuator.endpoints.health.writingcustomhealthindicators -import org.springframework.boot.actuate.health.Health -import org.springframework.boot.actuate.health.HealthIndicator +import org.springframework.boot.health.contributor.Health +import org.springframework.boot.health.contributor.HealthIndicator import org.springframework.stereotype.Component @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.kt index b24eb17d02f..3c79f539459 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MyHealthMetricsExportConfiguration.kt @@ -19,7 +19,7 @@ package org.springframework.boot.docs.howto.actuator.maphealthindicatorstometric import io.micrometer.core.instrument.Gauge import io.micrometer.core.instrument.MeterRegistry import org.springframework.boot.actuate.health.HealthEndpoint -import org.springframework.boot.actuate.health.Status +import org.springframework.boot.health.contributor.Status import org.springframework.context.annotation.Configuration @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MetricsHealthMicrometerExportTests.java b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MetricsHealthMicrometerExportTests.java index e659c6fd4fa..2566c5dc5a8 100644 --- a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MetricsHealthMicrometerExportTests.java +++ b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/actuator/maphealthindicatorstometrics/MetricsHealthMicrometerExportTests.java @@ -22,11 +22,12 @@ import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.boot.metrics.autoconfigure.MetricsAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; @@ -54,7 +55,8 @@ class MetricsHealthMicrometerExportTests { @Configuration(proxyBeanMethods = false) @Import(MyHealthMetricsExportConfiguration.class) - @ImportAutoConfiguration(classes = { HealthContributorAutoConfiguration.class, MetricsAutoConfiguration.class, + @ImportAutoConfiguration({ HealthContributorAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, MetricsAutoConfiguration.class, HealthEndpointAutoConfiguration.class }) static class Config { @@ -70,7 +72,7 @@ class MetricsHealthMicrometerExportTests { @Bean HealthIndicator outOfService() { - return () -> new Health.Builder().outOfService().build(); + return () -> Health.outOfService().build(); } } diff --git a/spring-boot-project/spring-boot-elasticsearch/build.gradle b/spring-boot-project/spring-boot-elasticsearch/build.gradle index 12cbe156e34..e1b93fd56ca 100644 --- a/spring-boot-project/spring-boot-elasticsearch/build.gradle +++ b/spring-boot-project/spring-boot-elasticsearch/build.gradle @@ -30,7 +30,7 @@ dependencies { api(project(":spring-boot-project:spring-boot")) api("org.elasticsearch.client:elasticsearch-rest-client") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) optional(project(":spring-boot-project:spring-boot-jsonb")) diff --git a/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfiguration.java index f3d2327277d..ec8483bbf65 100644 --- a/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.elasticsearch.autoconfigure.health; import org.elasticsearch.client.RestClient; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.elasticsearch.actuate.health.ElasticsearchRestClientHealthIndicator; import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration; +import org.springframework.boot.elasticsearch.health.ElasticsearchRestClientHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/actuate/health/ElasticsearchRestClientHealthIndicator.java b/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/health/ElasticsearchRestClientHealthIndicator.java similarity index 86% rename from spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/actuate/health/ElasticsearchRestClientHealthIndicator.java rename to spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/health/ElasticsearchRestClientHealthIndicator.java index 226e050ac15..534eb58bcd2 100644 --- a/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/actuate/health/ElasticsearchRestClientHealthIndicator.java +++ b/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/health/ElasticsearchRestClientHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.elasticsearch.actuate.health; +package org.springframework.boot.elasticsearch.health; import java.io.InputStream; import java.nio.charset.StandardCharsets; @@ -26,9 +26,10 @@ import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.json.JsonParser; import org.springframework.boot.json.JsonParserFactory; import org.springframework.util.StreamUtils; @@ -73,12 +74,7 @@ public class ElasticsearchRestClientHealthIndicator extends AbstractHealthIndica private void doHealthCheck(Health.Builder builder, String json) { Map response = this.jsonParser.parseMap(json); String status = (String) response.get("status"); - if (RED_STATUS.equals(status)) { - builder.outOfService(); - } - else { - builder.up(); - } + builder.status((RED_STATUS.equals(status)) ? Status.OUT_OF_SERVICE : Status.UP); builder.withDetails(response); } diff --git a/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/actuate/health/package-info.java b/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/actuate/health/package-info.java rename to spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/health/package-info.java index 0d86658d1bd..0f8ff9cda37 100644 --- a/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-elasticsearch/src/main/java/org/springframework/boot/elasticsearch/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for Elasticsearch. */ -package org.springframework.boot.elasticsearch.actuate.health; +package org.springframework.boot.elasticsearch.health; diff --git a/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfigurationTests.java index 9c27e94683c..97439220d50 100644 --- a/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/autoconfigure/health/ElasticsearchRestHealthContributorAutoConfigurationTests.java @@ -20,10 +20,10 @@ import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.elasticsearch.actuate.health.ElasticsearchRestClientHealthIndicator; import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration; +import org.springframework.boot.elasticsearch.health.ElasticsearchRestClientHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/actuate/health/ElasticsearchRestClientHealthIndicatorTests.java b/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/health/ElasticsearchRestClientHealthIndicatorTests.java similarity index 95% rename from spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/actuate/health/ElasticsearchRestClientHealthIndicatorTests.java rename to spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/health/ElasticsearchRestClientHealthIndicatorTests.java index 5adc0fdad01..58df73ffbbe 100644 --- a/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/actuate/health/ElasticsearchRestClientHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-elasticsearch/src/test/java/org/springframework/boot/elasticsearch/health/ElasticsearchRestClientHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.elasticsearch.actuate.health; +package org.springframework.boot.elasticsearch.health; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -27,8 +27,8 @@ import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -59,7 +59,8 @@ class ElasticsearchRestClientHealthIndicatorTests { given(response.getStatusLine()).willReturn(statusLine); given(response.getEntity()).willReturn(httpEntity); given(this.restClient.performRequest(any(Request.class))).willReturn(response); - Health health = this.elasticsearchRestClientHealthIndicator.health(); + org.springframework.boot.health.contributor.Health health = this.elasticsearchRestClientHealthIndicator + .health(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertHealthDetailsWithStatus(health.getDetails(), "green"); } diff --git a/spring-boot-project/spring-boot-hazelcast/build.gradle b/spring-boot-project/spring-boot-hazelcast/build.gradle index a7d5136bf5d..1253e79c43f 100644 --- a/spring-boot-project/spring-boot-hazelcast/build.gradle +++ b/spring-boot-project/spring-boot-hazelcast/build.gradle @@ -32,9 +32,9 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-hibernate")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("com.hazelcast:hazelcast-spring") diff --git a/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfiguration.java index 546433d381a..705a51706da 100644 --- a/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.hazelcast.autoconfigure.health; import com.hazelcast.core.HazelcastInstance; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.hazelcast.actuate.health.HazelcastHealthIndicator; import org.springframework.boot.hazelcast.autoconfigure.HazelcastAutoConfiguration; +import org.springframework.boot.hazelcast.health.HazelcastHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/actuate/health/HazelcastHealthIndicator.java b/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/health/HazelcastHealthIndicator.java similarity index 85% rename from spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/actuate/health/HazelcastHealthIndicator.java rename to spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/health/HazelcastHealthIndicator.java index c75242a258a..a415259cafa 100644 --- a/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/actuate/health/HazelcastHealthIndicator.java +++ b/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/health/HazelcastHealthIndicator.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.hazelcast.actuate.health; +package org.springframework.boot.hazelcast.health; import com.hazelcast.core.HazelcastInstance; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/actuate/health/package-info.java b/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/health/package-info.java similarity index 91% rename from spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/actuate/health/package-info.java rename to spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/health/package-info.java index f95df17fddb..c53637913d9 100644 --- a/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-hazelcast/src/main/java/org/springframework/boot/hazelcast/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for Hazelcast. */ -package org.springframework.boot.hazelcast.actuate.health; +package org.springframework.boot.hazelcast.health; diff --git a/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationIntegrationTests.java index 32cde39aee2..46eb627d99e 100644 --- a/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationIntegrationTests.java @@ -19,12 +19,12 @@ package org.springframework.boot.hazelcast.autoconfigure.health; import com.hazelcast.core.HazelcastInstance; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.hazelcast.actuate.health.HazelcastHealthIndicator; import org.springframework.boot.hazelcast.autoconfigure.HazelcastAutoConfiguration; +import org.springframework.boot.hazelcast.health.HazelcastHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.testsupport.classpath.resources.WithResource; diff --git a/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationTests.java index 1ea13b38de6..2cc1ffd4bea 100644 --- a/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/autoconfigure/health/HazelcastHealthContributorAutoConfigurationTests.java @@ -18,10 +18,10 @@ package org.springframework.boot.hazelcast.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.hazelcast.actuate.health.HazelcastHealthIndicator; import org.springframework.boot.hazelcast.autoconfigure.HazelcastAutoConfiguration; +import org.springframework.boot.hazelcast.health.HazelcastHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.testsupport.classpath.resources.WithResource; diff --git a/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/actuate/health/HazelcastHealthIndicatorTests.java b/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/health/HazelcastHealthIndicatorTests.java similarity index 94% rename from spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/actuate/health/HazelcastHealthIndicatorTests.java rename to spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/health/HazelcastHealthIndicatorTests.java index f7070ba948f..5e370f0c1f0 100644 --- a/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/actuate/health/HazelcastHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-hazelcast/src/test/java/org/springframework/boot/hazelcast/health/HazelcastHealthIndicatorTests.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package org.springframework.boot.hazelcast.actuate.health; +package org.springframework.boot.hazelcast.health; import com.hazelcast.core.HazelcastException; import com.hazelcast.core.HazelcastInstance; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.hazelcast.autoconfigure.HazelcastAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.testsupport.classpath.resources.WithResource; diff --git a/spring-boot-project/spring-boot-health/build.gradle b/spring-boot-project/spring-boot-health/build.gradle new file mode 100644 index 00000000000..5cb612f2716 --- /dev/null +++ b/spring-boot-project/spring-boot-health/build.gradle @@ -0,0 +1,39 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +plugins { + id "java-library" + id "org.springframework.boot.deployed" + id "org.springframework.boot.optional-dependencies" +} + +description = "Spring Boot Health" + +dependencies { + api(project(":spring-boot-project:spring-boot")) + + optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional("io.projectreactor:reactor-core") + optional("com.fasterxml.jackson.core:jackson-annotations") + + testImplementation(project(":spring-boot-project:spring-boot-test")) + testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + testImplementation("com.fasterxml.jackson.core:jackson-databind") + testImplementation("io.projectreactor:reactor-test") + + testRuntimeOnly("ch.qos.logback:logback-classic") +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/AbstractCompositeHealthContributorConfiguration.java similarity index 93% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/AbstractCompositeHealthContributorConfiguration.java index a8601b5136a..a4d15f2186d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/AbstractCompositeHealthContributorConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; import java.util.Map; import java.util.function.Function; @@ -32,9 +32,8 @@ import org.springframework.util.Assert; * @param the bean type * @author Stephane Nicoll * @author Phillip Webb - * @since 2.2.0 */ -public abstract class AbstractCompositeHealthContributorConfiguration { +abstract class AbstractCompositeHealthContributorConfiguration { private final Function indicatorFactory; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfiguration.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/CompositeHealthContributorConfiguration.java similarity index 84% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfiguration.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/CompositeHealthContributorConfiguration.java index c882062a132..507e8a96a68 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfiguration.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/CompositeHealthContributorConfiguration.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; import java.util.Map; import java.util.function.Function; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; /** * Base class for health contributor configurations that can combine source beans into a @@ -31,7 +31,7 @@ import org.springframework.boot.actuate.health.HealthIndicator; * @param the bean type * @author Stephane Nicoll * @author Phillip Webb - * @since 2.2.0 + * @since 4.0.0 */ public abstract class CompositeHealthContributorConfiguration extends AbstractCompositeHealthContributorConfiguration { @@ -40,7 +40,6 @@ public abstract class CompositeHealthContributorConfiguration indicatorFactory) { super(indicatorFactory); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/CompositeReactiveHealthContributorConfiguration.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/CompositeReactiveHealthContributorConfiguration.java similarity index 83% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/CompositeReactiveHealthContributorConfiguration.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/CompositeReactiveHealthContributorConfiguration.java index 8fe8c025bdf..3271137137f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/CompositeReactiveHealthContributorConfiguration.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/CompositeReactiveHealthContributorConfiguration.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; import java.util.Map; import java.util.function.Function; -import org.springframework.boot.actuate.health.CompositeReactiveHealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.CompositeReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; /** * Base class for health contributor configurations that can combine source beans into a @@ -31,7 +31,7 @@ import org.springframework.boot.actuate.health.ReactiveHealthIndicator; * @param the bean type * @author Stephane Nicoll * @author Phillip Webb - * @since 2.2.0 + * @since 4.0.0 */ public abstract class CompositeReactiveHealthContributorConfiguration extends AbstractCompositeHealthContributorConfiguration { @@ -40,7 +40,6 @@ public abstract class CompositeReactiveHealthContributorConfiguration indicatorFactory) { super(indicatorFactory); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ConditionalOnEnabledHealthIndicator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicator.java similarity index 95% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ConditionalOnEnabledHealthIndicator.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicator.java index 815093c7f6f..84d35dd4dd9 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/ConditionalOnEnabledHealthIndicator.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -32,7 +32,7 @@ import org.springframework.context.annotation.Conditional; * configured. * * @author Stephane Nicoll - * @since 2.0.0 + * @since 4.0.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/HealthContributorAutoConfiguration.java similarity index 75% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfiguration.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/HealthContributorAutoConfiguration.java index 4531d0efbd0..a86e406c0d2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/HealthContributorAutoConfiguration.java @@ -14,20 +14,20 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.PingHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.PingHealthIndicator; import org.springframework.context.annotation.Bean; /** - * {@link EnableAutoConfiguration Auto-configuration} for {@link HealthContributor health - * contributors}. + * {@link EnableAutoConfiguration Auto-configuration} for default {@link HealthContributor + * health contributors}. * * @author Phillip Webb - * @since 2.2.0 + * @since 4.0.0 */ @AutoConfiguration public class HealthContributorAutoConfiguration { diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/OnEnabledHealthIndicatorCondition.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/OnEnabledHealthIndicatorCondition.java new file mode 100644 index 00000000000..561e7062da5 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/OnEnabledHealthIndicatorCondition.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.autoconfigure.contributor; + +import org.springframework.boot.autoconfigure.condition.ConditionMessage; +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.env.Environment; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * {@link Condition} that checks if a health indicator is enabled. + * + * @author Stephane Nicoll + * @author Madhura Bhave + * @author Phillip Webb + */ +class OnEnabledHealthIndicatorCondition extends SpringBootCondition { + + private static final String DEFAULTS_PROPERTY_NAME = "management.health.defaults.enabled"; + + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + MergedAnnotation annotation = metadata.getAnnotations().get(ConditionalOnEnabledHealthIndicator.class); + String name = annotation.getString(MergedAnnotation.VALUE); + Environment environment = context.getEnvironment(); + ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnEnabledHealthIndicator.class); + String propertyName = "management.health." + name + ".enabled"; + if (environment.containsProperty(propertyName)) { + boolean match = environment.getProperty(propertyName, Boolean.class, true); + return new ConditionOutcome(match, message.because(propertyName + " is " + match)); + } + boolean match = Boolean.parseBoolean(context.getEnvironment().getProperty(DEFAULTS_PROPERTY_NAME, "true")); + return new ConditionOutcome(match, message.because(DEFAULTS_PROPERTY_NAME + " is considered " + match)); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/package-info.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/package-info.java new file mode 100644 index 00000000000..8c27a5d2201 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/contributor/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Auto-configuration for health contributors. + */ +package org.springframework.boot.health.autoconfigure.contributor; diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGenerator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGenerator.java new file mode 100644 index 00000000000..2422eab826c --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGenerator.java @@ -0,0 +1,97 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.autoconfigure.registry; + +import java.util.Locale; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * Strategy used to create health contributor names from bean names. + * + * @author Phillip Webb + * @since 4.0.0 + */ +@FunctionalInterface +public interface HealthContributorNameGenerator { + + /** + * Generate the health contributor name for the given bean name. + * @param beanName the bean name + * @return the health contributor name + */ + String generateContributorName(String beanName); + + /** + * Return a registrar that can be used to register the given contributor beans with a + * generated name. + * @param the contributor type + * @param contributorBeans the contributor beans + * @return a registrar + */ + default Consumer> registrar(Map contributorBeans) { + return (initialRegistrations) -> { + contributorBeans.forEach((beanName, contributorBean) -> { + String contributorName = generateContributorName(beanName); + try { + initialRegistrations.accept(contributorName, contributorBean); + } + catch (RuntimeException ex) { + throw new IllegalStateException( + "Unable to register contributor named '%s' of type %s from bean '%s': %s" + .formatted(contributorName, contributorBean.getClass(), beanName, ex.getMessage()), + ex); + } + }); + }; + } + + /** + * Return a {@link HealthContributorNameGenerator} that uses the unchanged bean name + * as the health contributor name. + * @return a new {@link HealthContributorNameGenerator} instance + */ + static HealthContributorNameGenerator unchanged() { + return (beanName) -> beanName; + } + + /** + * Return a {@link HealthContributorNameGenerator} that removes standard suffixes. + * @return a new {@link HealthContributorNameGenerator} instance + */ + static HealthContributorNameGenerator withoutStandardSuffixes() { + return withoutSuffixes("healthindicator", "healthcontributor"); + } + + /** + * Return a {@link HealthContributorNameGenerator} that removes the given suffixes. + * @param suffixes the suffixes to remove (not case sensitive) + * @return a new {@link HealthContributorNameGenerator} instance + */ + static HealthContributorNameGenerator withoutSuffixes(String... suffixes) { + return (beanName) -> { + for (String suffix : suffixes) { + if (beanName != null && beanName.toLowerCase(Locale.ENGLISH).endsWith(suffix)) { + return beanName.substring(0, beanName.length() - suffix.length()); + } + } + return beanName; + }; + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfiguration.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfiguration.java new file mode 100644 index 00000000000..43f3949c299 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfiguration.java @@ -0,0 +1,78 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.autoconfigure.registry; + +import java.util.List; +import java.util.Map; + +import reactor.core.publisher.Flux; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.DefaultReactiveHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorNameValidator; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; +import org.springframework.context.annotation.Bean; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for + * {@link HealthContributorRegistry} and {@link ReactiveHealthContributorRegistry}. + * + * @author Phillip Webb + * @since 4.0.0 + */ +@AutoConfiguration +public class HealthContributorRegistryAutoConfiguration { + + HealthContributorRegistryAutoConfiguration() { + } + + @Bean + @ConditionalOnMissingBean(HealthContributorRegistry.class) + DefaultHealthContributorRegistry healthContributorRegistry(Map contributorBeans, + ObjectProvider nameGeneratorProvider, + List nameValidators) { + HealthContributorNameGenerator nameGenerator = nameGeneratorProvider + .getIfAvailable(HealthContributorNameGenerator::withoutStandardSuffixes); + return new DefaultHealthContributorRegistry(nameValidators, nameGenerator.registrar(contributorBeans)); + } + + @ConditionalOnClass(Flux.class) + static class ReactiveHealthContributorRegistryConfiguration { + + @Bean + @ConditionalOnMissingBean(ReactiveHealthContributorRegistry.class) + DefaultReactiveHealthContributorRegistry reactiveHealthContributorRegistry( + Map contributorBeans, + ObjectProvider nameGeneratorProvider, + List nameValidators) { + HealthContributorNameGenerator nameGenerator = nameGeneratorProvider + .getIfAvailable(HealthContributorNameGenerator::withoutStandardSuffixes); + return new DefaultReactiveHealthContributorRegistry(nameValidators, + nameGenerator.registrar(contributorBeans)); + } + + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/package-info.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/package-info.java new file mode 100644 index 00000000000..f554b019261 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/autoconfigure/registry/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Auto-configuration for health registries. + */ +package org.springframework.boot.health.autoconfigure.registry; diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/AbstractHealthIndicator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/AbstractHealthIndicator.java similarity index 89% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/AbstractHealthIndicator.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/AbstractHealthIndicator.java index cbc032e5e2a..b2fb7e203c4 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/AbstractHealthIndicator.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/AbstractHealthIndicator.java @@ -14,14 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.function.Function; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.actuate.health.Health.Builder; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -30,11 +29,11 @@ import org.springframework.util.StringUtils; * {@link Health} instance and error handling. *

* This implementation is only suitable if an {@link Exception} raised from - * {@link #doHealthCheck(org.springframework.boot.actuate.health.Health.Builder)} should - * create a {@link Status#DOWN} health status. + * {@link #doHealthCheck(Health.Builder)} should create a {@link Status#DOWN} health + * status. * * @author Christian Dupuis - * @since 1.1.0 + * @since 4.0.0 */ public abstract class AbstractHealthIndicator implements HealthIndicator { @@ -58,7 +57,6 @@ public abstract class AbstractHealthIndicator implements HealthIndicator { * Create a new {@link AbstractHealthIndicator} instance with a specific message to * log when the health check fails. * @param healthCheckFailedMessage the message to log on health check failure - * @since 2.0.0 */ protected AbstractHealthIndicator(String healthCheckFailedMessage) { this.healthCheckFailedMessage = (ex) -> healthCheckFailedMessage; @@ -68,7 +66,6 @@ public abstract class AbstractHealthIndicator implements HealthIndicator { * Create a new {@link AbstractHealthIndicator} instance with a specific message to * log when the health check fails. * @param healthCheckFailedMessage the message to log on health check failure - * @since 2.0.0 */ protected AbstractHealthIndicator(Function healthCheckFailedMessage) { Assert.notNull(healthCheckFailedMessage, "'healthCheckFailedMessage' must not be null"); @@ -97,7 +94,7 @@ public abstract class AbstractHealthIndicator implements HealthIndicator { /** * Actual health check logic. - * @param builder the {@link Builder} to report health status and details + * @param builder the {@link Health.Builder} to report health status and details * @throws Exception any {@link Exception} that should create a {@link Status#DOWN} * system status. */ diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/AbstractReactiveHealthIndicator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/AbstractReactiveHealthIndicator.java similarity index 97% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/AbstractReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/AbstractReactiveHealthIndicator.java index a2dca84f503..0a81355f47a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/AbstractReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/AbstractReactiveHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.function.Function; @@ -32,7 +32,7 @@ import org.springframework.util.StringUtils; * @author Stephane Nicoll * @author Nikolay Rybak * @author Moritz Halbritter - * @since 2.0.0 + * @since 4.0.0 */ public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthIndicator { @@ -67,7 +67,6 @@ public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthI * Create a new {@link AbstractReactiveHealthIndicator} instance with a specific * message to log when the health check fails. * @param healthCheckFailedMessage the message to log on health check failure - * @since 2.1.7 */ protected AbstractReactiveHealthIndicator(Function healthCheckFailedMessage) { Assert.notNull(healthCheckFailedMessage, "'healthCheckFailedMessage' must not be null"); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributor.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributor.java similarity index 85% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributor.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributor.java index 414a97ca41c..71367224cf9 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributor.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Map; import java.util.function.Function; @@ -24,11 +24,11 @@ import java.util.function.Function; * instances. * * @author Phillip Webb - * @since 2.2.0 - * @see CompositeHealth + * @author Guirong Hu + * @since 4.0.0 * @see CompositeReactiveHealthContributor */ -public interface CompositeHealthContributor extends HealthContributor, NamedContributors { +public non-sealed interface CompositeHealthContributor extends HealthContributor, HealthContributors { /** * Factory method that will create a {@link CompositeHealthContributor} from the @@ -50,7 +50,7 @@ public interface CompositeHealthContributor extends HealthContributor, NamedCont */ static CompositeHealthContributor fromMap(Map map, Function valueAdapter) { - return new CompositeHealthContributorMapAdapter<>(map, valueAdapter); + return new MapCompositeHealthContributor<>(map, valueAdapter); } } diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapter.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapter.java new file mode 100644 index 00000000000..7483abe51ca --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapter.java @@ -0,0 +1,33 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +/** + * Adapts a {@link CompositeHealthContributor} to a + * {@link CompositeReactiveHealthContributor}. + * + * @author Phillip Webb + * @see ReactiveHealthContributor#adapt(HealthContributor) + */ +class CompositeHealthContributorAdapter extends HealthContributorsAdapter + implements CompositeReactiveHealthContributor { + + CompositeHealthContributorAdapter(HealthContributors delegate) { + super(delegate); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributors.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributors.java new file mode 100644 index 00000000000..ca6863e8b9c --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeHealthContributors.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + +/** + * {@link HealthContributors} composed of other {@link HealthContributors}. + * + * @author Phillip Webb + * @see HealthContributors#of(HealthContributors...) + */ +class CompositeHealthContributors implements HealthContributors { + + private final List contributors; + + CompositeHealthContributors(HealthContributors... contributors) { + this.contributors = List.of(contributors); + } + + @Override + public HealthContributor getContributor(String name) { + return this.contributors.stream() + .map((contributors) -> contributors.getContributor(name)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + @Override + public Stream stream() { + Set seen = new HashSet<>(); + return this.contributors.stream() + .flatMap(HealthContributors::stream) + .filter((element) -> seen.add(element.name())); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributor.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributor.java similarity index 80% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributor.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributor.java index d79b74af7be..3fcda372b8c 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributor.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Map; import java.util.function.Function; @@ -24,12 +24,16 @@ import java.util.function.Function; * {@link ReactiveHealthContributor} instances. * * @author Phillip Webb - * @since 2.2.0 - * @see CompositeHealth + * @since 4.0.0 * @see CompositeHealthContributor */ -public interface CompositeReactiveHealthContributor - extends ReactiveHealthContributor, NamedContributors { +public non-sealed interface CompositeReactiveHealthContributor + extends ReactiveHealthContributor, ReactiveHealthContributors { + + @Override + default CompositeHealthContributor asHealthContributor() { + return new CompositeReactiveHealthContributorAdapter(this); + } /** * Factory method that will create a {@link CompositeReactiveHealthContributor} from @@ -51,7 +55,7 @@ public interface CompositeReactiveHealthContributor */ static CompositeReactiveHealthContributor fromMap(Map map, Function valueAdapter) { - return new CompositeReactiveHealthContributorMapAdapter<>(map, valueAdapter); + return new MapCompositeReactiveHealthContributor<>(map, valueAdapter); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorMapAdapter.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapter.java similarity index 60% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorMapAdapter.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapter.java index 6f02061f771..265face7238 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeHealthContributorMapAdapter.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapter.java @@ -14,22 +14,20 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; - -import java.util.Map; -import java.util.function.Function; +package org.springframework.boot.health.contributor; /** - * {@link CompositeHealthContributor} backed by a map with values adapted as necessary. + * Adapts a {@link CompositeReactiveHealthContributor} to a + * {@link CompositeHealthContributor}. * - * @param the value type * @author Phillip Webb + * @see CompositeReactiveHealthContributor#asHealthContributor() */ -class CompositeHealthContributorMapAdapter extends NamedContributorsMapAdapter +class CompositeReactiveHealthContributorAdapter extends ReactiveHealthContributorsAdapter implements CompositeHealthContributor { - CompositeHealthContributorMapAdapter(Map map, Function valueAdapter) { - super(map, valueAdapter); + CompositeReactiveHealthContributorAdapter(ReactiveHealthContributors delegate) { + super(delegate); } } diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributors.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributors.java new file mode 100644 index 00000000000..9df0c5d1330 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributors.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + +/** + * {@link ReactiveHealthContributors} composed of other + * {@link ReactiveHealthContributors}. + * + * @author Phillip Webb + * @see ReactiveHealthContributors#of(ReactiveHealthContributors...) + */ +class CompositeReactiveHealthContributors implements ReactiveHealthContributors { + + private final List contributors; + + CompositeReactiveHealthContributors(ReactiveHealthContributors... contributors) { + this.contributors = List.of(contributors); + } + + @Override + public ReactiveHealthContributor getContributor(String name) { + return this.contributors.stream() + .map((reactiveContributors) -> reactiveContributors.getContributor(name)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + @Override + public Stream stream() { + Set seen = new HashSet<>(); + return this.contributors.stream() + .flatMap(ReactiveHealthContributors::stream) + .filter((element) -> seen.add(element.name())); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Health.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/Health.java similarity index 92% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Health.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/Health.java index 6b60cce8883..f4289bb2a9a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Health.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/Health.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Collections; import java.util.LinkedHashMap; @@ -22,13 +22,14 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonUnwrapped; import org.springframework.util.Assert; /** - * Carries information about the health of a component or subsystem. Extends - * {@link HealthComponent} so that additional contextual details about the system can be - * returned along with the {@link Status}. + * The health of a component or subsystem in including its {@link Status} as well as any + * additional contextual details. Subclasses should expect to be serialized and presented + * to the user, typically as JSON. *

* {@link Health} instances can be created by using {@link Builder}'s fluent API. Typical * usage in a {@link HealthIndicator} would be: @@ -46,10 +47,9 @@ import org.springframework.util.Assert; * @author Christian Dupuis * @author Phillip Webb * @author Michael Pratt - * @since 1.1.0 + * @since 4.0.0 */ -@JsonInclude(Include.NON_EMPTY) -public final class Health extends HealthComponent { +public final class Health { private final Status status; @@ -74,7 +74,7 @@ public final class Health extends HealthComponent { * Return the status of the health. * @return the status (never {@code null}) */ - @Override + @JsonUnwrapped public Status getStatus() { return this.status; } @@ -88,17 +88,8 @@ public final class Health extends HealthComponent { return this.details; } - /** - * Return a new instance of this {@link Health} with all {@link #getDetails() details} - * removed. - * @return a new instance without details - * @since 2.2.0 - */ Health withoutDetails() { - if (this.details.isEmpty()) { - return this; - } - return status(getStatus()).build(); + return (this.details.isEmpty()) ? this : status(getStatus()).build(); } @Override @@ -254,7 +245,6 @@ public final class Health extends HealthComponent { * replace any existing keys if there are duplicates. * @param details map of details * @return this {@link Builder} instance - * @since 2.1.0 */ public Builder withDetails(Map details) { Assert.notNull(details, "'details' must not be null"); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributor.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributor.java similarity index 67% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributor.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributor.java index d65e1586d1a..26b435f8d4d 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributor.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributor.java @@ -14,18 +14,17 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; /** - * Tagging interface for classes that contribute to {@link HealthComponent health - * components} to the results returned from the {@link HealthEndpoint}. A contributor must - * be either a {@link HealthIndicator} or a {@link CompositeHealthContributor}. + * Contributes health information, either directly ({@link HealthIndicator}) or via other + * contributors ({@link CompositeHealthContributor}). * * @author Phillip Webb - * @since 2.2.0 + * @since 4.0.0 * @see HealthIndicator * @see CompositeHealthContributor */ -public interface HealthContributor { +public sealed interface HealthContributor permits HealthIndicator, CompositeHealthContributor { } diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributors.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributors.java new file mode 100644 index 00000000000..fb249da1eeb --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributors.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Iterator; +import java.util.stream.Stream; + +import org.springframework.util.Assert; + +/** + * A collection of named {@link HealthContributor health contributors}. + * + * @author Phillip Webb + * @since 4.0.0 + */ +public interface HealthContributors extends Iterable { + + /** + * Return the contributor with the given name. + * @param name the name of the contributor + * @return a contributor instance or {@code null} + */ + HealthContributor getContributor(String name); + + @Override + default Iterator iterator() { + return stream().iterator(); + } + + /** + * Return a stream of the contributor entries. + * @return the stream of named contributors + */ + Stream stream(); + + /** + * Factory method to create a new {@link HealthContributors} instance composed of the + * given contributors. + * @param contributors the source contributors in the order they should be combined + * @return a new {@link HealthContributors} instance + */ + static HealthContributors of(HealthContributors... contributors) { + return new CompositeHealthContributors(contributors); + } + + /** + * A health contributor entry. + * + * @param name the name of the contributor + * @param contributor the contributor + */ + record Entry(String name, HealthContributor contributor) { + + public Entry { + Assert.hasText(name, "'name' must not be empty"); + Assert.notNull(contributor, "'contributor' must not be null"); + } + + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributorsAdapter.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributorsAdapter.java new file mode 100644 index 00000000000..adb9780fc2e --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthContributorsAdapter.java @@ -0,0 +1,46 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.stream.Stream; + +/** + * Adapts {@link HealthContributors} to {@link ReactiveHealthContributors}. + * + * @author Phillip Webb + * @see ReactiveHealthContributors#adapt(HealthContributors) + */ +class HealthContributorsAdapter implements ReactiveHealthContributors { + + private final HealthContributors delegate; + + HealthContributorsAdapter(HealthContributors delegate) { + this.delegate = delegate; + } + + @Override + public ReactiveHealthContributor getContributor(String name) { + return ReactiveHealthContributor.adapt(this.delegate.getContributor(name)); + } + + @Override + public Stream stream() { + return this.delegate.stream() + .map((entry) -> new Entry(entry.name(), ReactiveHealthContributor.adapt(entry.contributor()))); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicator.java similarity index 76% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicator.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicator.java index d44b85b6d3b..d0ecfbdc449 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicator.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicator.java @@ -14,26 +14,24 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; /** - * Strategy interface used to contribute {@link Health} to the results returned from the - * {@link HealthEndpoint}. + * Directly contributes {@link Health} information for specific component or subsystem. * * @author Dave Syer * @author Phillip Webb - * @since 1.0.0 + * @since 4.0.0 */ @FunctionalInterface -public interface HealthIndicator extends HealthContributor { +public non-sealed interface HealthIndicator extends HealthContributor { /** * Return an indication of health. * @param includeDetails if details should be included or removed * @return the health - * @since 2.2.0 */ - default Health getHealth(boolean includeDetails) { + default Health health(boolean includeDetails) { Health health = health(); return includeDetails ? health : health.withoutDetails(); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapter.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicatorAdapter.java similarity index 83% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapter.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicatorAdapter.java index b9e9aeb0252..09f9bec5920 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapter.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/HealthIndicatorAdapter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; @@ -26,12 +26,13 @@ import org.springframework.util.Assert; * safely invoked in a reactive environment. * * @author Stephane Nicoll + * @see ReactiveHealthContributor#adapt(HealthContributor) */ -class HealthIndicatorReactiveAdapter implements ReactiveHealthIndicator { +class HealthIndicatorAdapter implements ReactiveHealthIndicator { private final HealthIndicator delegate; - HealthIndicatorReactiveAdapter(HealthIndicator delegate) { + HealthIndicatorAdapter(HealthIndicator delegate) { Assert.notNull(delegate, "'delegate' must not be null"); this.delegate = delegate; } diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeHealthContributor.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeHealthContributor.java new file mode 100644 index 00000000000..34c9675e3c5 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeHealthContributor.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.springframework.util.Assert; + +/** + * {@link CompositeHealthContributor} backed by a map with values adapted as necessary. + * + * @param the value type + * @author Phillip Webb + * @see CompositeHealthContributor#fromMap(Map, Function) + */ +class MapCompositeHealthContributor implements CompositeHealthContributor { + + private final Map contributors; + + MapCompositeHealthContributor(Map map, Function valueAdapter) { + Assert.notNull(map, "'map' must not be null"); + Assert.notNull(valueAdapter, "'valueAdapter' must not be null"); + LinkedHashMap contributors = new LinkedHashMap<>(); + map.forEach((key, value) -> { + Assert.notNull(key, "'map' must not contain null keys"); + Assert.notNull(value, "'map' must not contain null values"); + Assert.isTrue(!key.contains("/"), "'map' keys must not contain a '/'"); + contributors.put(key, valueAdapter.apply(value)); + }); + this.contributors = Collections.unmodifiableMap(contributors); + } + + @Override + public HealthContributor getContributor(String name) { + return this.contributors.get(name); + } + + @Override + public Stream stream() { + return this.contributors.entrySet().stream().map((entry) -> new Entry(entry.getKey(), entry.getValue())); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributor.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributor.java new file mode 100644 index 00000000000..4f197785247 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributor.java @@ -0,0 +1,63 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.springframework.util.Assert; + +/** + * {@link CompositeReactiveHealthContributor} backed by a map with values adapted as + * necessary. + * + * @param the value type + * @author Phillip Webb + * @see CompositeReactiveHealthContributor#fromMap(Map, Function) + */ +class MapCompositeReactiveHealthContributor implements CompositeReactiveHealthContributor { + + private final Map contributors; + + MapCompositeReactiveHealthContributor(Map map, + Function valueAdapter) { + Assert.notNull(map, "'map' must not be null"); + Assert.notNull(valueAdapter, "'valueAdapter' must not be null"); + LinkedHashMap contributors = new LinkedHashMap<>(); + map.forEach((key, value) -> { + Assert.notNull(key, "'map' must not contain null keys"); + Assert.notNull(value, "'map' must not contain null values"); + Assert.isTrue(!key.contains("/"), "'map' keys must not contain a '/'"); + contributors.put(key, valueAdapter.apply(value)); + }); + this.contributors = Collections.unmodifiableMap(contributors); + } + + @Override + public ReactiveHealthContributor getContributor(String name) { + return this.contributors.get(name); + } + + @Override + public Stream stream() { + return this.contributors.entrySet().stream().map((entry) -> new Entry(entry.getKey(), entry.getValue())); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/PingHealthIndicator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/PingHealthIndicator.java similarity index 85% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/PingHealthIndicator.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/PingHealthIndicator.java index ba3c19a9a4f..d9316352d7e 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/PingHealthIndicator.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/PingHealthIndicator.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; /** - * Default implementation of {@link HealthIndicator} that returns {@link Status#UP}. + * Auto-configured {@link HealthIndicator} that always returns {@link Status#UP}. * * @author Dave Syer * @author Christian Dupuis - * @since 2.2.0 + * @since 4.0.0 * @see Status#UP */ public class PingHealthIndicator extends AbstractHealthIndicator { diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributor.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributor.java new file mode 100644 index 00000000000..29da2560719 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributor.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import reactor.core.scheduler.Schedulers; + +/** + * Contributes health information, either directly ({@link ReactiveHealthIndicator}) or + * via other contributors ({@link CompositeReactiveHealthContributor}). + * + * @author Phillip Webb + * @author Stephane Nicoll + * @since 4.0.0 + * @see ReactiveHealthIndicator + * @see CompositeReactiveHealthContributor + */ +public sealed interface ReactiveHealthContributor permits ReactiveHealthIndicator, CompositeReactiveHealthContributor { + + /** + * Return this reactive contributor as a standard blocking {@link HealthContributor}. + * @return a blocking health contributor + */ + HealthContributor asHealthContributor(); + + /** + * Adapts the given {@link HealthContributor} into a {@link ReactiveHealthContributor} + * by scheduling blocking calls to {@link Schedulers#boundedElastic()}. + * @param contributor the contributor to adapt or {@code null} + * @return the adapted contributor + */ + static ReactiveHealthContributor adapt(HealthContributor contributor) { + if (contributor == null) { + return null; + } + if (contributor instanceof HealthIndicator healthIndicator) { + return new HealthIndicatorAdapter(healthIndicator); + } + if (contributor instanceof CompositeHealthContributor compositeHealthContributor) { + return new CompositeHealthContributorAdapter(compositeHealthContributor); + } + throw new IllegalStateException("Unknown 'contributor' type"); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributors.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributors.java new file mode 100644 index 00000000000..d8975d50d44 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributors.java @@ -0,0 +1,97 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Iterator; +import java.util.stream.Stream; + +import reactor.core.scheduler.Schedulers; + +import org.springframework.util.Assert; + +/** + * A collection of named {@link ReactiveHealthContributor reactive health contributors}. + * + * @author Phillip Webb + * @since 4.0.0 + */ +public interface ReactiveHealthContributors extends Iterable { + + /** + * Return the contributor with the given name. + * @param name the name of the contributor + * @return a contributor instance or {@code null} + */ + ReactiveHealthContributor getContributor(String name); + + @Override + default Iterator iterator() { + return stream().iterator(); + } + + /** + * Return a stream of the contributor entries. + * @return the stream of named contributors + */ + Stream stream(); + + /** + * Return these reactive contributors as standard blocking {@link HealthContributors}. + * @return blocking health contributors + */ + default HealthContributors asHealthContributors() { + return new ReactiveHealthContributorsAdapter(this); + } + + /** + * Factory method to create a new {@link ReactiveHealthContributors} instance composed + * of the given contributors. + * @param contributors the source contributors in the order they should be combined + * @return a new {@link ReactiveHealthContributors} instance + */ + static ReactiveHealthContributors of(ReactiveHealthContributors... contributors) { + return new CompositeReactiveHealthContributors(contributors); + } + + /** + * Adapts the given {@link HealthContributors} into a + * {@link ReactiveHealthContributors} by scheduling blocking calls to + * {@link Schedulers#boundedElastic()}. + * @param contributors the contributors to adapt or {@code null} + * @return the adapted contributor + * @see ReactiveHealthContributor#adapt(HealthContributor) + */ + static ReactiveHealthContributors adapt(HealthContributors contributors) { + return (contributors != null) ? new HealthContributorsAdapter(contributors) : null; + } + + /** + * A reactive health contributor entry. + * + * @param name the name of the contributor + * @param contributor the contributor + */ + record Entry(String name, ReactiveHealthContributor contributor) { + + public Entry { + Assert.hasText(name, "'name' must not be empty"); + Assert.notNull(contributor, "'contributor' must not be null"); + } + + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapter.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapter.java new file mode 100644 index 00000000000..23f3e00dcc6 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapter.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.stream.Stream; + +/** + * Adapts {@link ReactiveHealthContributors} to {@link HealthContributors}. + * + * @author Phillip Webb + * @see ReactiveHealthContributors#asHealthContributors() + */ +class ReactiveHealthContributorsAdapter implements HealthContributors { + + private final ReactiveHealthContributors delegate; + + ReactiveHealthContributorsAdapter(ReactiveHealthContributors delegate) { + this.delegate = delegate; + } + + @Override + public HealthContributor getContributor(String name) { + return adapt(this.delegate.getContributor(name)); + } + + @Override + public Stream stream() { + return this.delegate.stream().map((entry) -> new Entry(entry.name(), adapt(entry.contributor()))); + } + + private HealthContributor adapt(ReactiveHealthContributor contributor) { + return (contributor != null) ? contributor.asHealthContributor() : null; + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthIndicator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicator.java similarity index 75% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicator.java index f1410a7f2d1..24561e88264 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicator.java @@ -14,31 +14,35 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import reactor.core.publisher.Mono; /** - * Strategy interface used to contribute {@link Health} to the results returned from the - * reactive variant of the {@link HealthEndpoint}. + * Directly contributes {@link Health} information for specific reactive component or + * subsystem. *

* This is non-blocking contract that is meant to be used in a reactive application. See * {@link HealthIndicator} for the traditional contract. * * @author Stephane Nicoll - * @since 2.0.0 + * @since 4.0.0 * @see HealthIndicator */ @FunctionalInterface -public interface ReactiveHealthIndicator extends ReactiveHealthContributor { +public non-sealed interface ReactiveHealthIndicator extends ReactiveHealthContributor { + + @Override + default HealthIndicator asHealthContributor() { + return new ReactiveHealthIndicatorAdapter(this); + } /** * Provide the indicator of health. * @param includeDetails if details should be included or removed * @return a {@link Mono} that provides the {@link Health} - * @since 2.2.0 */ - default Mono getHealth(boolean includeDetails) { + default Mono health(boolean includeDetails) { Mono health = health(); return includeDetails ? health : health.map(Health::withoutDetails); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorMapAdapter.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapter.java similarity index 53% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorMapAdapter.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapter.java index 4c603467620..ebdcc408db6 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorMapAdapter.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapter.java @@ -14,24 +14,30 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; - -import java.util.Map; -import java.util.function.Function; +package org.springframework.boot.health.contributor; /** - * {@link CompositeReactiveHealthContributor} backed by a map with values adapted as - * necessary. + * Adapts a {@link ReactiveHealthIndicator} to a {@link HealthIndicator}. * - * @param the value type * @author Phillip Webb + * @see ReactiveHealthIndicator#asHealthContributor() */ -class CompositeReactiveHealthContributorMapAdapter extends NamedContributorsMapAdapter - implements CompositeReactiveHealthContributor { +class ReactiveHealthIndicatorAdapter implements HealthIndicator { - CompositeReactiveHealthContributorMapAdapter(Map map, - Function valueAdapter) { - super(map, valueAdapter); + private final ReactiveHealthIndicator delegate; + + ReactiveHealthIndicatorAdapter(ReactiveHealthIndicator indicator) { + this.delegate = indicator; + } + + @Override + public Health health(boolean includeDetails) { + return this.delegate.health(includeDetails).block(); + } + + @Override + public Health health() { + return this.delegate.health().block(); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Status.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/Status.java similarity index 97% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Status.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/Status.java index 2d43d84a517..07fbfefd78d 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Status.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/Status.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -32,7 +32,7 @@ import org.springframework.util.ObjectUtils; * Custom states can also be created and used throughout the Spring Boot Health subsystem. * * @author Christian Dupuis - * @since 1.1.0 + * @since 4.0.0 */ @JsonInclude(Include.NON_EMPTY) public final class Status { diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/package-info.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/package-info.java new file mode 100644 index 00000000000..7a853a5ac87 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/contributor/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to contributing health information about an application. + */ +package org.springframework.boot.health.contributor; diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/AbstractRegistry.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/AbstractRegistry.java new file mode 100644 index 00000000000..46c54b39f09 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/AbstractRegistry.java @@ -0,0 +1,110 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +/** + * Internal base class for health registries. + * + * @param the contributor type + * @param the entry type + * @author Phillip Webb + */ +abstract class AbstractRegistry { + + private final Collection nameValidators; + + private final BiFunction entryAdapter; + + private volatile Map contributors; + + private final Object monitor = new Object(); + + AbstractRegistry(BiFunction entryAdapter, + Collection nameValidators, + Consumer> intialRegistrations) { + this.nameValidators = (nameValidators != null) ? List.copyOf(nameValidators) : Collections.emptyList(); + this.entryAdapter = entryAdapter; + Map contributors = new LinkedHashMap<>(); + if (intialRegistrations != null) { + intialRegistrations.accept((name, contributor) -> registerContributor(contributors, name, contributor)); + } + this.contributors = Collections.unmodifiableMap(contributors); + } + + void registerContributor(String name, C contributor) { + synchronized (this.monitor) { + Map contributors = new LinkedHashMap<>(this.contributors); + registerContributor(contributors, name, contributor); + this.contributors = Collections.unmodifiableMap(contributors); + } + } + + private void registerContributor(Map contributors, String name, C contributor) { + Assert.hasText(name, "'name' must not be empty"); + Assert.notNull(contributor, "'contributor' must not be null"); + verifyName(name, contributor); + Assert.state(!contributors.containsKey(name), + () -> "A contributor named \"" + name + "\" has already been registered"); + contributors.put(name, contributor); + } + + C unregisterContributor(String name) { + Assert.notNull(name, "'name' must not be null"); + synchronized (this.monitor) { + C unregistered = this.contributors.get(name); + if (unregistered != null) { + Map contributors = new LinkedHashMap<>(this.contributors); + contributors.remove(name); + this.contributors = Collections.unmodifiableMap(contributors); + } + return unregistered; + } + } + + C getContributor(String name) { + return this.contributors.get(name); + } + + Stream stream() { + return this.contributors.entrySet() + .stream() + .map((entry) -> this.entryAdapter.apply(entry.getKey(), entry.getValue())); + } + + private void verifyName(String name, C contributor) { + Assert.state(StringUtils.hasText(name), + () -> "Name for contributor '%s' must not be empty".formatted(contributor)); + if (!CollectionUtils.isEmpty(this.nameValidators)) { + this.nameValidators.forEach((nameValidator) -> nameValidator.validate(name)); + } + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistry.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistry.java new file mode 100644 index 00000000000..3b3cb591dc1 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistry.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import java.util.Collection; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors.Entry; + +/** + * Default {@link HealthContributorRegistry} implementation. + * + * @author Phillip Webb + * @since 4.0.0 + */ +public class DefaultHealthContributorRegistry extends AbstractRegistry + implements HealthContributorRegistry { + + /** + * Create a new empty {@link DefaultHealthContributorRegistry} instance. + */ + public DefaultHealthContributorRegistry() { + this(null, null); + } + + /** + * Create a new {@link DefaultHealthContributorRegistry} instance. + * @param nameValidators the name validators to apply + * @param intialRegistrations callback to setup any initial registrations + */ + public DefaultHealthContributorRegistry(Collection nameValidators, + Consumer> intialRegistrations) { + super(Entry::new, nameValidators, intialRegistrations); + } + + @Override + public HealthContributor getContributor(String name) { + return super.getContributor(name); + } + + @Override + public Stream stream() { + return super.stream(); + } + + @Override + public void registerContributor(String name, HealthContributor contributor) { + super.registerContributor(name, contributor); + } + + @Override + public HealthContributor unregisterContributor(String name) { + return super.unregisterContributor(name); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistry.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistry.java new file mode 100644 index 00000000000..20ffc646e7d --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistry.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import java.util.Collection; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributors.Entry; + +/** + * Default {@link ReactiveHealthContributorRegistry} implementation. + * + * @author Phillip Webb + * @since 4.0.0 + */ +public class DefaultReactiveHealthContributorRegistry extends AbstractRegistry + implements ReactiveHealthContributorRegistry { + + /** + * Create a new empty {@link DefaultReactiveHealthContributorRegistry} instance. + */ + public DefaultReactiveHealthContributorRegistry() { + this(null, null); + } + + /** + * Create a new {@link DefaultReactiveHealthContributorRegistry} instance. + * @param nameValidators the name validators to apply + * @param intialRegistrations callback to setup any initial registrations + */ + public DefaultReactiveHealthContributorRegistry(Collection nameValidators, + Consumer> intialRegistrations) { + super(Entry::new, nameValidators, intialRegistrations); + } + + @Override + public ReactiveHealthContributor getContributor(String name) { + return super.getContributor(name); + } + + @Override + public Stream stream() { + return super.stream(); + } + + @Override + public void registerContributor(String name, ReactiveHealthContributor contributor) { + super.registerContributor(name, contributor); + } + + @Override + public ReactiveHealthContributor unregisterContributor(String name) { + return super.unregisterContributor(name); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorNameValidator.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorNameValidator.java new file mode 100644 index 00000000000..2ce0bfd460f --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorNameValidator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +/** + * Interface that can be used to validate names before they are added to a health + * contributor registry. + * + * @author Phillip Webb + * @since 4.0.0 + */ +@FunctionalInterface +public interface HealthContributorNameValidator { + + /** + * Validate the contributor name. + * @param name the name to validate + * @throws IllegalStateException on an invalid name + */ + void validate(String name) throws IllegalStateException; + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ContributorRegistry.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorRegistry.java similarity index 70% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ContributorRegistry.java rename to spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorRegistry.java index af2efbe4d97..e78dbb584b8 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ContributorRegistry.java +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/HealthContributorRegistry.java @@ -14,21 +14,18 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.registry; + +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; /** - * A mutable registry of health endpoint contributors (either {@link HealthContributor} or - * {@link ReactiveHealthContributor}). + * A mutable registry of {@link HealthContributor health contributors}. * - * @param the contributor type * @author Phillip Webb - * @author Andy Wilkinson - * @author Vedran Pavic - * @author Stephane Nicoll - * @since 2.2.0 - * @see NamedContributors + * @since 4.0.0 */ -public interface ContributorRegistry extends NamedContributors { +public interface HealthContributorRegistry extends HealthContributors { /** * Register a contributor with the given {@code name}. @@ -37,7 +34,7 @@ public interface ContributorRegistry extends NamedContributors { * @throws IllegalStateException if the contributor cannot be registered with the * given {@code name}. */ - void registerContributor(String name, C contributor); + void registerContributor(String name, HealthContributor contributor); /** * Unregister a previously registered contributor. @@ -45,6 +42,6 @@ public interface ContributorRegistry extends NamedContributors { * @return the unregistered indicator, or {@code null} if no indicator was found in * the registry for the given {@code name}. */ - C unregisterContributor(String name); + HealthContributor unregisterContributor(String name); } diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/ReactiveHealthContributorRegistry.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/ReactiveHealthContributorRegistry.java new file mode 100644 index 00000000000..b34f66e23d1 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/ReactiveHealthContributorRegistry.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributors; + +/** + * A mutable registry of {@link ReactiveHealthContributor reactive health contributors}. + * + * @author Phillip Webb + * @since 4.0.0 + */ +public interface ReactiveHealthContributorRegistry extends ReactiveHealthContributors { + + /** + * Register a contributor with the given {@code name}. + * @param name the name of the contributor + * @param contributor the contributor to register + * @throws IllegalStateException if the contributor cannot be registered with the + * given {@code name}. + */ + void registerContributor(String name, ReactiveHealthContributor contributor); + + /** + * Unregister a previously registered contributor. + * @param name the name of the contributor to unregister + * @return the unregistered indicator, or {@code null} if no indicator was found in + * the registry for the given {@code name}. + */ + ReactiveHealthContributor unregisterContributor(String name); + +} diff --git a/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/package-info.java b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/package-info.java new file mode 100644 index 00000000000..ca2b7d73ae6 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/java/org/springframework/boot/health/registry/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Health registry support. + */ +package org.springframework.boot.health.registry; diff --git a/spring-boot-project/spring-boot-health/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-project/spring-boot-health/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..7346e1595a1 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration +org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfigurationTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/AbstractCompositeHealthContributorConfigurationTests.java similarity index 92% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfigurationTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/AbstractCompositeHealthContributorConfigurationTests.java index c2a59b33c19..b6b2dd77990 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfigurationTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/AbstractCompositeHealthContributorConfigurationTests.java @@ -14,16 +14,15 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.NamedContributor; -import org.springframework.boot.actuate.health.NamedContributors; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -71,7 +70,7 @@ abstract class AbstractCompositeHealthContributorConfigurationTests) contributor).stream().map(NamedContributor::getName)) - .containsExactlyInAnyOrder("standard", "nonDefault"); + assertThat(ClassUtils.getShortName(contributor.getClass())).startsWith("MapComposite"); + assertThat(allNamesFromComposite(contributor)).containsExactlyInAnyOrder("standard", "nonDefault"); } } protected abstract AbstractCompositeHealthContributorConfiguration newComposite(); + protected abstract Stream allNamesFromComposite(C composite); + static class TestBean { } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfigurationTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/CompositeHealthContributorConfigurationTests.java similarity index 65% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfigurationTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/CompositeHealthContributorConfigurationTests.java index 60288ed3592..487181ec142 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfigurationTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/CompositeHealthContributorConfigurationTests.java @@ -14,12 +14,15 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfigurationTests.TestHealthIndicator; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.HealthContributor; +import java.util.stream.Stream; + +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfigurationTests.TestHealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; /** * Tests for {@link CompositeHealthContributorConfiguration}. @@ -34,6 +37,11 @@ class CompositeHealthContributorConfigurationTests return new TestCompositeHealthContributorConfiguration(); } + @Override + protected Stream allNamesFromComposite(HealthContributor composite) { + return ((HealthContributors) composite).stream().map(HealthContributors.Entry::name); + } + static class TestCompositeHealthContributorConfiguration extends CompositeHealthContributorConfiguration { @@ -49,7 +57,7 @@ class CompositeHealthContributorConfigurationTests } @Override - protected void doHealthCheck(Builder builder) throws Exception { + protected void doHealthCheck(Health.Builder builder) throws Exception { builder.up(); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/CompositeReactiveHealthContributorConfigurationTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/CompositeReactiveHealthContributorConfigurationTests.java similarity index 67% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/CompositeReactiveHealthContributorConfigurationTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/CompositeReactiveHealthContributorConfigurationTests.java index 8602ee9c003..80266172850 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/CompositeReactiveHealthContributorConfigurationTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/CompositeReactiveHealthContributorConfigurationTests.java @@ -14,15 +14,17 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; + +import java.util.stream.Stream; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfigurationTests.TestReactiveHealthIndicator; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfigurationTests.TestReactiveHealthIndicator; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributors; /** * Tests for {@link CompositeReactiveHealthContributorConfiguration}. @@ -37,6 +39,11 @@ class CompositeReactiveHealthContributorConfigurationTests extends return new TestCompositeReactiveHealthContributorConfiguration(); } + @Override + protected Stream allNamesFromComposite(ReactiveHealthContributor composite) { + return ((ReactiveHealthContributors) composite).stream().map(ReactiveHealthContributors.Entry::name); + } + static class TestCompositeReactiveHealthContributorConfiguration extends CompositeReactiveHealthContributorConfiguration { @@ -52,7 +59,7 @@ class CompositeReactiveHealthContributorConfigurationTests extends } @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.just(builder.up().build()); } diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicatorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicatorTests.java new file mode 100644 index 00000000000..1ca977c6728 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/ConditionalOnEnabledHealthIndicatorTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.autoconfigure.contributor; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.PingHealthIndicator; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ConditionalOnEnabledHealthIndicator}. + * + * @author Phillip Webb + */ +class ConditionalOnEnabledHealthIndicatorTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(CustomHealthIndicatorConfiguration.class); + + @Test + void whenNoPropertyCreatesBean() { + this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HealthIndicator.class)); + } + + @Test + void whenIndicatorPropertyTrueCreatesBean() { + this.contextRunner.withPropertyValues("management.health.custom.enabled=true") + .run((context) -> assertThat(context).hasSingleBean(HealthIndicator.class)); + } + + @Test + void whenIndicatorPropertyFalseDoesNotCreateBean() { + this.contextRunner.withPropertyValues("management.health.custom.enabled=false") + .run((context) -> assertThat(context).doesNotHaveBean(HealthIndicator.class)); + } + + @Test + void whenDefaultsPropertyTrueCreatesBean() { + this.contextRunner.withPropertyValues("management.health.defaults.enabled=true") + .run((context) -> assertThat(context).hasSingleBean(HealthIndicator.class)); + } + + @Test + void whenDefaultsPropertyFalseDoesNotCreateBean() { + this.contextRunner.withPropertyValues("management.health.defaults.enabled=false") + .run((context) -> assertThat(context).doesNotHaveBean(HealthIndicator.class)); + } + + @Test + void whenIndicatorPropertyTrueAndDefaultsPropertyFalseCreatesBean() { + this.contextRunner + .withPropertyValues("management.health.custom.enabled=true", "management.health.defaults.enabled=false") + .run((context) -> assertThat(context).hasSingleBean(HealthIndicator.class)); + } + + @Test + void whenIndicatorPropertyFalseAndDefaultsPropertyTrueDoesNotCreateBean() { + this.contextRunner + .withPropertyValues("management.health.custom.enabled=false", "management.health.defaults.enabled=true") + .run((context) -> assertThat(context).doesNotHaveBean(HealthIndicator.class)); + } + + @Configuration(proxyBeanMethods = false) + static class CustomHealthIndicatorConfiguration { + + @Bean + @ConditionalOnEnabledHealthIndicator("custom") + PingHealthIndicator customHealthIndicator() { + return new PingHealthIndicator(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/HealthContributorAutoConfigurationTests.java similarity index 91% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfigurationTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/HealthContributorAutoConfigurationTests.java index 7516fa02d34..3e828f208cb 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/contributor/HealthContributorAutoConfigurationTests.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.health; +package org.springframework.boot.health.autoconfigure.contributor; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.PingHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.PingHealthIndicator; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -57,7 +57,6 @@ class HealthContributorAutoConfigurationTests { this.contextRunner.withUserConfiguration(CustomHealthIndicatorConfiguration.class) .withPropertyValues("management.health.defaults.enabled:false") .run((context) -> assertThat(context).doesNotHaveBean(HealthIndicator.class)); - } @Test @@ -65,7 +64,6 @@ class HealthContributorAutoConfigurationTests { this.contextRunner.withUserConfiguration(CustomHealthIndicatorConfiguration.class) .withPropertyValues("management.health.defaults.enabled:false", "management.health.ping.enabled:true") .run((context) -> assertThat(context).hasSingleBean(PingHealthIndicator.class)); - } @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGeneratorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGeneratorTests.java new file mode 100644 index 00000000000..aa0e1767cdf --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorNameGeneratorTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.autoconfigure.registry; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link HealthContributorNameGenerator}. + * + * @author Phillip Webb + */ +class HealthContributorNameGeneratorTests { + + @Test + void withoutStandardSuffixesWhenNameDoesNotEndWithSuffixReturnsName() { + assertThat(HealthContributorNameGenerator.withoutStandardSuffixes().generateContributorName("test")) + .isEqualTo("test"); + } + + @Test + void withoutStandardSuffixesWhenNameEndsWithSuffixReturnsNewName() { + assertThat( + HealthContributorNameGenerator.withoutStandardSuffixes().generateContributorName("testHealthIndicator")) + .isEqualTo("test"); + assertThat(HealthContributorNameGenerator.withoutStandardSuffixes() + .generateContributorName("testHealthContributor")).isEqualTo("test"); + } + + @Test + void withoutStandardSuffixesWhenNameEndsWithSuffixInDifferentReturnsNewName() { + assertThat( + HealthContributorNameGenerator.withoutStandardSuffixes().generateContributorName("testHEALTHindicator")) + .isEqualTo("test"); + assertThat(HealthContributorNameGenerator.withoutStandardSuffixes() + .generateContributorName("testHEALTHcontributor")).isEqualTo("test"); + } + + @Test + void withoutStandardSuffixesWhenNameContainsSuffixReturnsName() { + assertThat(HealthContributorNameGenerator.withoutStandardSuffixes() + .generateContributorName("testHealthIndicatorTest")).isEqualTo("testHealthIndicatorTest"); + assertThat(HealthContributorNameGenerator.withoutStandardSuffixes() + .generateContributorName("testHealthContributorTest")).isEqualTo("testHealthContributorTest"); + } + + @Test + void withoutSuffixesStripsSuffix() { + HealthContributorNameGenerator generator = HealthContributorNameGenerator.withoutSuffixes("spring", "boot"); + assertThat(generator.generateContributorName("testspring")).isEqualTo("test"); + assertThat(generator.generateContributorName("tEsTsPrInG")).isEqualTo("tEsT"); + assertThat(generator.generateContributorName("springboot")).isEqualTo("spring"); + assertThat(generator.generateContributorName("springspring")).isEqualTo("spring"); + assertThat(generator.generateContributorName("test")).isEqualTo("test"); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfigurationTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfigurationTests.java new file mode 100644 index 00000000000..e7c32966b1a --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/autoconfigure/registry/HealthContributorRegistryAutoConfigurationTests.java @@ -0,0 +1,158 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.autoconfigure.registry; + +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributors; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributors; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.registry.DefaultHealthContributorRegistry; +import org.springframework.boot.health.registry.DefaultReactiveHealthContributorRegistry; +import org.springframework.boot.health.registry.HealthContributorRegistry; +import org.springframework.boot.health.registry.ReactiveHealthContributorRegistry; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link HealthContributorRegistryAutoConfiguration}. + * + * @author Phillip Webb + * @author Andy Wilkinson + * @author Stephane Nicoll + * @author Scott Frederick + */ +class HealthContributorRegistryAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(HealthIndicatorsConfiguration.class) + .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class)); + + @Test + void runCreatesHealthContributorRegistriesContainingHealthBeans() { + this.contextRunner.run((context) -> { + HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); + assertThat(names).containsExactlyInAnyOrder("simple", "additional", "ping"); + ReactiveHealthContributorRegistry reactiveRegistry = context + .getBean(ReactiveHealthContributorRegistry.class); + Object[] reactiveNames = reactiveRegistry.stream().map(ReactiveHealthContributors.Entry::name).toArray(); + assertThat(reactiveNames).containsExactlyInAnyOrder("reactive"); + }); + } + + @Test + void runWhenNoReactorCreatesHealthContributorRegistryContainingHealthBeans() { + ClassLoader classLoader = new FilteredClassLoader(Mono.class, Flux.class); + this.contextRunner.withClassLoader(classLoader).run((context) -> { + HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); + assertThat(names).containsExactlyInAnyOrder("simple", "additional", "ping"); + }); + } + + @Test + void runWhenHasHealthContributorRegistryBeanDoesNotCreateAdditionalRegistry() { + this.contextRunner.withUserConfiguration(HealthContributorRegistryConfiguration.class).run((context) -> { + HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); + assertThat(names).isEmpty(); + }); + } + + @Test + void runWhenHasReactiveHealthContributorRegistryBeanDoesNotCreateAdditionalReactiveHealthContributorRegistry() { + this.contextRunner.withUserConfiguration(ReactiveHealthContributorRegistryConfiguration.class) + .run((context) -> { + ReactiveHealthContributorRegistry registry = context.getBean(ReactiveHealthContributorRegistry.class); + Object[] names = registry.stream().map(ReactiveHealthContributors.Entry::name).toArray(); + assertThat(names).isEmpty(); + }); + } + + @Test + void runWithIndicatorsInParentContextFindsIndicators() { + new ApplicationContextRunner().withUserConfiguration(HealthIndicatorsConfiguration.class) + .run((parent) -> new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class)) + .withParent(parent) + .run((context) -> { + HealthContributorRegistry registry = context.getBean(HealthContributorRegistry.class); + Object[] names = registry.stream().map(HealthContributors.Entry::name).toArray(); + assertThat(names).containsExactlyInAnyOrder("simple", "additional", "ping"); + ReactiveHealthContributorRegistry reactiveRegistry = context + .getBean(ReactiveHealthContributorRegistry.class); + Object[] reactiveNames = reactiveRegistry.stream() + .map(ReactiveHealthContributors.Entry::name) + .toArray(); + assertThat(reactiveNames).containsExactlyInAnyOrder("reactive"); + })); + } + + @Configuration(proxyBeanMethods = false) + static class HealthIndicatorsConfiguration { + + @Bean + HealthIndicator simpleHealthIndicator() { + return () -> Health.up().withDetail("counter", 42).build(); + } + + @Bean + HealthIndicator additionalHealthIndicator() { + return () -> Health.up().build(); + } + + @Bean + ReactiveHealthIndicator reactiveHealthIndicator() { + return () -> Mono.just(Health.up().build()); + } + + } + + @Configuration(proxyBeanMethods = false) + static class HealthContributorRegistryConfiguration { + + @Bean + HealthContributorRegistry healthContributorRegistry() { + return new DefaultHealthContributorRegistry(); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ReactiveHealthContributorRegistryConfiguration { + + @Bean + ReactiveHealthContributorRegistry reactiveHealthContributorRegistry() { + return new DefaultReactiveHealthContributorRegistry(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/AbstractHealthIndicatorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/AbstractHealthIndicatorTests.java similarity index 91% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/AbstractHealthIndicatorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/AbstractHealthIndicatorTests.java index 23c72da517d..6cf814488ef 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/AbstractHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/AbstractHealthIndicatorTests.java @@ -14,14 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.function.Consumer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.actuate.health.Health.Builder; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -38,7 +37,7 @@ class AbstractHealthIndicatorTests { @Test void healthCheckWhenUpDoesNotLogHealthCheckFailedMessage(CapturedOutput output) { - TestHealthIndicator indicator = new TestHealthIndicator("Test message", Builder::up); + TestHealthIndicator indicator = new TestHealthIndicator("Test message", Health.Builder::up); Health heath = indicator.health(); assertThat(heath.getStatus()).isEqualTo(Status.UP); assertThat(output).doesNotContain("Test message"); @@ -95,19 +94,19 @@ class AbstractHealthIndicatorTests { static class TestHealthIndicator extends AbstractHealthIndicator { - private final Consumer action; + private final Consumer action; - TestHealthIndicator(String message, Consumer action) { + TestHealthIndicator(String message, Consumer action) { super(message); this.action = action; } - TestHealthIndicator(Consumer action) { + TestHealthIndicator(Consumer action) { this.action = action; } @Override - protected void doHealthCheck(Builder builder) throws Exception { + protected void doHealthCheck(Health.Builder builder) throws Exception { this.action.accept(builder); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/AbstractReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/AbstractReactiveHealthIndicatorTests.java similarity index 88% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/AbstractReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/AbstractReactiveHealthIndicatorTests.java index 06ef82317f3..cdaf13decbb 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/AbstractReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/AbstractReactiveHealthIndicatorTests.java @@ -14,13 +14,12 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.Health.Builder; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -30,6 +29,8 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link AbstractReactiveHealthIndicator}. * * @author Moritz Halbritter + * @author Dmytro Nosan + * @author Stephane Nicoll */ @ExtendWith(OutputCaptureExtension.class) class AbstractReactiveHealthIndicatorTests { @@ -37,8 +38,9 @@ class AbstractReactiveHealthIndicatorTests { @Test void healthCheckWhenUpDoesNotLogHealthCheckFailedMessage(CapturedOutput output) { Health health = new AbstractReactiveHealthIndicator("Test message") { + @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.just(builder.up().build()); } @@ -51,10 +53,12 @@ class AbstractReactiveHealthIndicatorTests { @Test void healthCheckWhenDownWithExceptionThrownLogsHealthCheckFailedMessage(CapturedOutput output) { Health health = new AbstractReactiveHealthIndicator("Test message") { + @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { throw new IllegalStateException("Test exception"); } + }.health().block(); assertThat(health).isNotNull(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); @@ -64,10 +68,12 @@ class AbstractReactiveHealthIndicatorTests { @Test void healthCheckWhenDownWithExceptionConfiguredLogsHealthCheckFailedMessage(CapturedOutput output) { Health health = new AbstractReactiveHealthIndicator("Test message") { + @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.just(builder.down().withException(new IllegalStateException("Test exception")).build()); } + }.health().block(); assertThat(health).isNotNull(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); @@ -77,12 +83,14 @@ class AbstractReactiveHealthIndicatorTests { @Test void healthCheckWhenDownWithExceptionConfiguredDoesNotLogHealthCheckFailedMessageTwice(CapturedOutput output) { Health health = new AbstractReactiveHealthIndicator("Test message") { + @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { IllegalStateException ex = new IllegalStateException("Test exception"); builder.down().withException(ex); throw ex; } + }.health().block(); assertThat(health).isNotNull(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); @@ -92,10 +100,12 @@ class AbstractReactiveHealthIndicatorTests { @Test void healthCheckWhenDownWithExceptionAndNoFailureMessageLogsDefaultMessage(CapturedOutput output) { Health health = new AbstractReactiveHealthIndicator() { + @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.just(builder.down().withException(new IllegalStateException("Test exception")).build()); } + }.health().block(); assertThat(health).isNotNull(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); @@ -105,10 +115,12 @@ class AbstractReactiveHealthIndicatorTests { @Test void healthCheckWhenDownWithErrorLogsDefaultMessage(CapturedOutput output) { Health health = new AbstractReactiveHealthIndicator("Test Message") { + @Override - protected Mono doHealthCheck(Builder builder) { + protected Mono doHealthCheck(Health.Builder builder) { return Mono.just(builder.down().withException(new Error("Test error")).build()); } + }.health().block(); assertThat(health).isNotNull(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorRegistry.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapterTests.java similarity index 64% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorRegistry.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapterTests.java index 0773dd3d743..6d58e23c0c7 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorRegistry.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorAdapterTests.java @@ -14,14 +14,18 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; /** - * {@link ContributorRegistry} for {@link HealthContributor HealthContributors}. + * Tests for {@link CompositeHealthContributorAdapter}. * * @author Phillip Webb - * @since 2.2.0 */ -public interface HealthContributorRegistry extends ContributorRegistry { +class CompositeHealthContributorAdapterTests extends HealthContributorsAdapterTests { + + @Override + protected CompositeHealthContributorAdapter createAdapter(CompositeHealthContributor delegate) { + return new CompositeHealthContributorAdapter(delegate); + } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorTests.java similarity index 71% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorTests.java index 401ef576c48..c006575db00 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.LinkedHashMap; import java.util.Map; @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link CompositeHealthContributor}. * * @author Phillip Webb + * @author Guirong Hu */ class CompositeHealthContributorTests { @@ -36,10 +37,10 @@ class CompositeHealthContributorTests { HealthIndicator indicator = () -> Health.down().build(); map.put("test", indicator); CompositeHealthContributor composite = CompositeHealthContributor.fromMap(map); - assertThat(composite).isInstanceOf(CompositeHealthContributorMapAdapter.class); - NamedContributor namedContributor = composite.iterator().next(); - assertThat(namedContributor.getName()).isEqualTo("test"); - assertThat(namedContributor.getContributor()).isSameAs(indicator); + assertThat(composite).isInstanceOf(MapCompositeHealthContributor.class); + HealthContributors.Entry entry = composite.iterator().next(); + assertThat(entry.name()).isEqualTo("test"); + assertThat(entry.contributor()).isSameAs(indicator); } @Test @@ -49,10 +50,10 @@ class CompositeHealthContributorTests { HealthIndicator upIndicator = () -> Health.up().build(); map.put("test", downIndicator); CompositeHealthContributor composite = CompositeHealthContributor.fromMap(map, (value) -> upIndicator); - assertThat(composite).isInstanceOf(CompositeHealthContributorMapAdapter.class); - NamedContributor namedContributor = composite.iterator().next(); - assertThat(namedContributor.getName()).isEqualTo("test"); - assertThat(namedContributor.getContributor()).isSameAs(upIndicator); + assertThat(composite).isInstanceOf(MapCompositeHealthContributor.class); + HealthContributors.Entry entry = composite.iterator().next(); + assertThat(entry.name()).isEqualTo("test"); + assertThat(entry.contributor()).isSameAs(upIndicator); } } diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorsTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorsTests.java new file mode 100644 index 00000000000..c46ec749d5c --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeHealthContributorsTests.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.health.contributor.HealthContributors.Entry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link CompositeHealthContributors}. + * + * @author Phillip Webb + */ +class CompositeHealthContributorsTests { + + @Test + void getContributorWhenManyReturnsFirstContributor() { + HealthIndicator a1 = mock(HealthIndicator.class); + CompositeHealthContributor c1 = CompositeHealthContributor.fromMap(Map.of("a", a1)); + HealthIndicator a2 = mock(HealthIndicator.class); + CompositeHealthContributor c2 = CompositeHealthContributor.fromMap(Map.of("a", a2)); + HealthContributors composite = HealthContributors.of(c1, c2); + assertThat(composite.getContributor("a")).isSameAs(a1); + } + + @Test + void getContributorWhenNoneReturnsNull() { + HealthIndicator a = mock(HealthIndicator.class); + HealthContributors composite = HealthContributors.of(CompositeHealthContributor.fromMap(Map.of("a", a))); + assertThat(composite.getContributor("x")).isNull(); + } + + @Test + void streamStreamsWithoutDuplicates() { + HealthIndicator a1 = mock(HealthIndicator.class); + CompositeHealthContributor c1 = CompositeHealthContributor.fromMap(Map.of("a", a1)); + HealthIndicator a2 = mock(HealthIndicator.class); + CompositeHealthContributor c2 = CompositeHealthContributor.fromMap(Map.of("a", a2)); + HealthIndicator b = mock(HealthIndicator.class); + CompositeHealthContributor c3 = CompositeHealthContributor.fromMap(Map.of("b", b)); + HealthContributors composite = HealthContributors.of(c1, c2, c3); + assertThat(composite.stream()).containsExactly(new Entry("a", a1), new Entry("b", b)); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributorRegistry.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapterTests.java similarity index 61% rename from spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributorRegistry.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapterTests.java index 06ae7b5fda2..0dd8468246d 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributorRegistry.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorAdapterTests.java @@ -14,15 +14,18 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; /** - * {@link ContributorRegistry} for {@link ReactiveHealthContributor - * ReactiveHealthContributors}. + * Tests for {@link CompositeReactiveHealthContributorAdapter}. * * @author Phillip Webb - * @since 2.2.0 */ -public interface ReactiveHealthContributorRegistry extends ContributorRegistry { +class CompositeReactiveHealthContributorAdapterTests extends ReactiveHealthContributorsAdapterTests { + + @Override + protected CompositeReactiveHealthContributorAdapter createAdapter(CompositeReactiveHealthContributor delegate) { + return new CompositeReactiveHealthContributorAdapter(delegate); + } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorTests.java similarity index 55% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorTests.java index ba770391ec8..02b2896b882 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeReactiveHealthContributorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.LinkedHashMap; import java.util.Map; @@ -31,16 +31,31 @@ import static org.assertj.core.api.Assertions.assertThat; */ class CompositeReactiveHealthContributorTests { + @Test + void asHealthContributorReturnsAdaptedContributor() { + ReactiveHealthIndicator indicator = () -> Mono.just(Health.up().withDetail("spring", "boot").build()); + Map reactiveContributors = Map.of("test", indicator); + CompositeReactiveHealthContributor contributor = CompositeReactiveHealthContributor + .fromMap(reactiveContributors); + CompositeHealthContributor adapted = contributor.asHealthContributor(); + HealthIndicator byName = (HealthIndicator) adapted.getContributor("test"); + assertThat(byName.health(true).getDetails()).containsEntry("spring", "boot"); + HealthContributors.Entry entry = adapted.iterator().next(); + assertThat(entry.name()).isEqualTo("test"); + HealthIndicator byEntry = (HealthIndicator) entry.contributor(); + assertThat(byEntry.health(true).getDetails()).containsEntry("spring", "boot"); + } + @Test void fromMapReturnsCompositeReactiveHealthContributorMapAdapter() { Map map = new LinkedHashMap<>(); ReactiveHealthIndicator indicator = () -> Mono.just(Health.down().build()); map.put("test", indicator); CompositeReactiveHealthContributor composite = CompositeReactiveHealthContributor.fromMap(map); - assertThat(composite).isInstanceOf(CompositeReactiveHealthContributorMapAdapter.class); - NamedContributor namedContributor = composite.iterator().next(); - assertThat(namedContributor.getName()).isEqualTo("test"); - assertThat(namedContributor.getContributor()).isSameAs(indicator); + assertThat(composite).isInstanceOf(MapCompositeReactiveHealthContributor.class); + ReactiveHealthContributors.Entry entry = composite.iterator().next(); + assertThat(entry.name()).isEqualTo("test"); + assertThat(entry.contributor()).isSameAs(indicator); } @Test @@ -51,10 +66,10 @@ class CompositeReactiveHealthContributorTests { map.put("test", downIndicator); CompositeReactiveHealthContributor composite = CompositeReactiveHealthContributor.fromMap(map, (value) -> upIndicator); - assertThat(composite).isInstanceOf(CompositeReactiveHealthContributorMapAdapter.class); - NamedContributor namedContributor = composite.iterator().next(); - assertThat(namedContributor.getName()).isEqualTo("test"); - assertThat(namedContributor.getContributor()).isSameAs(upIndicator); + assertThat(composite).isInstanceOf(MapCompositeReactiveHealthContributor.class); + ReactiveHealthContributors.Entry entry = composite.iterator().next(); + assertThat(entry.name()).isEqualTo("test"); + assertThat(entry.contributor()).isSameAs(upIndicator); } } diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorsTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorsTests.java new file mode 100644 index 00000000000..c0798d02880 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/CompositeReactiveHealthContributorsTests.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.health.contributor.ReactiveHealthContributors.Entry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link CompositeReactiveHealthContributors}. + * + * @author Phillip Webb + */ +class CompositeReactiveHealthContributorsTests { + + @Test + void getContributorWhenManyReturnsFirstContributor() { + ReactiveHealthIndicator a1 = mock(ReactiveHealthIndicator.class); + CompositeReactiveHealthContributor c1 = CompositeReactiveHealthContributor.fromMap(Map.of("a", a1)); + ReactiveHealthIndicator a2 = mock(ReactiveHealthIndicator.class); + CompositeReactiveHealthContributor c2 = CompositeReactiveHealthContributor.fromMap(Map.of("a", a2)); + ReactiveHealthContributors composite = ReactiveHealthContributors.of(c1, c2); + assertThat(composite.getContributor("a")).isSameAs(a1); + } + + @Test + void getContributorWhenNoneReturnsNull() { + ReactiveHealthIndicator a = mock(ReactiveHealthIndicator.class); + ReactiveHealthContributors composite = ReactiveHealthContributors + .of(CompositeReactiveHealthContributor.fromMap(Map.of("a", a))); + assertThat(composite.getContributor("x")).isNull(); + } + + @Test + void streamStreamsWithoutDuplicates() { + ReactiveHealthIndicator a1 = mock(ReactiveHealthIndicator.class); + CompositeReactiveHealthContributor c1 = CompositeReactiveHealthContributor.fromMap(Map.of("a", a1)); + ReactiveHealthIndicator a2 = mock(ReactiveHealthIndicator.class); + CompositeReactiveHealthContributor c2 = CompositeReactiveHealthContributor.fromMap(Map.of("a", a2)); + ReactiveHealthIndicator b = mock(ReactiveHealthIndicator.class); + CompositeReactiveHealthContributor c3 = CompositeReactiveHealthContributor.fromMap(Map.of("b", b)); + ReactiveHealthContributors composite = ReactiveHealthContributors.of(c1, c2, c3); + assertThat(composite.stream()).containsExactly(new Entry("a", a1), new Entry("b", b)); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapterTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsAdapterTests.java similarity index 58% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapterTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsAdapterTests.java index c6a5257678a..cec65a7c945 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthContributorReactiveAdapterTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsAdapterTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Collections; import java.util.Iterator; @@ -22,33 +22,26 @@ import java.util.Iterator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** - * Tests for {@link CompositeHealthContributorReactiveAdapter}. + * Tests for {@link HealthContributorsAdapter}. * * @author Phillip Webb */ -class CompositeHealthContributorReactiveAdapterTests { - - @Test - void createWhenDelegateIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> new CompositeHealthContributorReactiveAdapter(null)) - .withMessage("'delegate' must not be null"); - } +class HealthContributorsAdapterTests { @Test void iteratorWhenDelegateContainsHealthIndicatorAdaptsDelegate() { HealthIndicator indicator = () -> Health.up().withDetail("spring", "boot").build(); CompositeHealthContributor delegate = CompositeHealthContributor .fromMap(Collections.singletonMap("test", indicator)); - CompositeHealthContributorReactiveAdapter adapter = new CompositeHealthContributorReactiveAdapter(delegate); - Iterator> iterator = adapter.iterator(); + HealthContributorsAdapter adapter = createAdapter(delegate); + Iterator iterator = adapter.iterator(); assertThat(iterator.hasNext()).isTrue(); - NamedContributor adapted = iterator.next(); - assertThat(adapted.getName()).isEqualTo("test"); - assertThat(adapted.getContributor()).isInstanceOf(ReactiveHealthIndicator.class); - Health health = ((ReactiveHealthIndicator) adapted.getContributor()).getHealth(true).block(); + ReactiveHealthContributors.Entry adapted = iterator.next(); + assertThat(adapted.name()).isEqualTo("test"); + assertThat(adapted.contributor()).isInstanceOf(ReactiveHealthIndicator.class); + Health health = ((ReactiveHealthIndicator) adapted.contributor()).health(true).block(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).containsEntry("spring", "boot"); } @@ -60,15 +53,15 @@ class CompositeHealthContributorReactiveAdapterTests { .fromMap(Collections.singletonMap("test1", indicator)); CompositeHealthContributor delegate = CompositeHealthContributor .fromMap(Collections.singletonMap("test2", composite)); - CompositeHealthContributorReactiveAdapter adapter = new CompositeHealthContributorReactiveAdapter(delegate); - Iterator> iterator = adapter.iterator(); + HealthContributorsAdapter adapter = createAdapter(delegate); + Iterator iterator = adapter.iterator(); assertThat(iterator.hasNext()).isTrue(); - NamedContributor adapted = iterator.next(); - assertThat(adapted.getName()).isEqualTo("test2"); - assertThat(adapted.getContributor()).isInstanceOf(CompositeReactiveHealthContributor.class); - ReactiveHealthContributor nested = ((CompositeReactiveHealthContributor) adapted.getContributor()) + ReactiveHealthContributors.Entry adapted = iterator.next(); + assertThat(adapted.name()).isEqualTo("test2"); + assertThat(adapted.contributor()).isInstanceOf(CompositeReactiveHealthContributor.class); + ReactiveHealthContributor nested = ((CompositeReactiveHealthContributor) adapted.contributor()) .getContributor("test1"); - Health health = ((ReactiveHealthIndicator) nested).getHealth(true).block(); + Health health = ((ReactiveHealthIndicator) nested).health(true).block(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).containsEntry("spring", "boot"); } @@ -78,11 +71,15 @@ class CompositeHealthContributorReactiveAdapterTests { HealthIndicator indicator = () -> Health.up().withDetail("spring", "boot").build(); CompositeHealthContributor delegate = CompositeHealthContributor .fromMap(Collections.singletonMap("test", indicator)); - CompositeHealthContributorReactiveAdapter adapter = new CompositeHealthContributorReactiveAdapter(delegate); + HealthContributorsAdapter adapter = createAdapter(delegate); ReactiveHealthContributor adapted = adapter.getContributor("test"); - Health health = ((ReactiveHealthIndicator) adapted).getHealth(true).block(); + Health health = ((ReactiveHealthIndicator) adapted).health(true).block(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).containsEntry("spring", "boot"); } + protected HealthContributorsAdapter createAdapter(CompositeHealthContributor delegate) { + return new CompositeHealthContributorAdapter(delegate); + } + } diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsTests.java new file mode 100644 index 00000000000..c822986d4b9 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthContributorsTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.health.contributor.HealthContributors.Entry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link HealthContributors}. + * + * @author Phillip Webb + */ +class HealthContributorsTests { + + @Test + void iteratorAdaptsStream() { + Entry e1 = new Entry("e1", mock(HealthIndicator.class)); + Entry e2 = new Entry("e2", mock(HealthIndicator.class)); + HealthContributors contributors = new HealthContributors() { + + @Override + public Stream stream() { + return Stream.of(e1, e2); + } + + @Override + public HealthContributor getContributor(String name) { + return null; + } + + }; + assertThat(contributors).containsExactly(e1, e2); + } + + @Test + void createEntryWhenNameIsEmptyThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> new Entry("", mock(HealthIndicator.class))) + .withMessage("'name' must not be empty"); + } + + @Test + void createEntryWhenContributorIsNullThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> new Entry("test", null)) + .withMessage("'contributor' must not be null"); + } + + @Test + void ofCreatesComposite() { + HealthContributors c = mock(HealthContributors.class); + assertThat(HealthContributors.of(c)).isInstanceOf(CompositeHealthContributors.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapterTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorAdapterTests.java similarity index 81% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapterTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorAdapterTests.java index bedaa9f7580..d86c849d28a 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorReactiveAdapterTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorAdapterTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.time.Duration; @@ -25,16 +25,16 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; /** - * Tests for {@link HealthIndicatorReactiveAdapter}. + * Tests for {@link HealthIndicatorAdapter}. * * @author Stephane Nicoll */ -class HealthIndicatorReactiveAdapterTests { +class HealthIndicatorAdapterTests { @Test void delegateReturnsHealth() { HealthIndicator delegate = mock(HealthIndicator.class); - HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate); + HealthIndicatorAdapter adapter = new HealthIndicatorAdapter(delegate); Health status = Health.up().build(); given(delegate.health()).willReturn(status); StepVerifier.create(adapter.health()).expectNext(status).expectComplete().verify(Duration.ofSeconds(30)); @@ -43,7 +43,7 @@ class HealthIndicatorReactiveAdapterTests { @Test void delegateThrowError() { HealthIndicator delegate = mock(HealthIndicator.class); - HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate); + HealthIndicatorAdapter adapter = new HealthIndicatorAdapter(delegate); given(delegate.health()).willThrow(new IllegalStateException("Expected")); StepVerifier.create(adapter.health()).expectError(IllegalStateException.class).verify(Duration.ofSeconds(10)); } @@ -54,7 +54,7 @@ class HealthIndicatorReactiveAdapterTests { HealthIndicator delegate = () -> Health .status(Thread.currentThread().getName().equals(currentThread) ? Status.DOWN : Status.UP) .build(); - HealthIndicatorReactiveAdapter adapter = new HealthIndicatorReactiveAdapter(delegate); + HealthIndicatorAdapter adapter = new HealthIndicatorAdapter(delegate); StepVerifier.create(adapter.health()) .expectNext(Health.status(Status.UP).build()) .expectComplete() diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorTests.java similarity index 89% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorTests.java index 7e874074665..8066f560b42 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import org.junit.jupiter.api.Test; @@ -31,14 +31,14 @@ class HealthIndicatorTests { @Test void getHealthWhenIncludeDetailsIsTrueReturnsHealthWithDetails() { - Health health = this.indicator.getHealth(true); + Health health = this.indicator.health(true); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).containsEntry("spring", "boot"); } @Test void getHealthWhenIncludeDetailsIsFalseReturnsHealthWithoutDetails() { - Health health = this.indicator.getHealth(false); + Health health = this.indicator.health(false); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).isEmpty(); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthTests.java similarity index 99% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthTests.java index 46a7faa9d8a..dfe1f3ffa1e 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/HealthTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Collections; import java.util.LinkedHashMap; diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeHealthContributorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeHealthContributorTests.java new file mode 100644 index 00000000000..93a3f9f850d --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeHealthContributorTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.springframework.boot.health.contributor.HealthContributors.Entry; + +/** + * Tests for {@link MapCompositeHealthContributor}. + * + * @author Phillip Webb + */ +class MapCompositeHealthContributorTests + extends MapCompositeTests { + + @Override + protected CompositeHealthContributor create(Map map, + Function valueAdapter) { + return new MapCompositeHealthContributor<>(map, valueAdapter); + } + + @Override + protected Stream stream(CompositeHealthContributor composite) { + return composite.stream(); + } + + @Override + protected HealthContributor getContributor(CompositeHealthContributor composite, String name) { + return composite.getContributor(name); + } + + @Override + protected HealthContributor createContributor(String data) { + return (HealthIndicator) () -> Health.up().withDetail("data", data).build(); + } + + @Override + protected String getData(HealthContributor contributor) { + return (String) ((HealthIndicator) contributor).health().getDetails().get("data"); + } + + @Override + protected String getName(Entry entry) { + return entry.name(); + } + + @Override + protected HealthContributor getContributor(Entry entry) { + return entry.contributor(); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributorTests.java new file mode 100644 index 00000000000..5f666ecc571 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeReactiveHealthContributorTests.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +import reactor.core.publisher.Mono; + +import org.springframework.boot.health.contributor.ReactiveHealthContributors.Entry; + +/** + * Tests for {@link MapCompositeReactiveHealthContributor}. + * + * @author Phillip Webb + */ +class MapCompositeReactiveHealthContributorTests + extends MapCompositeTests { + + @Override + protected CompositeReactiveHealthContributor create(Map map, + Function valueAdapter) { + return new MapCompositeReactiveHealthContributor<>(map, valueAdapter); + } + + @Override + protected Stream stream(CompositeReactiveHealthContributor composite) { + return composite.stream(); + } + + @Override + protected ReactiveHealthContributor getContributor(CompositeReactiveHealthContributor composite, String name) { + return composite.getContributor(name); + } + + @Override + protected ReactiveHealthContributor createContributor(String data) { + return (ReactiveHealthIndicator) () -> Mono.just(Health.up().withDetail("data", data).build()); + } + + @Override + protected String getData(ReactiveHealthContributor contributor) { + return (String) ((ReactiveHealthIndicator) contributor).health().block().getDetails().get("data"); + } + + @Override + protected String getName(Entry entry) { + return entry.name(); + } + + @Override + protected ReactiveHealthContributor getContributor(Entry entry) { + return entry.contributor(); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapterTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeTests.java similarity index 51% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapterTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeTests.java index ceda9df4888..6ac8442b5fb 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/NamedContributorsMapAdapterTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/MapCompositeTests.java @@ -14,14 +14,15 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Collections; -import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -29,69 +30,67 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** - * Tests for {@link NamedContributorsMapAdapter}. + * Base class for {@link Map} backed composites. * + * @param the composite type + * @param the contributor type + * @param the entry type * @author Phillip Webb * @author Guirong Hu */ -class NamedContributorsMapAdapterTests { +abstract class MapCompositeTests { @Test void createWhenMapIsNullThrowsException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new TestNamedContributorsMapAdapter<>(null, Function.identity())) + assertThatIllegalArgumentException().isThrownBy(() -> createWithData(null, Function.identity())) .withMessage("'map' must not be null"); } @Test void createWhenValueAdapterIsNullThrowsException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new TestNamedContributorsMapAdapter<>(Collections.emptyMap(), null)) + assertThatIllegalArgumentException().isThrownBy(() -> createWithData(Collections.emptyMap(), null)) .withMessage("'valueAdapter' must not be null"); } @Test void createWhenMapContainsNullValueThrowsException() { assertThatIllegalArgumentException() - .isThrownBy(() -> new TestNamedContributorsMapAdapter<>(Collections.singletonMap("test", null), - Function.identity())) + .isThrownBy(() -> createWithData(Collections.singletonMap("test", null), Function.identity())) .withMessage("'map' must not contain null values"); } @Test void createWhenMapContainsNullKeyThrowsException() { assertThatIllegalArgumentException() - .isThrownBy(() -> new TestNamedContributorsMapAdapter<>(Collections.singletonMap(null, "test"), - Function.identity())) + .isThrownBy(() -> createWithData(Collections.singletonMap(null, "test"), Function.identity())) .withMessage("'map' must not contain null keys"); } @Test void createWhenMapContainsKeyWithSlashThrowsException() { assertThatIllegalArgumentException() - .isThrownBy(() -> new TestNamedContributorsMapAdapter<>(Collections.singletonMap("test/key", "test"), - Function.identity())) + .isThrownBy(() -> createWithData(Collections.singletonMap("test/key", "test"), Function.identity())) .withMessage("'map' keys must not contain a '/'"); } @Test - void iterateReturnsAdaptedEntries() { - TestNamedContributorsMapAdapter adapter = createAdapter(); - Iterator> iterator = adapter.iterator(); - NamedContributor one = iterator.next(); - NamedContributor two = iterator.next(); - assertThat(iterator.hasNext()).isFalse(); - assertThat(one.getName()).isEqualTo("one"); - assertThat(one.getContributor()).isEqualTo("eno"); - assertThat(two.getName()).isEqualTo("two"); - assertThat(two.getContributor()).isEqualTo("owt"); + void streamReturnsAdaptedEntries() { + T composite = create(); + List streamed = stream(composite).toList(); + assertThat(streamed).hasSize(2); + E one = streamed.get(0); + E two = streamed.get(1); + assertThat(getName(one)).isEqualTo("one"); + assertThat(getData(getContributor(one))).isEqualTo("eno"); + assertThat(getName(two)).isEqualTo("two"); + assertThat(getData(getContributor(two))).isEqualTo("owt"); } @Test void getContributorReturnsAdaptedEntry() { - TestNamedContributorsMapAdapter adapter = createAdapter(); - assertThat(adapter.getContributor("one")).isEqualTo("eno"); - assertThat(adapter.getContributor("two")).isEqualTo("owt"); + T composite = create(); + assertThat(getContributorData(composite, "one")).isEqualTo("eno"); + assertThat(getContributorData(composite, "two")).isEqualTo("owt"); } @Test @@ -101,26 +100,17 @@ class NamedContributorsMapAdapterTests { map.put("two", "two"); int callCount = map.size(); AtomicInteger counter = new AtomicInteger(0); - TestNamedContributorsMapAdapter adapter = new TestNamedContributorsMapAdapter<>(map, - (name) -> count(name, counter)); - assertThat(adapter.getContributor("one")).isEqualTo("eno"); + T composite = createWithData(map, (name) -> count(name, counter)); + assertThat(getContributorData(composite, "one")).isEqualTo("eno"); assertThat(counter.get()).isEqualTo(callCount); - assertThat(adapter.getContributor("two")).isEqualTo("owt"); + assertThat(getContributorData(composite, "two")).isEqualTo("owt"); assertThat(counter.get()).isEqualTo(callCount); } @Test void getContributorWhenNotInMapReturnsNull() { - TestNamedContributorsMapAdapter adapter = createAdapter(); - assertThat(adapter.getContributor("missing")).isNull(); - } - - private TestNamedContributorsMapAdapter createAdapter() { - Map map = new LinkedHashMap<>(); - map.put("one", "one"); - map.put("two", "two"); - TestNamedContributorsMapAdapter adapter = new TestNamedContributorsMapAdapter<>(map, this::reverse); - return adapter; + T composite = create(); + assertThat(getContributor(composite, "missing")).isNull(); } private String count(CharSequence charSequence, AtomicInteger counter) { @@ -132,12 +122,33 @@ class NamedContributorsMapAdapterTests { return new StringBuilder(charSequence).reverse().toString(); } - static class TestNamedContributorsMapAdapter extends NamedContributorsMapAdapter { - - TestNamedContributorsMapAdapter(Map map, Function valueAdapter) { - super(map, valueAdapter); - } - + private T create() { + Map map = new LinkedHashMap<>(); + map.put("one", "one"); + map.put("two", "two"); + return createWithData(map, this::reverse); } + private T createWithData(Map map, Function dataAdapter) { + return create(map, (dataAdapter != null) ? (key) -> createContributor(dataAdapter.apply(key)) : null); + } + + private String getContributorData(T composite, String name) { + return getData(getContributor(composite, name)); + } + + protected abstract T create(Map map, Function valueAdapter); + + protected abstract Stream stream(T composite); + + protected abstract C getContributor(T composite, String name); + + protected abstract C createContributor(String data); + + protected abstract String getData(C contributor); + + protected abstract String getName(E entry); + + protected abstract C getContributor(E entry); + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/PingHealthIndicatorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/PingHealthIndicatorTests.java similarity index 95% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/PingHealthIndicatorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/PingHealthIndicatorTests.java index e6c57089866..bb9ca60905a 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/PingHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/PingHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import org.junit.jupiter.api.Test; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthContributorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorTests.java similarity index 68% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthContributorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorTests.java index be1227dfea4..6071ca94903 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthContributorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorTests.java @@ -14,35 +14,27 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import java.util.Collections; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.Mockito.mock; /** * Tests for {@link ReactiveHealthContributor}. * * @author Phillip Webb + * @author Stephane Nicoll */ class ReactiveHealthContributorTests { - @Test - void adaptWhenNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> ReactiveHealthContributor.adapt(null)) - .withMessage("'healthContributor' must not be null"); - } - @Test void adaptWhenHealthIndicatorReturnsHealthIndicatorReactiveAdapter() { HealthIndicator indicator = () -> Health.outOfService().build(); ReactiveHealthContributor adapted = ReactiveHealthContributor.adapt(indicator); - assertThat(adapted).isInstanceOf(HealthIndicatorReactiveAdapter.class); + assertThat(adapted).isInstanceOf(HealthIndicatorAdapter.class); assertThat(((ReactiveHealthIndicator) adapted).health().block().getStatus()).isEqualTo(Status.OUT_OF_SERVICE); } @@ -52,16 +44,9 @@ class ReactiveHealthContributorTests { CompositeHealthContributor contributor = CompositeHealthContributor .fromMap(Collections.singletonMap("a", indicator)); ReactiveHealthContributor adapted = ReactiveHealthContributor.adapt(contributor); - assertThat(adapted).isInstanceOf(CompositeHealthContributorReactiveAdapter.class); + assertThat(adapted).isInstanceOf(CompositeHealthContributorAdapter.class); ReactiveHealthContributor contained = ((CompositeReactiveHealthContributor) adapted).getContributor("a"); assertThat(((ReactiveHealthIndicator) contained).health().block().getStatus()).isEqualTo(Status.OUT_OF_SERVICE); } - @Test - void adaptWhenUnknownThrowsException() { - assertThatIllegalStateException() - .isThrownBy(() -> ReactiveHealthContributor.adapt(mock(HealthContributor.class))) - .withMessage("Unknown HealthContributor type"); - } - } diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapterTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapterTests.java new file mode 100644 index 00000000000..f0afe6112b7 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsAdapterTests.java @@ -0,0 +1,80 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.mockito.Answers; + +import org.springframework.boot.health.contributor.HealthContributors.Entry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.withSettings; + +/** + * Tests for {@link ReactiveHealthContributorsAdapter}. + * + * @author Phillip Webb + */ +class ReactiveHealthContributorsAdapterTests { + + @Test + void getContributorWhenNoneReturnsNull() { + ReactiveHealthIndicator a = mock(ReactiveHealthIndicator.class, + withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); + CompositeReactiveHealthContributor delegate = CompositeReactiveHealthContributor.fromMap(Map.of("a", a)); + ReactiveHealthContributorsAdapter adapter = createAdapter(delegate); + assertThat(adapter.getContributor("x")).isNull(); + } + + @Test + void getContributorReturnsAdaptedContributor() { + ReactiveHealthIndicator a = mock(ReactiveHealthIndicator.class, + withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); + CompositeReactiveHealthContributor delegate = CompositeReactiveHealthContributor.fromMap(Map.of("a", a)); + ReactiveHealthContributorsAdapter adapter = createAdapter(delegate); + assertThat(adapter.getContributor("a")).isInstanceOf(ReactiveHealthIndicatorAdapter.class); + assertThat(adapter.getContributor("a")).extracting("delegate").isSameAs(a); + } + + @Test + void streamAdaptsEntries() { + ReactiveHealthIndicator a = mock(ReactiveHealthIndicator.class, + withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); + ReactiveHealthIndicator b = mock(ReactiveHealthIndicator.class, + withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); + Map map = new LinkedHashMap<>(); + map.put("a", a); + map.put("b", b); + CompositeReactiveHealthContributor delegate = CompositeReactiveHealthContributor.fromMap(map); + ReactiveHealthContributorsAdapter adapter = createAdapter(delegate); + assertThat(adapter.stream().map(Entry::name)).containsExactly("a", "b"); + Object[] contributors = adapter.stream().map(Entry::contributor).toArray(); + assertThat(contributors[0]).isInstanceOf(ReactiveHealthIndicatorAdapter.class); + assertThat(contributors[0]).extracting("delegate").isSameAs(a); + assertThat(contributors[1]).isInstanceOf(ReactiveHealthIndicatorAdapter.class); + assertThat(contributors[1]).extracting("delegate").isSameAs(b); + } + + protected ReactiveHealthContributorsAdapter createAdapter(CompositeReactiveHealthContributor delegate) { + return new CompositeReactiveHealthContributorAdapter(delegate); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsTests.java new file mode 100644 index 00000000000..4d4920eb3ad --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthContributorsTests.java @@ -0,0 +1,94 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.mockito.Answers; + +import org.springframework.boot.health.contributor.ReactiveHealthContributors.Entry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.withSettings; + +/** + * Tests for {@link ReactiveHealthContributors}. + * + * @author Phillip Webb + */ +class ReactiveHealthContributorsTests { + + @Test + void iteratorAdaptsStream() { + Entry e1 = new Entry("e1", mock(ReactiveHealthIndicator.class)); + Entry e2 = new Entry("e2", mock(ReactiveHealthIndicator.class)); + ReactiveHealthContributors contributors = new ReactiveHealthContributors() { + + @Override + public Stream stream() { + return Stream.of(e1, e2); + } + + @Override + public ReactiveHealthContributor getContributor(String name) { + return null; + } + + }; + assertThat(contributors).containsExactly(e1, e2); + } + + @Test + void asHealthContributorsReturnsAdapter() { + ReactiveHealthContributors contributors = mock(ReactiveHealthContributors.class, + withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); + assertThat(contributors.asHealthContributors()).isInstanceOf(ReactiveHealthContributorsAdapter.class); + } + + @Test + void ofCreateComposite() { + ReactiveHealthContributors c = mock(ReactiveHealthContributors.class); + assertThat(ReactiveHealthContributors.of(c)).isInstanceOf(CompositeReactiveHealthContributors.class); + } + + @Test + void adaptWhenNullReturnsNull() { + assertThat(ReactiveHealthContributors.adapt(null)).isNull(); + } + + @Test + void adaptReturnsAdapter() { + HealthContributors c = mock(HealthContributors.class); + assertThat(ReactiveHealthContributors.adapt(c)).isInstanceOf(HealthContributorsAdapter.class); + } + + @Test + void createEntryWhenNameIsEmptyThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> new Entry("", mock(ReactiveHealthIndicator.class))) + .withMessage("'name' must not be empty"); + } + + @Test + void createEntryWhenContributorIsNullThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> new Entry("test", null)) + .withMessage("'contributor' must not be null"); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapterTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapterTests.java new file mode 100644 index 00000000000..d9abdb3f59e --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorAdapterTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.contributor; + +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ReactiveHealthIndicatorAdapter}. + * + * @author Phillip Webb + */ +class ReactiveHealthIndicatorAdapterTests { + + @Test + void getHealthReturnsDetails() { + ReactiveHealthIndicator reactiveHealthIndicator = () -> Mono + .just(Health.up().withDetail("test", "test").build()); + ReactiveHealthIndicatorAdapter adapter = new ReactiveHealthIndicatorAdapter(reactiveHealthIndicator); + assertThat(adapter.health().getStatus()).isEqualTo(Status.UP); + assertThat(adapter.health().getDetails()).containsEntry("test", "test"); + } + + @Test + void getHealthWithoutDetailsReturnsHealth() { + ReactiveHealthIndicator reactiveHealthIndicator = () -> Mono + .just(Health.up().withDetail("test", "test").build()); + ReactiveHealthIndicatorAdapter adapter = new ReactiveHealthIndicatorAdapter(reactiveHealthIndicator); + assertThat(adapter.health(false).getStatus()).isEqualTo(Status.UP); + assertThat(adapter.health(false).getDetails()).isEmpty(); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorTests.java similarity index 79% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorTests.java index d81eca0d304..d77a97f9639 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/ReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; @@ -30,16 +30,22 @@ class ReactiveHealthIndicatorTests { private final ReactiveHealthIndicator indicator = () -> Mono.just(Health.up().withDetail("spring", "boot").build()); + @Test + void asHealthContributor() { + HealthIndicator adapted = this.indicator.asHealthContributor(); + assertThat(adapted.health(true).getDetails()).containsEntry("spring", "boot"); + } + @Test void getHealthWhenIncludeDetailsIsTrueReturnsHealthWithDetails() { - Health health = this.indicator.getHealth(true).block(); + Health health = this.indicator.health(true).block(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).containsEntry("spring", "boot"); } @Test void getHealthWhenIncludeDetailsIsFalseReturnsHealthWithoutDetails() { - Health health = this.indicator.getHealth(false).block(); + Health health = this.indicator.health(false).block(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).isEmpty(); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/StatusTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/StatusTests.java similarity index 97% rename from spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/StatusTests.java rename to spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/StatusTests.java index 8fb7f770f1d..92ba26c4a22 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/StatusTests.java +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/contributor/StatusTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.health; +package org.springframework.boot.health.contributor; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/AbstractHealthContributorRegistryTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/AbstractHealthContributorRegistryTests.java new file mode 100644 index 00000000000..354de559b94 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/AbstractHealthContributorRegistryTests.java @@ -0,0 +1,158 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.util.Assert; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; + +/** + * Tests for {@link AbstractRegistry}. + * + * @param the contributor type + * @param the entry type + * @author Phillip Webb + * @author Vedran Pavic + * @author Stephane Nicoll + */ +abstract class AbstractHealthContributorRegistryTests { + + private AbstractRegistry registry; + + @BeforeEach + void setUp() { + this.registry = createRegistry(Collections.emptyList(), null); + } + + @Test + void registerContributorWhenNameIsNullThrowsException() { + assertThatIllegalArgumentException() + .isThrownBy(() -> this.registry.registerContributor(null, mockHealthIndicator())) + .withMessage("'name' must not be empty"); + } + + @Test + void registerContributorWhenContributorIsNullThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> this.registry.registerContributor("one", null)) + .withMessage("'contributor' must not be null"); + } + + @Test + void registerContributorRegistersContributors() { + C c1 = mockHealthIndicator(); + C c2 = mockHealthIndicator(); + this.registry.registerContributor("one", c1); + this.registry.registerContributor("two", c2); + assertThat((Iterable) this.registry).hasSize(2); + assertThat(this.registry.getContributor("one")).isSameAs(c1); + assertThat(this.registry.getContributor("two")).isSameAs(c2); + } + + @Test + void registerContributorWhenNameAlreadyUsedThrowsException() { + this.registry.registerContributor("one", mockHealthIndicator()); + assertThatIllegalStateException() + .isThrownBy(() -> this.registry.registerContributor("one", mockHealthIndicator())) + .withMessageContaining("A contributor named \"one\" has already been registered"); + } + + @Test + void unregisterContributorUnregistersContributor() { + C c1 = mockHealthIndicator(); + C c2 = mockHealthIndicator(); + this.registry.registerContributor("one", c1); + this.registry.registerContributor("two", c2); + assertThat((Iterable) this.registry).hasSize(2); + C two = this.registry.unregisterContributor("two"); + assertThat(two).isSameAs(c2); + assertThat((Iterable) this.registry).hasSize(1); + } + + @Test + void unregisterContributorWhenUnknownReturnsNull() { + this.registry.registerContributor("one", mockHealthIndicator()); + assertThat((Iterable) this.registry).hasSize(1); + Object two = this.registry.unregisterContributor("two"); + assertThat(two).isNull(); + assertThat((Iterable) this.registry).hasSize(1); + } + + @Test + void getContributorReturnsContributor() { + C c1 = mockHealthIndicator(); + this.registry.registerContributor("one", c1); + assertThat(this.registry.getContributor("one")).isEqualTo(c1); + } + + @Test + void streamStreamsContributors() { + C c1 = mockHealthIndicator(); + C c2 = mockHealthIndicator(); + this.registry.registerContributor("one", c1); + this.registry.registerContributor("two", c2); + List streamed = this.registry.stream().toList(); + assertThat(streamed).hasSize(2); + E first = streamed.get(0); + E second = streamed.get(1); + assertThat(name(first)).isEqualTo("one"); + assertThat(contributor(first)).isEqualTo(c1); + assertThat(name(second)).isEqualTo("two"); + assertThat(contributor(second)).isEqualTo(c2); + } + + @Test + void nameValidatorsValidateMapKeys() { + assertThatIllegalStateException().isThrownBy(() -> createRegistry(testValidator(), (intialRegistrations) -> { + intialRegistrations.accept("ok", mockHealthIndicator()); + intialRegistrations.accept("fail", mockHealthIndicator()); + })).withMessage("Failed validation"); + } + + @Test + void nameValidatorsValidateRegisteredName() { + AbstractRegistry registry = createRegistry(testValidator(), null); + registry.registerContributor("ok", mockHealthIndicator()); + assertThatIllegalStateException().isThrownBy(() -> registry.registerContributor("fail", mockHealthIndicator())) + .withMessage("Failed validation"); + } + + private List testValidator() { + return List.of((name) -> Assert.state(!"fail".equals(name), "Failed validation")); + } + + protected abstract AbstractRegistry createRegistry( + Collection nameValidators, + Consumer> intialRegistrations); + + protected abstract C mockHealthIndicator(); + + protected abstract String name(E entry); + + protected abstract C contributor(E entry); + +} diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistryTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistryTests.java new file mode 100644 index 00000000000..1c253c3b369 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultHealthContributorRegistryTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import java.util.Collection; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; +import org.springframework.boot.health.contributor.HealthContributors.Entry; +import org.springframework.boot.health.contributor.HealthIndicator; + +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link DefaultHealthContributorRegistry}. + * + * @author Phillip Webb + */ +class DefaultHealthContributorRegistryTests + extends AbstractHealthContributorRegistryTests { + + @Override + protected AbstractRegistry createRegistry( + Collection nameValidators, + Consumer> intialRegistrations) { + return new DefaultHealthContributorRegistry(nameValidators, intialRegistrations); + } + + @Override + protected HealthContributor mockHealthIndicator() { + return mock(HealthIndicator.class); + } + + @Override + protected String name(Entry entry) { + return entry.name(); + } + + @Override + protected HealthContributor contributor(Entry entry) { + return entry.contributor(); + } + +} diff --git a/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistryTests.java b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistryTests.java new file mode 100644 index 00000000000..3d8e442bae7 --- /dev/null +++ b/spring-boot-project/spring-boot-health/src/test/java/org/springframework/boot/health/registry/DefaultReactiveHealthContributorRegistryTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.health.registry; + +import java.util.Collection; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributors; +import org.springframework.boot.health.contributor.ReactiveHealthContributors.Entry; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; + +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link DefaultReactiveHealthContributorRegistry}. + * + * @author Phillip Webb + */ +class DefaultReactiveHealthContributorRegistryTests + extends AbstractHealthContributorRegistryTests { + + @Override + protected AbstractRegistry createRegistry( + Collection nameValidators, + Consumer> intialRegistrations) { + return new DefaultReactiveHealthContributorRegistry(nameValidators, intialRegistrations); + } + + @Override + protected ReactiveHealthContributor mockHealthIndicator() { + return mock(ReactiveHealthIndicator.class); + } + + @Override + protected String name(Entry entry) { + return entry.name(); + } + + @Override + protected ReactiveHealthContributor contributor(Entry entry) { + return entry.contributor(); + } + +} diff --git a/spring-boot-project/spring-boot-jdbc/build.gradle b/spring-boot-project/spring-boot-jdbc/build.gradle index e54c6f8b502..37f4b1ceb3e 100644 --- a/spring-boot-project/spring-boot-jdbc/build.gradle +++ b/spring-boot-project/spring-boot-jdbc/build.gradle @@ -35,9 +35,9 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-tx")) - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("com.h2database:h2") diff --git a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfiguration.java index 86cc8115428..77d4645ad95 100644 --- a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfiguration.java @@ -18,11 +18,11 @@ package org.springframework.boot.jdbc.autoconfigure.health; import java.sql.SQLException; import java.util.Collection; -import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.sql.DataSource; @@ -30,18 +30,18 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.SimpleAutowireCandidateResolver; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.NamedContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.jdbc.actuate.health.DataSourceHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; +import org.springframework.boot.jdbc.health.DataSourceHealthIndicator; import org.springframework.boot.jdbc.metadata.CompositeDataSourcePoolMetadataProvider; import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadata; import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider; @@ -171,8 +171,8 @@ public class DataSourceHealthContributorAutoConfiguration implements Initializin } @Override - public Iterator> iterator() { - return this.delegate.iterator(); + public Stream stream() { + return this.delegate.stream(); } } diff --git a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthIndicatorProperties.java b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthIndicatorProperties.java index fb71816f55f..2626bde5c69 100644 --- a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthIndicatorProperties.java +++ b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthIndicatorProperties.java @@ -17,7 +17,7 @@ package org.springframework.boot.jdbc.autoconfigure.health; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.jdbc.actuate.health.DataSourceHealthIndicator; +import org.springframework.boot.jdbc.health.DataSourceHealthIndicator; /** * External configuration properties for {@link DataSourceHealthIndicator}. diff --git a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/actuate/health/DataSourceHealthIndicator.java b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/health/DataSourceHealthIndicator.java similarity index 94% rename from spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/actuate/health/DataSourceHealthIndicator.java rename to spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/health/DataSourceHealthIndicator.java index 89868fa5d19..855f7a3d93c 100644 --- a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/actuate/health/DataSourceHealthIndicator.java +++ b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/health/DataSourceHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.jdbc.actuate.health; +package org.springframework.boot.jdbc.health; import java.sql.Connection; import java.sql.ResultSet; @@ -25,10 +25,10 @@ import java.util.List; import javax.sql.DataSource; import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.dao.support.DataAccessUtils; import org.springframework.jdbc.IncorrectResultSetColumnCountException; import org.springframework.jdbc.core.ConnectionCallback; diff --git a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/actuate/health/package-info.java b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/actuate/health/package-info.java rename to spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/health/package-info.java index 0ace3c2fa21..8b08ab049fa 100644 --- a/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for JDBC. */ -package org.springframework.boot.jdbc.actuate.health; +package org.springframework.boot.jdbc.health; diff --git a/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfigurationTests.java index 1495923d61e..77866e1aa29 100644 --- a/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/autoconfigure/health/DataSourceHealthContributorAutoConfigurationTests.java @@ -29,18 +29,18 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.NamedContributor; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.boot.jdbc.actuate.health.DataSourceHealthIndicator; import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; import org.springframework.boot.jdbc.autoconfigure.DataSourcePoolMetadataProvidersConfiguration; import org.springframework.boot.jdbc.autoconfigure.EmbeddedDataSourceConfiguration; import org.springframework.boot.jdbc.autoconfigure.health.DataSourceHealthContributorAutoConfiguration.RoutingDataSourceHealthContributor; +import org.springframework.boot.jdbc.health.DataSourceHealthIndicator; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -80,7 +80,7 @@ class DataSourceHealthContributorAutoConfigurationTests { .run((context) -> { assertThat(context).hasSingleBean(CompositeHealthContributor.class); CompositeHealthContributor contributor = context.getBean(CompositeHealthContributor.class); - String[] names = contributor.stream().map(NamedContributor::getName).toArray(String[]::new); + String[] names = contributor.stream().map(HealthContributors.Entry::name).toArray(String[]::new); assertThat(names).containsExactlyInAnyOrder("dataSource", "standardDataSource", "nonDefaultDataSource"); }); } diff --git a/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/actuate/health/DataSourceHealthIndicatorTests.java b/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/health/DataSourceHealthIndicatorTests.java similarity index 96% rename from spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/actuate/health/DataSourceHealthIndicatorTests.java rename to spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/health/DataSourceHealthIndicatorTests.java index 8b8e1ff25b1..55645092e6e 100644 --- a/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/actuate/health/DataSourceHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-jdbc/src/test/java/org/springframework/boot/jdbc/health/DataSourceHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.jdbc.actuate.health; +package org.springframework.boot.jdbc.health; import java.sql.Connection; import java.sql.SQLException; @@ -25,8 +25,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.jdbc.EmbeddedDatabaseConnection; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SingleConnectionDataSource; diff --git a/spring-boot-project/spring-boot-jersey/build.gradle b/spring-boot-project/spring-boot-jersey/build.gradle index d218a4c7d9a..23bd9539647 100644 --- a/spring-boot-project/spring-boot-jersey/build.gradle +++ b/spring-boot-project/spring-boot-jersey/build.gradle @@ -39,6 +39,7 @@ dependencies { optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-jackson")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-observation")) diff --git a/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/endpoint/web/HealthEndpointJerseyExtensionAutoConfigurationTests.java b/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/endpoint/web/HealthEndpointJerseyExtensionAutoConfigurationTests.java index b00132146b0..04794f9e1cc 100644 --- a/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/endpoint/web/HealthEndpointJerseyExtensionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/endpoint/web/HealthEndpointJerseyExtensionAutoConfigurationTests.java @@ -22,15 +22,16 @@ import reactor.core.publisher.Mono; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.WithTestEndpointOutcomeExposureContributor; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; -import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointWebExtension; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; import org.springframework.boot.jersey.autoconfigure.actuate.endpoint.web.HealthEndpointJerseyExtensionAutoConfiguration.JerseyAdditionalHealthEndpointPathsResourcesRegistrar; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.context.annotation.Bean; @@ -48,7 +49,8 @@ class HealthEndpointJerseyExtensionAutoConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withUserConfiguration(HealthIndicatorsConfiguration.class) .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, HealthEndpointJerseyExtensionAutoConfiguration.class)); + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + HealthEndpointJerseyExtensionAutoConfiguration.class)); @Test @WithTestEndpointOutcomeExposureContributor diff --git a/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/web/JerseyHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/web/JerseyHealthEndpointAdditionalPathIntegrationTests.java index 4c9667a1e7f..9065b14b947 100644 --- a/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/web/JerseyHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-jersey/src/test/java/org/springframework/boot/jersey/autoconfigure/actuate/web/JerseyHealthEndpointAdditionalPathIntegrationTests.java @@ -23,6 +23,7 @@ import org.springframework.boot.actuate.autoconfigure.integrationtest.AbstractHe import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.jersey.autoconfigure.JerseyAutoConfiguration; import org.springframework.boot.jersey.autoconfigure.actuate.endpoint.web.HealthEndpointJerseyExtensionAutoConfiguration; @@ -50,6 +51,7 @@ class JerseyHealthEndpointAdditionalPathIntegrationTests extends TomcatServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, JerseyAutoConfiguration.class, ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HealthEndpointJerseyExtensionAutoConfiguration.class, DiskSpaceHealthContributorAutoConfiguration.class)) .withInitializer(new ServerPortInfoApplicationContextInitializer()) diff --git a/spring-boot-project/spring-boot-jms/build.gradle b/spring-boot-project/spring-boot-jms/build.gradle index de5949604a2..20fa0e3eb94 100644 --- a/spring-boot-project/spring-boot-jms/build.gradle +++ b/spring-boot-project/spring-boot-jms/build.gradle @@ -33,8 +33,8 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional("jakarta.transaction:jakarta.transaction-api") optional("org.messaginghub:pooled-jms") { exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec" diff --git a/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfiguration.java index 10eabcb005a..e4392d8d8b9 100644 --- a/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.jms.autoconfigure.health; import jakarta.jms.ConnectionFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.jms.actuate.health.JmsHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.boot.jms.autoconfigure.JmsAutoConfiguration; +import org.springframework.boot.jms.health.JmsHealthIndicator; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/actuate/health/JmsHealthIndicator.java b/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/health/JmsHealthIndicator.java similarity index 90% rename from spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/actuate/health/JmsHealthIndicator.java rename to spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/health/JmsHealthIndicator.java index d42933fda3d..ac3681de69b 100644 --- a/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/actuate/health/JmsHealthIndicator.java +++ b/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/health/JmsHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.jms.actuate.health; +package org.springframework.boot.jms.health; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -25,9 +25,9 @@ import jakarta.jms.JMSException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; /** * {@link HealthIndicator} for a JMS {@link ConnectionFactory}. diff --git a/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/actuate/health/package-info.java b/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/actuate/health/package-info.java rename to spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/health/package-info.java index f66fb1275e2..9ce57fb93ad 100644 --- a/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-jms/src/main/java/org/springframework/boot/jms/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for JMS. */ -package org.springframework.boot.jms.actuate.health; +package org.springframework.boot.jms.health; diff --git a/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfigurationTests.java index f47c9701e84..43795bff614 100644 --- a/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/autoconfigure/health/JmsHealthContributorAutoConfigurationTests.java @@ -19,9 +19,9 @@ package org.springframework.boot.jms.autoconfigure.health; import jakarta.jms.ConnectionFactory; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.jms.actuate.health.JmsHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.jms.health.JmsHealthIndicator; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/actuate/health/JmsHealthIndicatorTests.java b/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/health/JmsHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/actuate/health/JmsHealthIndicatorTests.java rename to spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/health/JmsHealthIndicatorTests.java index c5e143776f3..c454945b5df 100644 --- a/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/actuate/health/JmsHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-jms/src/test/java/org/springframework/boot/jms/health/JmsHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.jms.actuate.health; +package org.springframework.boot.jms.health; import jakarta.jms.Connection; import jakarta.jms.ConnectionFactory; @@ -24,8 +24,8 @@ import org.junit.jupiter.api.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; diff --git a/spring-boot-project/spring-boot-ldap/build.gradle b/spring-boot-project/spring-boot-ldap/build.gradle index 97fa1cdc0d2..03929388a60 100644 --- a/spring-boot-project/spring-boot-ldap/build.gradle +++ b/spring-boot-project/spring-boot-ldap/build.gradle @@ -32,9 +32,9 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("com.unboundid:unboundid-ldapsdk") optional("org.testcontainers:ldap") diff --git a/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfiguration.java index 231f23f96dd..8b5a3668545 100644 --- a/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfiguration.java @@ -17,16 +17,16 @@ package org.springframework.boot.ldap.autoconfigure.health; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.ldap.actuate.health.LdapHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.boot.ldap.autoconfigure.LdapAutoConfiguration; +import org.springframework.boot.ldap.health.LdapHealthIndicator; import org.springframework.context.annotation.Bean; import org.springframework.ldap.core.LdapOperations; diff --git a/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/actuate/health/LdapHealthIndicator.java b/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/health/LdapHealthIndicator.java similarity index 88% rename from spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/actuate/health/LdapHealthIndicator.java rename to spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/health/LdapHealthIndicator.java index 45a34742d6d..6865b5814a9 100644 --- a/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/actuate/health/LdapHealthIndicator.java +++ b/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/health/LdapHealthIndicator.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.ldap.actuate.health; +package org.springframework.boot.ldap.health; import javax.naming.NamingException; import javax.naming.directory.DirContext; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.ldap.core.ContextExecutor; import org.springframework.ldap.core.LdapOperations; import org.springframework.util.Assert; diff --git a/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/actuate/health/package-info.java b/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/actuate/health/package-info.java rename to spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/health/package-info.java index ce895f20fc8..427c1cc0874 100644 --- a/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for LDAP. */ -package org.springframework.boot.ldap.actuate.health; +package org.springframework.boot.ldap.health; diff --git a/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfigurationTests.java index d3882385877..1d0dbce7e7f 100644 --- a/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/health/LdapHealthContributorAutoConfigurationTests.java @@ -18,9 +18,9 @@ package org.springframework.boot.ldap.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.ldap.actuate.health.LdapHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.ldap.health.LdapHealthIndicator; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.ldap.core.LdapOperations; diff --git a/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/actuate/health/LdapHealthIndicatorTests.java b/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/health/LdapHealthIndicatorTests.java similarity index 93% rename from spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/actuate/health/LdapHealthIndicatorTests.java rename to spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/health/LdapHealthIndicatorTests.java index 7737530d105..eef8eb4fa2a 100644 --- a/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/actuate/health/LdapHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/health/LdapHealthIndicatorTests.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.springframework.boot.ldap.actuate.health; +package org.springframework.boot.ldap.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.ldap.CommunicationException; import org.springframework.ldap.core.ContextExecutor; import org.springframework.ldap.core.LdapTemplate; diff --git a/spring-boot-project/spring-boot-mail/build.gradle b/spring-boot-project/spring-boot-mail/build.gradle index cac453cb1bc..cfd8d94df3b 100644 --- a/spring-boot-project/spring-boot-mail/build.gradle +++ b/spring-boot-project/spring-boot-mail/build.gradle @@ -33,8 +33,8 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) dockerTestImplementation(project(":spring-boot-project:spring-boot-test")) dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker")) diff --git a/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfiguration.java index d01b21cd6d0..a9d98c9d430 100644 --- a/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfiguration.java @@ -17,15 +17,15 @@ package org.springframework.boot.mail.autoconfigure; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.mail.actuate.health.MailHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.mail.health.MailHealthIndicator; import org.springframework.context.annotation.Bean; import org.springframework.mail.javamail.JavaMailSenderImpl; diff --git a/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/actuate/health/MailHealthIndicator.java b/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/health/MailHealthIndicator.java similarity index 82% rename from spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/actuate/health/MailHealthIndicator.java rename to spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/health/MailHealthIndicator.java index f8b76e4e755..113fdb09628 100644 --- a/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/actuate/health/MailHealthIndicator.java +++ b/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/health/MailHealthIndicator.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.springframework.boot.mail.actuate.health; +package org.springframework.boot.mail.health; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.util.StringUtils; @@ -39,7 +39,7 @@ public class MailHealthIndicator extends AbstractHealthIndicator { } @Override - protected void doHealthCheck(Builder builder) throws Exception { + protected void doHealthCheck(Health.Builder builder) throws Exception { String host = this.mailSender.getHost(); int port = this.mailSender.getPort(); StringBuilder location = new StringBuilder((host != null) ? host : ""); diff --git a/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/actuate/health/package-info.java b/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/actuate/health/package-info.java rename to spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/health/package-info.java index 49fa2c94d03..0a6a389998f 100644 --- a/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-mail/src/main/java/org/springframework/boot/mail/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for JavaMail. */ -package org.springframework.boot.mail.actuate.health; +package org.springframework.boot.mail.health; diff --git a/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfigurationTests.java index c42bc182dd5..8be34675166 100644 --- a/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/autoconfigure/MailHealthContributorAutoConfigurationTests.java @@ -18,9 +18,9 @@ package org.springframework.boot.mail.autoconfigure; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.mail.actuate.health.MailHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.mail.health.MailHealthIndicator; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/actuate/health/MailHealthIndicatorTests.java b/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/health/MailHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/actuate/health/MailHealthIndicatorTests.java rename to spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/health/MailHealthIndicatorTests.java index 782c4843932..3f6320efaf0 100644 --- a/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/actuate/health/MailHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-mail/src/test/java/org/springframework/boot/mail/health/MailHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.mail.actuate.health; +package org.springframework.boot.mail.health; import java.util.Properties; @@ -29,8 +29,8 @@ import jakarta.mail.URLName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.mail.javamail.JavaMailSenderImpl; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-neo4j/build.gradle b/spring-boot-project/spring-boot-neo4j/build.gradle index 57d0f4931fc..e6c9cfdefa3 100644 --- a/spring-boot-project/spring-boot-neo4j/build.gradle +++ b/spring-boot-project/spring-boot-neo4j/build.gradle @@ -32,9 +32,9 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-testcontainers")) optional("org.testcontainers:neo4j") diff --git a/spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorIntegrationTests.java b/spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/neo4/health/Neo4jReactiveHealthIndicatorIntegrationTests.java similarity index 88% rename from spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorIntegrationTests.java rename to spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/neo4/health/Neo4jReactiveHealthIndicatorIntegrationTests.java index 096db0978c2..13c2ad70230 100644 --- a/spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorIntegrationTests.java +++ b/spring-boot-project/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/neo4/health/Neo4jReactiveHealthIndicatorIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.neo4j; +package org.springframework.boot.neo4.health; import java.time.Duration; @@ -24,11 +24,11 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.neo4j.actuate.health.Neo4jReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.neo4j.autoconfigure.Neo4jAutoConfiguration; +import org.springframework.boot.neo4j.health.Neo4jReactiveHealthIndicator; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.testsupport.container.TestImage; import org.springframework.context.annotation.Configuration; @@ -64,7 +64,7 @@ class Neo4jReactiveHealthIndicatorIntegrationTests { @Test void health() { - Health health = this.healthIndicator.getHealth(true).block(Duration.ofSeconds(20)); + Health health = this.healthIndicator.health(true).block(Duration.ofSeconds(20)); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails()).containsEntry("edition", "community"); } diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfiguration.java index 1820bfc3676..fa6768b2435 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfiguration.java @@ -18,16 +18,16 @@ package org.springframework.boot.neo4j.autoconfigure.health; import org.neo4j.driver.Driver; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.neo4j.actuate.health.Neo4jHealthIndicator; -import org.springframework.boot.neo4j.actuate.health.Neo4jReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.neo4j.autoconfigure.Neo4jAutoConfiguration; import org.springframework.boot.neo4j.autoconfigure.health.Neo4jHealthContributorConfigurations.Neo4jConfiguration; import org.springframework.boot.neo4j.autoconfigure.health.Neo4jHealthContributorConfigurations.Neo4jReactiveConfiguration; +import org.springframework.boot.neo4j.health.Neo4jHealthIndicator; +import org.springframework.boot.neo4j.health.Neo4jReactiveHealthIndicator; import org.springframework.context.annotation.Import; /** diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorConfigurations.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorConfigurations.java index f340ac05fd6..0b5f2ad8f3c 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorConfigurations.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorConfigurations.java @@ -20,14 +20,14 @@ import org.neo4j.driver.Driver; import reactor.core.publisher.Flux; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.neo4j.actuate.health.Neo4jHealthIndicator; -import org.springframework.boot.neo4j.actuate.health.Neo4jReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; +import org.springframework.boot.neo4j.health.Neo4jHealthIndicator; +import org.springframework.boot.neo4j.health.Neo4jReactiveHealthIndicator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthDetails.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthDetails.java similarity index 95% rename from spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthDetails.java rename to spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthDetails.java index 614841f5856..ce43f5c838d 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthDetails.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthDetails.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import org.neo4j.driver.Record; import org.neo4j.driver.summary.ResultSummary; diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthDetailsHandler.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthDetailsHandler.java similarity index 86% rename from spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthDetailsHandler.java rename to spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthDetailsHandler.java index ae040925f9a..2b4211caed8 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthDetailsHandler.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthDetailsHandler.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import org.neo4j.driver.summary.DatabaseInfo; import org.neo4j.driver.summary.ResultSummary; import org.neo4j.driver.summary.ServerInfo; -import org.springframework.boot.actuate.health.Health.Builder; +import org.springframework.boot.health.contributor.Health; import org.springframework.util.StringUtils; /** @@ -32,10 +32,10 @@ class Neo4jHealthDetailsHandler { /** * Add health details for the specified {@link ResultSummary} and {@code edition}. - * @param builder the {@link Builder} to use + * @param builder the builder to use * @param healthDetails the health details of the server */ - void addHealthDetails(Builder builder, Neo4jHealthDetails healthDetails) { + void addHealthDetails(Health.Builder builder, Neo4jHealthDetails healthDetails) { ResultSummary summary = healthDetails.getSummary(); ServerInfo serverInfo = summary.server(); builder.up() diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthIndicator.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthIndicator.java similarity index 92% rename from spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthIndicator.java rename to spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthIndicator.java index 90ea64c6508..2bc69c79a3d 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthIndicator.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -27,9 +27,9 @@ import org.neo4j.driver.SessionConfig; import org.neo4j.driver.exceptions.SessionExpiredException; import org.neo4j.driver.summary.ResultSummary; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; /** * {@link HealthIndicator} that tests the status of a Neo4j by executing a Cypher diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jReactiveHealthIndicator.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jReactiveHealthIndicator.java similarity index 92% rename from spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jReactiveHealthIndicator.java rename to spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jReactiveHealthIndicator.java index 7fd930e6e0a..ca23f586137 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/Neo4jReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/Neo4jReactiveHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -28,9 +28,9 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.retry.Retry; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; /** * {@link ReactiveHealthIndicator} that tests the status of a Neo4j by executing a Cypher diff --git a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/package-info.java b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/package-info.java rename to spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/package-info.java index a6930ad867e..de96196cf62 100644 --- a/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for Neo4j. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; diff --git a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfigurationTests.java index bbbec1b6e8f..d4da6993f1a 100644 --- a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/autoconfigure/health/Neo4jHealthContributorAutoConfigurationTests.java @@ -20,13 +20,13 @@ import org.junit.jupiter.api.Test; import org.neo4j.driver.Driver; import reactor.core.publisher.Flux; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.neo4j.actuate.health.Neo4jHealthIndicator; -import org.springframework.boot.neo4j.actuate.health.Neo4jReactiveHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.neo4j.health.Neo4jHealthIndicator; +import org.springframework.boot.neo4j.health.Neo4jReactiveHealthIndicator; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthIndicatorTests.java b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/Neo4jHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthIndicatorTests.java rename to spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/Neo4jHealthIndicatorTests.java index a5dc8d854a0..109334cc2e5 100644 --- a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/Neo4jHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/Neo4jHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import java.util.concurrent.atomic.AtomicInteger; @@ -29,8 +29,8 @@ import org.neo4j.driver.exceptions.ServiceUnavailableException; import org.neo4j.driver.exceptions.SessionExpiredException; import org.neo4j.driver.summary.ResultSummary; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; diff --git a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/Neo4jReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/Neo4jReactiveHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/Neo4jReactiveHealthIndicatorTests.java rename to spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/Neo4jReactiveHealthIndicatorTests.java index fd4ae715e25..f593c7b0b95 100644 --- a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/Neo4jReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/Neo4jReactiveHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; @@ -33,7 +33,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; diff --git a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/ResultSummaryMock.java b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/ResultSummaryMock.java similarity index 96% rename from spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/ResultSummaryMock.java rename to spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/ResultSummaryMock.java index 87bb6c56051..758b3934836 100644 --- a/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/actuate/health/ResultSummaryMock.java +++ b/spring-boot-project/spring-boot-neo4j/src/test/java/org/springframework/boot/neo4j/health/ResultSummaryMock.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.neo4j.actuate.health; +package org.springframework.boot.neo4j.health; import org.neo4j.driver.summary.DatabaseInfo; import org.neo4j.driver.summary.ResultSummary; diff --git a/spring-boot-project/spring-boot-r2dbc/build.gradle b/spring-boot-project/spring-boot-r2dbc/build.gradle index 66db70f778f..e86ba797431 100644 --- a/spring-boot-project/spring-boot-r2dbc/build.gradle +++ b/spring-boot-project/spring-boot-r2dbc/build.gradle @@ -36,9 +36,9 @@ dependencies { compileOnly("com.fasterxml.jackson.core:jackson-annotations") - optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) optional(project(":spring-boot-project:spring-boot-docker-compose")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-jdbc")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-observation")) diff --git a/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfiguration.java b/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfiguration.java index a238f316bc1..613f81e58c9 100644 --- a/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfiguration.java @@ -19,16 +19,16 @@ package org.springframework.boot.r2dbc.autoconfigure.health; import io.r2dbc.spi.ConnectionFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.r2dbc.actuate.health.ConnectionFactoryHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration; +import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthContributor; import org.springframework.boot.r2dbc.autoconfigure.R2dbcAutoConfiguration; +import org.springframework.boot.r2dbc.health.ConnectionFactoryHealthIndicator; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/actuate/health/ConnectionFactoryHealthIndicator.java b/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/health/ConnectionFactoryHealthIndicator.java similarity index 85% rename from spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/actuate/health/ConnectionFactoryHealthIndicator.java rename to spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/health/ConnectionFactoryHealthIndicator.java index 2bed4bd3e2c..dd79f908cc7 100644 --- a/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/actuate/health/ConnectionFactoryHealthIndicator.java +++ b/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/health/ConnectionFactoryHealthIndicator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.r2dbc.actuate.health; +package org.springframework.boot.r2dbc.health; import io.r2dbc.spi.Connection; import io.r2dbc.spi.ConnectionFactory; @@ -24,11 +24,10 @@ import io.r2dbc.spi.ValidationDepth; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -69,18 +68,18 @@ public class ConnectionFactoryHealthIndicator extends AbstractReactiveHealthIndi } @Override - protected final Mono doHealthCheck(Builder builder) { + protected final Mono doHealthCheck(Health.Builder builder) { return validate(builder).defaultIfEmpty(builder.build()) .onErrorResume(Exception.class, (ex) -> Mono.just(builder.down(ex).build())); } - private Mono validate(Builder builder) { + private Mono validate(Health.Builder builder) { builder.withDetail("database", this.connectionFactory.getMetadata().getName()); return (StringUtils.hasText(this.validationQuery)) ? validateWithQuery(builder) : validateWithConnectionValidation(builder); } - private Mono validateWithQuery(Builder builder) { + private Mono validateWithQuery(Health.Builder builder) { builder.withDetail("validationQuery", this.validationQuery); Mono connectionValidation = Mono.usingWhen(this.connectionFactory.create(), (conn) -> Flux.from(conn.createStatement(this.validationQuery).execute()) @@ -90,7 +89,7 @@ public class ConnectionFactoryHealthIndicator extends AbstractReactiveHealthIndi return connectionValidation.map((result) -> builder.up().withDetail("result", result).build()); } - private Mono validateWithConnectionValidation(Builder builder) { + private Mono validateWithConnectionValidation(Health.Builder builder) { builder.withDetail("validationQuery", "validate(REMOTE)"); Mono connectionValidation = Mono.usingWhen(this.connectionFactory.create(), (connection) -> Mono.from(connection.validate(ValidationDepth.REMOTE)), Connection::close, diff --git a/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/actuate/health/package-info.java b/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/health/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/actuate/health/package-info.java rename to spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/health/package-info.java index 55548dd8b4e..ab2aa272f2e 100644 --- a/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/actuate/health/package-info.java +++ b/spring-boot-project/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/health/package-info.java @@ -17,4 +17,4 @@ /** * Health integration for R2DBC. */ -package org.springframework.boot.r2dbc.actuate.health; +package org.springframework.boot.r2dbc.health; diff --git a/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfigurationTests.java b/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfigurationTests.java index 1c7bd2a2219..8ef67dda4b3 100644 --- a/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/autoconfigure/health/ConnectionFactoryHealthContributorAutoConfigurationTests.java @@ -18,10 +18,10 @@ package org.springframework.boot.r2dbc.autoconfigure.health; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.r2dbc.actuate.health.ConnectionFactoryHealthIndicator; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.r2dbc.autoconfigure.R2dbcAutoConfiguration; +import org.springframework.boot.r2dbc.health.ConnectionFactoryHealthIndicator; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/actuate/health/ConnectionFactoryHealthIndicatorTests.java b/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/health/ConnectionFactoryHealthIndicatorTests.java similarity index 97% rename from spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/actuate/health/ConnectionFactoryHealthIndicatorTests.java rename to spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/health/ConnectionFactoryHealthIndicatorTests.java index 37efe647b77..e345acffc82 100644 --- a/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/actuate/health/ConnectionFactoryHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-r2dbc/src/test/java/org/springframework/boot/r2dbc/health/ConnectionFactoryHealthIndicatorTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.r2dbc.actuate.health; +package org.springframework.boot.r2dbc.health; import java.time.Duration; import java.util.Collections; @@ -32,8 +32,8 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; +import org.springframework.boot.health.contributor.Status; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; diff --git a/spring-boot-project/spring-boot-security/build.gradle b/spring-boot-project/spring-boot-security/build.gradle index ac9281a3789..8bfe469eeb1 100644 --- a/spring-boot-project/spring-boot-security/build.gradle +++ b/spring-boot-project/spring-boot-security/build.gradle @@ -54,6 +54,7 @@ dependencies { optional("org.springframework.security:spring-security-messaging") optional("org.springframework.security:spring-security-rsocket") + testImplementation(project(":spring-boot-project:spring-boot-health")) testImplementation(project(":spring-boot-project:spring-boot-hibernate")) testImplementation(project(":spring-boot-project:spring-boot-http-converter")) testImplementation(project(":spring-boot-project:spring-boot-jackson")) diff --git a/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/reactive/ReactiveManagementWebSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/reactive/ReactiveManagementWebSecurityAutoConfigurationTests.java index 5a640e803a9..003424471a3 100644 --- a/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/reactive/ReactiveManagementWebSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/reactive/ReactiveManagementWebSecurityAutoConfigurationTests.java @@ -27,10 +27,11 @@ import reactor.core.publisher.Mono; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.security.autoconfigure.reactive.ReactiveSecurityAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; @@ -67,10 +68,11 @@ class ReactiveManagementWebSecurityAutoConfigurationTests { private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class, - WebFluxAutoConfiguration.class, EnvironmentEndpointAutoConfiguration.class, - EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - ReactiveSecurityAutoConfiguration.class, ReactiveManagementWebSecurityAutoConfiguration.class)); + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + InfoEndpointAutoConfiguration.class, WebFluxAutoConfiguration.class, + EnvironmentEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, + WebEndpointAutoConfiguration.class, ReactiveSecurityAutoConfiguration.class, + ReactiveManagementWebSecurityAutoConfiguration.class)); @Test void permitAllForHealth() { diff --git a/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/servlet/ManagementWebSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/servlet/ManagementWebSecurityAutoConfigurationTests.java index 8115a346a58..804b6decad9 100644 --- a/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/servlet/ManagementWebSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/servlet/ManagementWebSecurityAutoConfigurationTests.java @@ -25,10 +25,11 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.security.autoconfigure.SecurityProperties; import org.springframework.boot.security.autoconfigure.servlet.SecurityAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; @@ -69,10 +70,10 @@ class ManagementWebSecurityAutoConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner(contextSupplier(), WebServerApplicationContext.class) .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class, - EnvironmentEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, - WebMvcAutoConfiguration.class, WebEndpointAutoConfiguration.class, SecurityAutoConfiguration.class, - ManagementWebSecurityAutoConfiguration.class)); + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + InfoEndpointAutoConfiguration.class, EnvironmentEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class, WebMvcAutoConfiguration.class, WebEndpointAutoConfiguration.class, + SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class)); private static Supplier contextSupplier() { return WebApplicationContextRunner.withMockServletContext(MockWebServerApplicationContext::new); diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-actuator/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-actuator/build.gradle index 9f7a16076ef..19ed5e74e4f 100644 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-actuator/build.gradle +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-actuator/build.gradle @@ -22,6 +22,7 @@ description = "Starter for using Spring Boot's Actuator which provides productio dependencies { api(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) + api(project(":spring-boot-project:spring-boot-health")) api(project(":spring-boot-project:spring-boot-metrics")) api(project(":spring-boot-project:spring-boot-tracing")) api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter")) diff --git a/spring-boot-project/spring-boot-webflux/build.gradle b/spring-boot-project/spring-boot-webflux/build.gradle index 982842f0830..c478672e735 100644 --- a/spring-boot-project/spring-boot-webflux/build.gradle +++ b/spring-boot-project/spring-boot-webflux/build.gradle @@ -35,6 +35,7 @@ dependencies { optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-observation")) optional(project(":spring-boot-project:spring-boot-validation")) diff --git a/spring-boot-project/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfiguration.java b/spring-boot-project/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfiguration.java index cc81127d4ff..6e3d185a547 100644 --- a/spring-boot-project/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfiguration.java +++ b/spring-boot-project/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfiguration.java @@ -28,9 +28,11 @@ import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointGroups; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.health.contributor.Health; import org.springframework.boot.webflux.actuate.endpoint.web.AdditionalHealthEndpointPathsWebFluxHandlerMapping; import org.springframework.context.annotation.Bean; @@ -43,7 +45,8 @@ import org.springframework.context.annotation.Bean; */ @AutoConfiguration @ConditionalOnWebApplication(type = Type.REACTIVE) -@ConditionalOnClass(HealthEndpoint.class) +@ConditionalOnClass({ HealthEndpoint.class, Health.class }) +@ConditionalOnBean({ WebEndpointsSupplier.class, HealthEndpointGroups.class }) @ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB) public class WebFluxHealthEndpointExtensionAutoConfiguration { diff --git a/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointAdditionalPathIntegrationTests.java index 6f254499da7..a9619abcd14 100644 --- a/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointAdditionalPathIntegrationTests.java @@ -24,6 +24,8 @@ import org.springframework.boot.actuate.autoconfigure.integrationtest.AbstractHe import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.http.codec.autoconfigure.CodecsAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.reactor.netty.autoconfigure.NettyReactiveWebServerAutoConfiguration; @@ -47,8 +49,10 @@ class WebFluxHealthEndpointAdditionalPathIntegrationTests extends WebFluxHealthEndpointAdditionalPathIntegrationTests() { super(new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class, - WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, WebFluxHealthEndpointExtensionAutoConfiguration.class, + WebFluxAutoConfiguration.class, HealthContributorAutoConfiguration.class, + HealthContributorRegistryAutoConfiguration.class, HttpHandlerAutoConfiguration.class, + EndpointAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + WebFluxHealthEndpointExtensionAutoConfiguration.class, DiskSpaceHealthContributorAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, NettyReactiveWebServerAutoConfiguration.class, NettyReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class)) diff --git a/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfigurationTests.java b/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfigurationTests.java index 757e842fc2f..c694920340b 100644 --- a/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/actuate/endpoint/web/WebFluxHealthEndpointExtensionAutoConfigurationTests.java @@ -22,15 +22,16 @@ import reactor.core.publisher.Mono; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.WithTestEndpointOutcomeExposureContributor; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; -import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthEndpoint; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; +import org.springframework.boot.health.contributor.ReactiveHealthIndicator; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.webflux.actuate.endpoint.web.AdditionalHealthEndpointPathsWebFluxHandlerMapping; import org.springframework.context.annotation.Bean; @@ -48,7 +49,8 @@ class WebFluxHealthEndpointExtensionAutoConfigurationTests { private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() .withUserConfiguration(HealthIndicatorsConfiguration.class) .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, WebFluxHealthEndpointExtensionAutoConfiguration.class)); + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + WebFluxHealthEndpointExtensionAutoConfiguration.class)); @Test @WithTestEndpointOutcomeExposureContributor @@ -67,6 +69,16 @@ class WebFluxHealthEndpointExtensionAutoConfigurationTests { }); } + @Test + @WithTestEndpointOutcomeExposureContributor + void backsOffWithoutWebEndpointInfrastructure() { + this.contextRunner.withConfiguration(AutoConfigurations.of(EndpointAutoConfiguration.class)) + .withPropertyValues("management.endpoints.web.exposure.exclude=*", + "management.endpoints.test.exposure.include=*") + .run((context) -> assertThat(context) + .doesNotHaveBean(AdditionalHealthEndpointPathsWebFluxHandlerMapping.class)); + } + @Configuration(proxyBeanMethods = false) static class HealthIndicatorsConfiguration { diff --git a/spring-boot-project/spring-boot-webmvc/build.gradle b/spring-boot-project/spring-boot-webmvc/build.gradle index 8fe35d19f33..7682416597a 100644 --- a/spring-boot-project/spring-boot-webmvc/build.gradle +++ b/spring-boot-project/spring-boot-webmvc/build.gradle @@ -37,6 +37,7 @@ dependencies { optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure")) optional(project(":spring-boot-project:spring-boot-autoconfigure")) + optional(project(":spring-boot-project:spring-boot-health")) optional(project(":spring-boot-project:spring-boot-metrics")) optional(project(":spring-boot-project:spring-boot-observation")) optional(project(":spring-boot-project:spring-boot-tomcat")) diff --git a/spring-boot-project/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointExtensionAutoConfiguration.java b/spring-boot-project/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointExtensionAutoConfiguration.java index 44c2bbb7ba6..414675e458e 100644 --- a/spring-boot-project/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointExtensionAutoConfiguration.java +++ b/spring-boot-project/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointExtensionAutoConfiguration.java @@ -44,7 +44,7 @@ import org.springframework.context.annotation.Bean; @AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(HealthEndpoint.class) -@ConditionalOnBean(HealthEndpoint.class) +@ConditionalOnBean({ HealthEndpoint.class, WebEndpointsSupplier.class, HealthEndpointGroups.class }) @ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB) public class WebMvcHealthEndpointExtensionAutoConfiguration { diff --git a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/actuate/autoconfigure/health/WebMvcHealthEndpointExtensionAutoConfigurationTests.java b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/actuate/autoconfigure/health/WebMvcHealthEndpointExtensionAutoConfigurationTests.java index d9002bf3084..0ea35498751 100644 --- a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/actuate/autoconfigure/health/WebMvcHealthEndpointExtensionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/actuate/autoconfigure/health/WebMvcHealthEndpointExtensionAutoConfigurationTests.java @@ -21,14 +21,15 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.WithTestEndpointOutcomeExposureContributor; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; -import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.health.HealthEndpointWebExtension; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.webmvc.actuate.endpoint.web.AdditionalHealthEndpointPathsWebMvcHandlerMapping; import org.springframework.boot.webmvc.autoconfigure.actuate.endpoint.web.WebMvcHealthEndpointExtensionAutoConfiguration; @@ -47,7 +48,8 @@ class WebMvcHealthEndpointExtensionAutoConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, WebMvcHealthEndpointExtensionAutoConfiguration.class)); + HealthContributorRegistryAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + WebMvcHealthEndpointExtensionAutoConfiguration.class)); @Test @WithTestEndpointOutcomeExposureContributor @@ -67,6 +69,17 @@ class WebMvcHealthEndpointExtensionAutoConfigurationTests { }); } + @Test + @WithTestEndpointOutcomeExposureContributor + void backsOffWithoutWebEndpointInfrastructure() { + this.contextRunner.withConfiguration(AutoConfigurations.of(EndpointAutoConfiguration.class)) + .withBean(DispatcherServlet.class) + .withPropertyValues("management.endpoints.web.exposure.exclude=*", + "management.endpoints.test.exposure.include=*") + .run((context) -> assertThat(context) + .doesNotHaveBean(AdditionalHealthEndpointPathsWebMvcHandlerMapping.class)); + } + @Configuration(proxyBeanMethods = false) static class HealthIndicatorsConfiguration { diff --git a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointAdditionalPathIntegrationTests.java index 57205d24bc6..8b1bfc9a43e 100644 --- a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/endpoint/web/WebMvcHealthEndpointAdditionalPathIntegrationTests.java @@ -23,6 +23,8 @@ import org.springframework.boot.actuate.autoconfigure.integrationtest.AbstractHe import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.servlet.autoconfigure.actuate.web.ServletManagementContextAutoConfiguration; @@ -47,6 +49,7 @@ class WebMvcHealthEndpointAdditionalPathIntegrationTests extends WebMvcHealthEndpointAdditionalPathIntegrationTests() { super(new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, + HealthContributorAutoConfiguration.class, HealthContributorRegistryAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, ManagementContextAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, TomcatServletManagementContextAutoConfiguration.class, WebMvcAutoConfiguration.class, diff --git a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointAccessIntegrationTests.java b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointAccessIntegrationTests.java index fdb57cff006..90cf0083c99 100644 --- a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointAccessIntegrationTests.java +++ b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointAccessIntegrationTests.java @@ -28,9 +28,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.servlet.autoconfigure.actuate.web.ServletManagementContextAutoConfiguration; diff --git a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointExposureIntegrationTests.java b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointExposureIntegrationTests.java index 99a2894a01f..5d75151e109 100644 --- a/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointExposureIntegrationTests.java +++ b/spring-boot-project/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/actuate/web/WebMvcEndpointExposureIntegrationTests.java @@ -30,11 +30,12 @@ import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoCon import org.springframework.boot.actuate.autoconfigure.context.ShutdownEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.actuate.web.exchanges.InMemoryHttpExchangeRepository; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.registry.HealthContributorRegistryAutoConfiguration; import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration; import org.springframework.boot.servlet.autoconfigure.actuate.ServletHttpExchangesAutoConfiguration; @@ -72,8 +73,9 @@ class WebMvcEndpointExposureIntegrationTests { WebMvcAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, ServletHttpExchangesAutoConfiguration.class, - HealthContributorAutoConfiguration.class, BeansEndpointAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, ShutdownEndpointAutoConfiguration.class)) + HealthContributorAutoConfiguration.class, HealthContributorRegistryAutoConfiguration.class, + BeansEndpointAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + ShutdownEndpointAutoConfiguration.class)) .withUserConfiguration(CustomMvcEndpoint.class, CustomServletEndpoint.class, HttpExchangeRepositoryConfiguration.class, AuditEventRepositoryConfiguration.class) .withPropertyValues("server.port:0"); diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/ExampleHealthIndicator.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/ExampleHealthIndicator.java index f3a69a4841a..484e94dee2e 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/ExampleHealthIndicator.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/ExampleHealthIndicator.java @@ -16,8 +16,8 @@ package smoketest.actuator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/SampleActuatorApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/SampleActuatorApplication.java index 0b2d890f3b4..d73e846752b 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/SampleActuatorApplication.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/main/java/smoketest/actuator/SampleActuatorApplication.java @@ -20,13 +20,13 @@ import java.util.LinkedHashMap; import java.util.Map; import org.springframework.boot.SpringApplication; -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthIndicator; import org.springframework.context.annotation.Bean; @SpringBootApplication