From 850ace5f5e34bc2747aa82546837abdc286cec6a Mon Sep 17 00:00:00 2001 From: Mona Mohamadinia Date: Fri, 14 Aug 2020 03:02:52 +0430 Subject: [PATCH 1/4] Custom Health Indicators in Spring Boot --- .../baeldung/health/HealthApplication.java | 12 ++++++++ .../health/RandomHealthIndicator.java | 28 +++++++++++++++++++ .../src/main/resources/application.properties | 6 +++- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/HealthApplication.java create mode 100644 spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/HealthApplication.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/HealthApplication.java new file mode 100644 index 0000000000..af1f35b29f --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/HealthApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.health; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HealthApplication { + + public static void main(String[] args) { + SpringApplication.run(HealthApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java new file mode 100644 index 0000000000..958f173458 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java @@ -0,0 +1,28 @@ +package com.baeldung.health; + +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; + +@Component +public class RandomHealthIndicator implements HealthIndicator { + + @Override + public Health health() { + double chance = ThreadLocalRandom.current().nextDouble(); + Health.Builder status = Health.up(); + if (chance > 0.9) { + status = Health.down(new RuntimeException("Bad Luck")); + } + + Map details = new HashMap<>(); + details.put("chance", chance); + details.put("strategy", "thread-local"); + + return status.withDetails(details).build(); + } +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties b/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties index 8c706a9b1d..290221b731 100644 --- a/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties @@ -1 +1,5 @@ -management.health.probes.enabled=true \ No newline at end of file +management.health.probes.enabled=true +management.endpoint.health.show-details=always +management.health.random.enabled=false +management.endpoint.health.status.http-mapping.down=500 +management.endpoint.health.status.http-mapping.out_of_service=503 \ No newline at end of file From 89ef54df80995ef56f7e31fa926749d0ae62ece6 Mon Sep 17 00:00:00 2001 From: Mona Mohamadinia Date: Fri, 14 Aug 2020 03:26:35 +0430 Subject: [PATCH 2/4] Added a HttpCodeStatusMapper impl. --- .../health/CustomStatusCodeMapper.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java new file mode 100644 index 0000000000..0ff6773240 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java @@ -0,0 +1,26 @@ +package com.baeldung.health; + +import org.springframework.boot.actuate.health.HttpCodeStatusMapper; +import org.springframework.boot.actuate.health.Status; +import org.springframework.stereotype.Component; + +@Component +public class CustomStatusCodeMapper implements HttpCodeStatusMapper { + + @Override + public int getStatusCode(Status status) { + if (status == Status.DOWN) { + return 500; + } + + if (status == Status.OUT_OF_SERVICE) { + return 503; + } + + if (status == Status.UNKNOWN) { + return 500; + } + + return 200; + } +} From ba5f54d666e4fd0a13a5eb2982a7321df1006ea9 Mon Sep 17 00:00:00 2001 From: Mona Mohamadinia Date: Tue, 18 Aug 2020 00:55:42 +0430 Subject: [PATCH 3/4] Fixed the Broken Test --- spring-boot-modules/spring-boot-actuator/pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-boot-modules/spring-boot-actuator/pom.xml b/spring-boot-modules/spring-boot-actuator/pom.xml index 0a7ad5725b..701949519e 100644 --- a/spring-boot-modules/spring-boot-actuator/pom.xml +++ b/spring-boot-modules/spring-boot-actuator/pom.xml @@ -43,6 +43,9 @@ org.springframework.boot spring-boot-maven-plugin + + com.baeldung.probes.ProbesApplication + From 090404a08be19d7c323bb0fc74dbc6b695c5ee98 Mon Sep 17 00:00:00 2001 From: Mona Mohamadinia Date: Wed, 19 Aug 2020 13:13:46 +0430 Subject: [PATCH 4/4] Added Tests --- .../health/CustomStatusCodeMapper.java | 4 +++ .../health/RandomHealthIndicator.java | 2 ++ .../health/WarningHealthIndicator.java | 14 ++++++++++ .../src/main/resources/application.properties | 4 +-- ...dRandomHealthIndicatorIntegrationTest.java | 26 +++++++++++++++++++ .../RandomHealthIndicatorIntegrationTest.java | 26 +++++++++++++++++++ ...WarningHealthIndicatorIntegrationTest.java | 26 +++++++++++++++++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/WarningHealthIndicator.java create mode 100644 spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/DisabledRandomHealthIndicatorIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/RandomHealthIndicatorIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/WarningHealthIndicatorIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java index 0ff6773240..483c21dfc1 100644 --- a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/CustomStatusCodeMapper.java @@ -21,6 +21,10 @@ public class CustomStatusCodeMapper implements HttpCodeStatusMapper { return 500; } + if (status.getCode().equals("WARNING")) { + return 500; + } + return 200; } } diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java index 958f173458..d8b27c7865 100644 --- a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/RandomHealthIndicator.java @@ -1,5 +1,6 @@ package com.baeldung.health; +import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.stereotype.Component; @@ -9,6 +10,7 @@ import java.util.Map; import java.util.concurrent.ThreadLocalRandom; @Component +@ConditionalOnEnabledHealthIndicator("random") public class RandomHealthIndicator implements HealthIndicator { @Override diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/WarningHealthIndicator.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/WarningHealthIndicator.java new file mode 100644 index 0000000000..d978d90339 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/health/WarningHealthIndicator.java @@ -0,0 +1,14 @@ +package com.baeldung.health; + +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.stereotype.Component; + +@Component +public class WarningHealthIndicator implements HealthIndicator { + + @Override + public Health health() { + return Health.status("WARNING").build(); + } +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties b/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties index 290221b731..27dba985b8 100644 --- a/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties @@ -1,5 +1,5 @@ management.health.probes.enabled=true management.endpoint.health.show-details=always -management.health.random.enabled=false management.endpoint.health.status.http-mapping.down=500 -management.endpoint.health.status.http-mapping.out_of_service=503 \ No newline at end of file +management.endpoint.health.status.http-mapping.out_of_service=503 +management.endpoint.health.status.http-mapping.warning=500 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/DisabledRandomHealthIndicatorIntegrationTest.java b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/DisabledRandomHealthIndicatorIntegrationTest.java new file mode 100644 index 0000000000..b69e7fd1f8 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/DisabledRandomHealthIndicatorIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.health; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@TestPropertySource(properties = "management.health.random.enabled=false") +class DisabledRandomHealthIndicatorIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void givenADisabledIndicator_whenSendingRequest_thenReturns404() throws Exception { + mockMvc.perform(get("/actuator/health/random")) + .andExpect(status().isNotFound()); + } +} diff --git a/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/RandomHealthIndicatorIntegrationTest.java b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/RandomHealthIndicatorIntegrationTest.java new file mode 100644 index 0000000000..dba38d4da3 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/RandomHealthIndicatorIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.health; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@SpringBootTest +@AutoConfigureMockMvc +class RandomHealthIndicatorIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void givenRandomIndicator_whenCallingTheAPI_thenReturnsExpectedDetails() throws Exception { + mockMvc.perform(get("/actuator/health/random")) + .andExpect(jsonPath("$.status").exists()) + .andExpect(jsonPath("$.details.strategy").value("thread-local")) + .andExpect(jsonPath("$.details.chance").exists()); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/WarningHealthIndicatorIntegrationTest.java b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/WarningHealthIndicatorIntegrationTest.java new file mode 100644 index 0000000000..60d11a00c7 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/health/WarningHealthIndicatorIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.health; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +class WarningHealthIndicatorIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void givenCustomMapping_whenCallingTheAPI_thenTheStatusCodeIsAsExpected() throws Exception { + mockMvc.perform(get("/actuator/health/warning")) + .andExpect(jsonPath("$.status").value("WARNING")) + .andExpect(status().isInternalServerError()); + } +} \ No newline at end of file