Merge pull request #46877 from tommyk-gears

* pr/46877:
  Polish contribution
  Improve Hazelcast health indicator to check that Hazelcast is running

Closes gh-46877
This commit is contained in:
Stéphane Nicoll 2025-08-19 16:35:15 +02:00
commit e1db00b411
2 changed files with 56 additions and 16 deletions

View File

@ -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);

View File

@ -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 = """
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/config
http://www.hazelcast.com/schema/config/hazelcast-config-5.0.xsd">
<instance-name>actuator-hazelcast</instance-name>
<map name="defaultCache" />
<network>
<join>
<auto-detection enabled="false"/>
<multicast enabled="false"/>
</join>
</network>
</hazelcast>
""")
class HazelcastHealthIndicatorTests {
@Test
@WithResource(name = "hazelcast.xml", content = """
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/config
http://www.hazelcast.com/schema/config/hazelcast-config-5.0.xsd">
<instance-name>actuator-hazelcast</instance-name>
<map name="defaultCache" />
<network>
<join>
<auto-detection enabled="false"/>
<multicast enabled="false"/>
</join>
</network>
</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;
}
}