diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicator.java index ee6fffc0e33..a284cd502e4 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicator.java @@ -28,6 +28,7 @@ import org.springframework.util.Assert; * * @author Dmytro Nosan * @author Stephane Nicoll + * @author Tommy Karlsson * @since 2.2.0 */ public class HazelcastHealthIndicator extends AbstractHealthIndicator { @@ -42,6 +43,10 @@ public class HazelcastHealthIndicator extends AbstractHealthIndicator { @Override protected void doHealthCheck(Health.Builder builder) { + if (!this.hazelcast.getLifecycleService().isRunning()) { + builder.down(); + return; + } this.hazelcast.executeTransaction((context) -> { String uuid = this.hazelcast.getLocalEndpoint().getUuid().toString(); builder.up().withDetail("name", this.hazelcast.getName()).withDetail("uuid", uuid); diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicatorTests.java index e41e0cd09f4..74042e2173e 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicatorTests.java @@ -18,6 +18,7 @@ package org.springframework.boot.actuate.hazelcast; import com.hazelcast.core.HazelcastException; import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.LifecycleService; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.health.Health; @@ -30,6 +31,7 @@ import org.springframework.boot.testsupport.classpath.resources.WithResource; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; /** @@ -37,25 +39,26 @@ import static org.mockito.Mockito.mock; * * @author Dmytro Nosan * @author Stephane Nicoll + * @author Tommy Karlsson */ +@WithResource(name = "hazelcast.xml", content = """ + + actuator-hazelcast + + + + + + + + + """) class HazelcastHealthIndicatorTests { @Test - @WithResource(name = "hazelcast.xml", content = """ - - actuator-hazelcast - - - - - - - - - """) void hazelcastUp() { new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class)) .withPropertyValues("spring.hazelcast.config=hazelcast.xml") @@ -69,12 +72,44 @@ class HazelcastHealthIndicatorTests { }); } + @Test + void hazelcastShutdown() { + new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class)) + .withPropertyValues("spring.hazelcast.config=hazelcast.xml") + .run((context) -> { + HazelcastInstance hazelcast = context.getBean(HazelcastInstance.class); + hazelcast.shutdown(); + Health health = new HazelcastHealthIndicator(hazelcast).health(); + assertThat(health.getStatus()).isEqualTo(Status.DOWN); + }); + } + + @Test + void hazelcastLifecycleNotRunning() { + HazelcastInstance hazelcast = mockHazelcastInstance(false); + Health health = new HazelcastHealthIndicator(hazelcast).health(); + assertThat(health.getStatus()).isEqualTo(Status.DOWN); + then(hazelcast).should().getLifecycleService(); + then(hazelcast).shouldHaveNoMoreInteractions(); + } + @Test void hazelcastDown() { - HazelcastInstance hazelcast = mock(HazelcastInstance.class); + HazelcastInstance hazelcast = mockHazelcastInstance(true); given(hazelcast.executeTransaction(any())).willThrow(new HazelcastException()); Health health = new HazelcastHealthIndicator(hazelcast).health(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); + then(hazelcast).should().getLifecycleService(); + then(hazelcast).should().executeTransaction(any()); + then(hazelcast).shouldHaveNoMoreInteractions(); + } + + private static HazelcastInstance mockHazelcastInstance(boolean isRunning) { + LifecycleService lifecycleService = mock(LifecycleService.class); + given(lifecycleService.isRunning()).willReturn(isRunning); + HazelcastInstance hazelcastInstance = mock(HazelcastInstance.class); + given(hazelcastInstance.getLifecycleService()).willReturn(lifecycleService); + return hazelcastInstance; } }