Skip to content

Commit 776cd08

Browse files
committed
Merge pull request #20887 from adutra
* pr/20887: Polish "Add health indicator for Cassandra that uses the CqlSession" Add health indicator for Cassandra that uses the CqlSession Closes gh-20887
2 parents 78a9cdc + 35e069e commit 776cd08

File tree

12 files changed

+494
-73
lines changed

12 files changed

+494
-73
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ dependencies {
3131

3232
optional(platform(project(":spring-boot-project:spring-boot-dependencies")))
3333
optional("ch.qos.logback:logback-classic")
34+
optional("com.datastax.oss:java-driver-core")
3435
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
3536
optional("com.github.ben-manes.caffeine:caffeine")
3637
optional("com.hazelcast:hazelcast")

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cassandra/CassandraHealthContributorAutoConfiguration.java

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,19 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.cassandra;
1818

19-
import java.util.Map;
20-
2119
import com.datastax.oss.driver.api.core.CqlSession;
2220

23-
import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration;
21+
import org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorConfigurations.CassandraDriverConfiguration;
22+
import org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorConfigurations.CassandraOperationsConfiguration;
2423
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
2524
import org.springframework.boot.actuate.cassandra.CassandraHealthIndicator;
26-
import org.springframework.boot.actuate.health.HealthContributor;
2725
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2826
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2927
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
30-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3128
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
32-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3329
import org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration;
34-
import org.springframework.context.annotation.Bean;
3530
import org.springframework.context.annotation.Configuration;
36-
import org.springframework.data.cassandra.core.CassandraOperations;
31+
import org.springframework.context.annotation.Import;
3732

3833
/**
3934
* {@link EnableAutoConfiguration Auto-configuration} for
@@ -44,18 +39,11 @@
4439
* @since 2.1.0
4540
*/
4641
@Configuration(proxyBeanMethods = false)
47-
@ConditionalOnClass({ CqlSession.class, CassandraOperations.class })
48-
@ConditionalOnBean(CassandraOperations.class)
42+
@ConditionalOnClass(CqlSession.class)
4943
@ConditionalOnEnabledHealthIndicator("cassandra")
5044
@AutoConfigureAfter({ CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
5145
CassandraReactiveHealthContributorAutoConfiguration.class })
52-
public class CassandraHealthContributorAutoConfiguration
53-
extends CompositeHealthContributorConfiguration<CassandraHealthIndicator, CassandraOperations> {
54-
55-
@Bean
56-
@ConditionalOnMissingBean(name = { "cassandraHealthIndicator", "cassandraHealthContributor" })
57-
public HealthContributor cassandraHealthContributor(Map<String, CassandraOperations> cassandraOperations) {
58-
return createContributor(cassandraOperations);
59-
}
46+
@Import({ CassandraOperationsConfiguration.class, CassandraDriverConfiguration.class })
47+
public class CassandraHealthContributorAutoConfiguration {
6048

6149
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.cassandra;
18+
19+
import java.util.Map;
20+
21+
import com.datastax.oss.driver.api.core.CqlSession;
22+
23+
import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration;
24+
import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration;
25+
import org.springframework.boot.actuate.cassandra.CassandraDriverHealthIndicator;
26+
import org.springframework.boot.actuate.cassandra.CassandraDriverReactiveHealthIndicator;
27+
import org.springframework.boot.actuate.cassandra.CassandraHealthIndicator;
28+
import org.springframework.boot.actuate.cassandra.CassandraReactiveHealthIndicator;
29+
import org.springframework.boot.actuate.health.HealthContributor;
30+
import org.springframework.boot.actuate.health.ReactiveHealthContributor;
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
32+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
33+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
34+
import org.springframework.context.annotation.Bean;
35+
import org.springframework.context.annotation.Configuration;
36+
import org.springframework.data.cassandra.core.CassandraOperations;
37+
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
38+
39+
/**
40+
* Health contributor options for Cassandra.
41+
*
42+
* @author Stephane Nicoll
43+
*/
44+
class CassandraHealthContributorConfigurations {
45+
46+
@Configuration(proxyBeanMethods = false)
47+
@ConditionalOnBean(CqlSession.class)
48+
static class CassandraDriverConfiguration
49+
extends CompositeHealthContributorConfiguration<CassandraDriverHealthIndicator, CqlSession> {
50+
51+
@Bean
52+
@ConditionalOnMissingBean(name = { "cassandraHealthIndicator", "cassandraHealthContributor" })
53+
HealthContributor cassandraHealthContributor(Map<String, CqlSession> sessions) {
54+
return createContributor(sessions);
55+
}
56+
57+
}
58+
59+
@Configuration(proxyBeanMethods = false)
60+
@ConditionalOnClass(CassandraOperations.class)
61+
@ConditionalOnBean(CassandraOperations.class)
62+
static class CassandraOperationsConfiguration
63+
extends CompositeHealthContributorConfiguration<CassandraHealthIndicator, CassandraOperations> {
64+
65+
@Bean
66+
@ConditionalOnMissingBean(name = { "cassandraHealthIndicator", "cassandraHealthContributor" })
67+
HealthContributor cassandraHealthContributor(Map<String, CassandraOperations> cassandraOperations) {
68+
return createContributor(cassandraOperations);
69+
}
70+
71+
}
72+
73+
@Configuration(proxyBeanMethods = false)
74+
@ConditionalOnBean(CqlSession.class)
75+
static class CassandraReactiveDriverConfiguration extends
76+
CompositeReactiveHealthContributorConfiguration<CassandraDriverReactiveHealthIndicator, CqlSession> {
77+
78+
@Bean
79+
@ConditionalOnMissingBean(name = { "cassandraHealthIndicator", "cassandraHealthContributor" })
80+
ReactiveHealthContributor cassandraHealthContributor(Map<String, CqlSession> sessions) {
81+
return createContributor(sessions);
82+
}
83+
84+
}
85+
86+
@Configuration(proxyBeanMethods = false)
87+
@ConditionalOnClass(ReactiveCassandraOperations.class)
88+
@ConditionalOnBean(ReactiveCassandraOperations.class)
89+
static class CassandraReactiveOperationsConfiguration extends
90+
CompositeReactiveHealthContributorConfiguration<CassandraReactiveHealthIndicator, ReactiveCassandraOperations> {
91+
92+
@Bean
93+
@ConditionalOnMissingBean(name = { "cassandraHealthIndicator", "cassandraHealthContributor" })
94+
ReactiveHealthContributor cassandraHealthContributor(
95+
Map<String, ReactiveCassandraOperations> reactiveCassandraOperations) {
96+
return createContributor(reactiveCassandraOperations);
97+
}
98+
99+
}
100+
101+
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cassandra/CassandraReactiveHealthContributorAutoConfiguration.java

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,19 @@
1515
*/
1616
package org.springframework.boot.actuate.autoconfigure.cassandra;
1717

18-
import java.util.Map;
19-
2018
import com.datastax.oss.driver.api.core.CqlSession;
2119
import reactor.core.publisher.Flux;
2220

23-
import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthContributorConfiguration;
21+
import org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorConfigurations.CassandraReactiveDriverConfiguration;
22+
import org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorConfigurations.CassandraReactiveOperationsConfiguration;
2423
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
2524
import org.springframework.boot.actuate.cassandra.CassandraReactiveHealthIndicator;
26-
import org.springframework.boot.actuate.health.ReactiveHealthContributor;
2725
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2826
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
29-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3027
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
31-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3228
import org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration;
33-
import org.springframework.context.annotation.Bean;
3429
import org.springframework.context.annotation.Configuration;
35-
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
30+
import org.springframework.context.annotation.Import;
3631

3732
/**
3833
* {@link EnableAutoConfiguration Auto-configuration} for
@@ -43,18 +38,10 @@
4338
* @since 2.1.0
4439
*/
4540
@Configuration(proxyBeanMethods = false)
46-
@ConditionalOnClass({ CqlSession.class, ReactiveCassandraOperations.class, Flux.class })
47-
@ConditionalOnBean(ReactiveCassandraOperations.class)
41+
@ConditionalOnClass({ CqlSession.class, Flux.class })
4842
@ConditionalOnEnabledHealthIndicator("cassandra")
4943
@AutoConfigureAfter(CassandraReactiveDataAutoConfiguration.class)
50-
public class CassandraReactiveHealthContributorAutoConfiguration extends
51-
CompositeReactiveHealthContributorConfiguration<CassandraReactiveHealthIndicator, ReactiveCassandraOperations> {
52-
53-
@Bean
54-
@ConditionalOnMissingBean(name = { "cassandraHealthIndicator", "cassandraHealthContributor" })
55-
public ReactiveHealthContributor cassandraHealthContributor(
56-
Map<String, ReactiveCassandraOperations> reactiveCassandraOperations) {
57-
return createContributor(reactiveCassandraOperations);
58-
}
44+
@Import({ CassandraReactiveOperationsConfiguration.class, CassandraReactiveDriverConfiguration.class })
45+
public class CassandraReactiveHealthContributorAutoConfiguration {
5946

6047
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cassandra/CassandraHealthContributorAutoConfigurationTests.java

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.cassandra;
1818

19+
import com.datastax.oss.driver.api.core.CqlSession;
1920
import org.junit.jupiter.api.Test;
2021

2122
import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration;
23+
import org.springframework.boot.actuate.cassandra.CassandraDriverHealthIndicator;
2224
import org.springframework.boot.actuate.cassandra.CassandraHealthIndicator;
2325
import org.springframework.boot.autoconfigure.AutoConfigurations;
24-
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
26+
import org.springframework.boot.test.context.FilteredClassLoader;
2527
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
26-
import org.springframework.context.annotation.Bean;
27-
import org.springframework.context.annotation.Configuration;
2828
import org.springframework.data.cassandra.core.CassandraOperations;
2929

3030
import static org.assertj.core.api.Assertions.assertThat;
@@ -34,33 +34,50 @@
3434
* Tests for {@link CassandraHealthContributorAutoConfiguration}.
3535
*
3636
* @author Phillip Webb
37+
* @author Stephane Nicoll
3738
*/
3839
class CassandraHealthContributorAutoConfigurationTests {
3940

40-
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
41-
.withConfiguration(AutoConfigurations.of(CassandraConfiguration.class,
42-
CassandraHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
41+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
42+
.withConfiguration(AutoConfigurations.of(CassandraHealthContributorAutoConfiguration.class,
43+
HealthContributorAutoConfiguration.class));
4344

4445
@Test
45-
void runShouldCreateIndicator() {
46-
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraHealthIndicator.class));
46+
void runWithoutCqlSessionOrCassandraOperationsShouldNotCreateIndicator() {
47+
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
48+
.doesNotHaveBean(CassandraHealthIndicator.class).doesNotHaveBean(CassandraDriverHealthIndicator.class));
4749
}
4850

4951
@Test
50-
void runWhenDisabledShouldNotCreateIndicator() {
51-
this.contextRunner.withPropertyValues("management.health.cassandra.enabled:false")
52-
.run((context) -> assertThat(context).doesNotHaveBean(CassandraHealthIndicator.class));
52+
void runWithCassandraOperationsShouldCreateRegularIndicator() {
53+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
54+
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
55+
.run((context) -> assertThat(context).hasSingleBean(CassandraHealthIndicator.class)
56+
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
5357
}
5458

55-
@Configuration(proxyBeanMethods = false)
56-
@AutoConfigureBefore(CassandraHealthContributorAutoConfiguration.class)
57-
static class CassandraConfiguration {
59+
@Test
60+
void runWithCqlSessionOnlyShouldCreateDriverIndicator() {
61+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class)).run((context) -> assertThat(context)
62+
.hasSingleBean(CassandraDriverHealthIndicator.class).doesNotHaveBean(CassandraHealthIndicator.class));
63+
}
5864

59-
@Bean
60-
CassandraOperations cassandraOperations() {
61-
return mock(CassandraOperations.class);
62-
}
65+
@Test
66+
void runWithCqlSessionAndSpringDataAbsentShouldCreateDriverIndicator() {
67+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
68+
.withClassLoader(new FilteredClassLoader("org.springframework.data"))
69+
.run((context) -> assertThat(context).hasSingleBean(CassandraDriverHealthIndicator.class)
70+
.doesNotHaveBean(CassandraHealthIndicator.class));
71+
}
6372

73+
@Test
74+
void runWhenDisabledShouldNotCreateIndicator() {
75+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
76+
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
77+
.withPropertyValues("management.health.cassandra.enabled:false")
78+
.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
79+
.doesNotHaveBean(CassandraHealthIndicator.class)
80+
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
6481
}
6582

6683
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cassandra/CassandraReactiveHealthContributorAutoConfigurationTests.java

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.cassandra;
1818

19+
import com.datastax.oss.driver.api.core.CqlSession;
1920
import org.junit.jupiter.api.Test;
2021

21-
import org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorAutoConfigurationTests.CassandraConfiguration;
2222
import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration;
23+
import org.springframework.boot.actuate.cassandra.CassandraDriverHealthIndicator;
24+
import org.springframework.boot.actuate.cassandra.CassandraDriverReactiveHealthIndicator;
2325
import org.springframework.boot.actuate.cassandra.CassandraHealthIndicator;
2426
import org.springframework.boot.actuate.cassandra.CassandraReactiveHealthIndicator;
2527
import org.springframework.boot.autoconfigure.AutoConfigurations;
28+
import org.springframework.boot.test.context.FilteredClassLoader;
2629
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
30+
import org.springframework.data.cassandra.core.CassandraOperations;
2731
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
2832

2933
import static org.assertj.core.api.Assertions.assertThat;
@@ -37,31 +41,53 @@
3741
*/
3842
class CassandraReactiveHealthContributorAutoConfigurationTests {
3943

40-
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
41-
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
44+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
4245
.withConfiguration(AutoConfigurations.of(CassandraReactiveHealthContributorAutoConfiguration.class,
43-
HealthContributorAutoConfiguration.class));
46+
CassandraHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
4447

4548
@Test
46-
void runShouldCreateIndicator() {
47-
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraReactiveHealthIndicator.class)
48-
.hasBean("cassandraHealthContributor"));
49+
void runWithoutCqlSessionOrReactiveCassandraOperationsShouldNotCreateIndicator() {
50+
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
51+
.doesNotHaveBean(CassandraReactiveHealthIndicator.class)
52+
.doesNotHaveBean(CassandraDriverReactiveHealthIndicator.class));
4953
}
5054

5155
@Test
52-
void runWithRegularIndicatorShouldOnlyCreateReactiveIndicator() {
53-
this.contextRunner
54-
.withConfiguration(AutoConfigurations.of(CassandraConfiguration.class,
55-
CassandraHealthContributorAutoConfiguration.class))
56-
.run((context) -> assertThat(context).hasSingleBean(CassandraReactiveHealthIndicator.class)
57-
.hasBean("cassandraHealthContributor").doesNotHaveBean(CassandraHealthIndicator.class));
56+
void runWithReactiveCassandraOperationsShouldOnlyCreateReactiveIndicator() {
57+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
58+
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
59+
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
60+
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
61+
.hasSingleBean(CassandraReactiveHealthIndicator.class)
62+
.doesNotHaveBean(CassandraDriverReactiveHealthIndicator.class)
63+
.doesNotHaveBean(CassandraHealthIndicator.class)
64+
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
65+
}
66+
67+
@Test
68+
void runWithCqlSessionShouldCreateDriverIndicator() {
69+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
70+
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
71+
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class)
72+
.doesNotHaveBean(CassandraReactiveHealthIndicator.class));
73+
}
74+
75+
@Test
76+
void runWithCqlSessionAndSpringDataAbsentShouldACreateDriverIndicator() {
77+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
78+
.withClassLoader(new FilteredClassLoader("org.springframework.data"))
79+
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
80+
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class)
81+
.doesNotHaveBean(CassandraReactiveHealthIndicator.class));
5882
}
5983

6084
@Test
6185
void runWhenDisabledShouldNotCreateIndicator() {
62-
this.contextRunner.withPropertyValues("management.health.cassandra.enabled:false")
63-
.run((context) -> assertThat(context).doesNotHaveBean(CassandraReactiveHealthIndicator.class)
64-
.doesNotHaveBean("cassandraHealthContributor"));
86+
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
87+
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
88+
.withPropertyValues("management.health.cassandra.enabled:false")
89+
.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
90+
.doesNotHaveBean(CassandraReactiveHealthIndicator.class));
6591
}
6692

6793
}

spring-boot-project/spring-boot-actuator/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies {
1313
api(project(":spring-boot-project:spring-boot"))
1414

1515
optional(platform(project(":spring-boot-project:spring-boot-dependencies")))
16+
optional("com.datastax.oss:java-driver-core")
1617
optional("com.fasterxml.jackson.core:jackson-databind")
1718
optional("com.github.ben-manes.caffeine:caffeine")
1819
optional("com.hazelcast:hazelcast")

0 commit comments

Comments
 (0)