diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
index 9783a666d28..394fa29dac8 100644
--- a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
@@ -64,6 +64,11 @@
hazelcast-spring
true
+
+ com.hazelcast
+ hazelcast-client
+ test
+
com.sun.mail
jakarta.mail
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfiguration.java
new file mode 100644
index 00000000000..097b7f3bdfa
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfiguration.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-2019 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.hazelcast;
+
+import java.util.Map;
+
+import com.hazelcast.core.HazelcastInstance;
+
+import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthIndicatorConfiguration;
+import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
+import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
+import org.springframework.boot.actuate.hazelcast.HazelcastHealthIndicator;
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+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.autoconfigure.hazelcast.HazelcastAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for
+ * {@link HazelcastHealthIndicator}.
+ *
+ * @author Dmytro Nosan
+ * @since 2.2.0
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnClass(HazelcastInstance.class)
+@ConditionalOnBean(HazelcastInstance.class)
+@ConditionalOnEnabledHealthIndicator("hazelcast")
+@AutoConfigureBefore(HealthIndicatorAutoConfiguration.class)
+@AutoConfigureAfter(HazelcastAutoConfiguration.class)
+public class HazelcastHealthIndicatorAutoConfiguration
+ extends CompositeHealthIndicatorConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(name = "hazelcastHealthIndicator")
+ public HealthIndicator hazelcastHealthIndicator(Map hazelcastInstances) {
+ return createHealthIndicator(hazelcastInstances);
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/hazelcast/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/hazelcast/package-info.java
new file mode 100644
index 00000000000..58d63614e04
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/hazelcast/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2019 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 Hazelcast's actuator.
+ */
+package org.springframework.boot.actuate.autoconfigure.hazelcast;
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfigurationIntegrationTests.java
new file mode 100644
index 00000000000..8056ceef9b5
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfigurationIntegrationTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2019 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.hazelcast;
+
+import com.hazelcast.client.config.ClientConfig;
+import com.hazelcast.config.Config;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
+import org.springframework.boot.actuate.hazelcast.HazelcastHealthIndicator;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.Status;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration tests for {@link HazelcastHealthIndicatorAutoConfiguration}.
+ *
+ * @author Dmytro Nosan
+ */
+class HazelcastHealthIndicatorAutoConfigurationIntegrationTests {
+
+ private final HazelcastInstance hazelcastServer = Hazelcast.newHazelcastInstance(new Config());
+
+ private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withBean(ClientConfig.class)
+ .withConfiguration(AutoConfigurations.of(HazelcastHealthIndicatorAutoConfiguration.class,
+ HazelcastAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
+
+ @AfterEach
+ void shutdown() {
+ this.hazelcastServer.shutdown();
+ }
+
+ @Test
+ void hazelcastUp() {
+ this.contextRunner.run((context) -> {
+ assertThat(context).hasSingleBean(HazelcastInstance.class).hasSingleBean(HazelcastHealthIndicator.class);
+ HazelcastInstance hazelcast = context.getBean(HazelcastInstance.class);
+ Health health = context.getBean(HazelcastHealthIndicator.class).health();
+ assertThat(health.getStatus()).isEqualTo(Status.UP);
+ assertThat(health.getDetails()).containsOnlyKeys("name", "uuid").containsEntry("name", hazelcast.getName())
+ .containsEntry("uuid", hazelcast.getLocalEndpoint().getUuid());
+ });
+ }
+
+ @Test
+ void hazelcastDown() {
+ this.contextRunner.run((context) -> {
+ shutdown();
+ assertThat(context).hasSingleBean(HazelcastHealthIndicator.class);
+ Health health = context.getBean(HazelcastHealthIndicator.class).health();
+ assertThat(health.getStatus()).isEqualTo(Status.DOWN);
+ });
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfigurationTests.java
new file mode 100644
index 00000000000..a980c6db548
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/hazelcast/HazelcastHealthIndicatorAutoConfigurationTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2019 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.hazelcast;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
+import org.springframework.boot.actuate.hazelcast.HazelcastHealthIndicator;
+import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link HazelcastHealthIndicatorAutoConfiguration}.
+ *
+ * @author Dmytro Nosan
+ */
+class HazelcastHealthIndicatorAutoConfigurationTests {
+
+ private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class,
+ HazelcastHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
+
+ @Test
+ void runShouldCreateIndicator() {
+ this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HazelcastHealthIndicator.class)
+ .doesNotHaveBean(ApplicationHealthIndicator.class));
+ }
+
+ @Test
+ void runWhenDisabledShouldNotCreateIndicator() {
+ this.contextRunner.withPropertyValues("management.health.hazelcast.enabled:false")
+ .run((context) -> assertThat(context).doesNotHaveBean(HazelcastHealthIndicator.class)
+ .doesNotHaveBean(HazelcastHealthIndicator.class)
+ .hasSingleBean(ApplicationHealthIndicator.class));
+ }
+
+}
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
new file mode 100644
index 00000000000..42d531b5d92
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicator.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-2019 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.hazelcast;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.hazelcast.core.Endpoint;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.transaction.TransactionalTask;
+
+import org.springframework.boot.actuate.health.AbstractHealthIndicator;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.util.Assert;
+
+/**
+ * {@link HealthIndicator} for a Hazelcast.
+ *
+ * @author Dmytro Nosan
+ * @since 2.2.0
+ */
+public class HazelcastHealthIndicator extends AbstractHealthIndicator {
+
+ private static final TransactionalTask> TASK = (context) -> null;
+
+ private final HazelcastInstance hazelcast;
+
+ public HazelcastHealthIndicator(HazelcastInstance hazelcast) {
+ super("Hazelcast health check failed");
+ Assert.notNull(hazelcast, "HazelcastInstance must not be null");
+ this.hazelcast = hazelcast;
+ }
+
+ @Override
+ protected void doHealthCheck(Health.Builder builder) {
+ this.hazelcast.executeTransaction(TASK);
+ builder.up().withDetails(getDetails());
+ }
+
+ private Map getDetails() {
+ Map details = new LinkedHashMap<>();
+ Endpoint endpoint = this.hazelcast.getLocalEndpoint();
+ details.put("name", this.hazelcast.getName());
+ details.put("uuid", endpoint.getUuid());
+ return details;
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/package-info.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/package-info.java
new file mode 100644
index 00000000000..44e785578dc
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2019 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.
+ */
+
+/**
+ * Actuator support for Hazelcast.
+ */
+package org.springframework.boot.actuate.hazelcast;
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
new file mode 100644
index 00000000000..a8dd1d2841a
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicatorTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012-2019 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.hazelcast;
+
+import com.hazelcast.core.Endpoint;
+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 static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.BDDMockito.when;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link HazelcastHealthIndicator}.
+ *
+ * @author Dmytro Nosan
+ */
+class HazelcastHealthIndicatorTests {
+
+ private final HazelcastInstance hazelcast = mock(HazelcastInstance.class);
+
+ private final HazelcastHealthIndicator healthIndicator = new HazelcastHealthIndicator(this.hazelcast);
+
+ @Test
+ void hazelcastUp() {
+ Endpoint endpoint = mock(Endpoint.class);
+ when(this.hazelcast.getName()).thenReturn("hz0-instance");
+ when(this.hazelcast.getLocalEndpoint()).thenReturn(endpoint);
+ when(endpoint.getUuid()).thenReturn("7581bb2f-879f-413f-b574-0071d7519eb0");
+
+ Health health = this.healthIndicator.health();
+
+ assertThat(health.getStatus()).isEqualTo(Status.UP);
+ assertThat(health.getDetails()).containsOnlyKeys("name", "uuid").containsEntry("name", "hz0-instance")
+ .containsEntry("uuid", "7581bb2f-879f-413f-b574-0071d7519eb0");
+ }
+
+ @Test
+ void hazelcastDown() {
+ when(this.hazelcast.executeTransaction(any())).thenThrow(new HazelcastException());
+
+ Health health = this.healthIndicator.health();
+
+ assertThat(health.getStatus()).isEqualTo(Status.DOWN);
+ }
+
+}