From d3c8b53b62817493ad66a639da0e53cc04c0532e Mon Sep 17 00:00:00 2001 From: Roelof Jan Date: Wed, 7 Oct 2020 13:52:12 +0200 Subject: [PATCH 1/3] PIS-30 Shared health endpoint --- pom.xml | 2 +- vpro-shared-bom/pom.xml | 5 ++ vpro-shared-monitoring/pom.xml | 53 ++++++++++++++++ .../nl/vpro/monitoring/domain/Health.java | 11 ++++ .../vpro/monitoring/web/HealthController.java | 47 +++++++++++++++ .../monitoring/web/HealthControllerTest.java | 60 +++++++++++++++++++ .../src/test/resources/manage-servlet.xml | 29 +++++++++ vpro-shared-test/pom.xml | 9 +++ 8 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 vpro-shared-monitoring/pom.xml create mode 100644 vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/domain/Health.java create mode 100644 vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java create mode 100644 vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java create mode 100644 vpro-shared-monitoring/src/test/resources/manage-servlet.xml diff --git a/pom.xml b/pom.xml index 09f21e5f5..1f3c8af89 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,7 @@ vpro-shared-hibernate-search vpro-shared-jackson2 vpro-shared-logging + vpro-shared-monitoring vpro-shared-persistence vpro-shared-resteasy vpro-shared-rs @@ -736,7 +737,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 attach-javadocs diff --git a/vpro-shared-bom/pom.xml b/vpro-shared-bom/pom.xml index 985391562..0d058102f 100644 --- a/vpro-shared-bom/pom.xml +++ b/vpro-shared-bom/pom.xml @@ -112,6 +112,11 @@ vpro-shared-logging ${project.version} + + nl.vpro.shared + vpro-shared-monitoring + ${project.version} + nl.vpro.shared vpro-shared-persistence diff --git a/vpro-shared-monitoring/pom.xml b/vpro-shared-monitoring/pom.xml new file mode 100644 index 000000000..50719898c --- /dev/null +++ b/vpro-shared-monitoring/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + + nl.vpro.shared + vpro-shared-parent + 2.16-SNAPSHOT + + vpro-shared-monitoring + This modules contains utilities and endpoints for application deployments and monitoring. + + + nl.vpro.shared + vpro-shared-test + + + javax.servlet + javax.servlet-api + 3.1.0 + test + + + org.slf4j + slf4j-api + + + com.fasterxml.jackson.core + jackson-core + compile + + + org.projectlombok + lombok + + + org.springframework + spring-context + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + test + + + org.springframework + spring-test + + + diff --git a/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/domain/Health.java b/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/domain/Health.java new file mode 100644 index 000000000..893354074 --- /dev/null +++ b/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/domain/Health.java @@ -0,0 +1,11 @@ +package nl.vpro.monitoring.domain; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class Health { + private int status; + private String message; +} diff --git a/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java b/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java new file mode 100644 index 000000000..9b7196e27 --- /dev/null +++ b/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java @@ -0,0 +1,47 @@ +package nl.vpro.monitoring.web; + +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.event.*; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import nl.vpro.monitoring.domain.Health; + +@Lazy(false) +@RestController +@RequestMapping(value = "/health", produces = MediaType.APPLICATION_JSON_VALUE) +public class HealthController { + + private Status status = Status.STARTING; + + @EventListener + public void onApplicationEvent(ContextRefreshedEvent contextStartedEvent) { + status = Status.STARTED; + } + + @EventListener + public void onApplicationEvent(ContextStoppedEvent stoppedEvent) { + status = Status.STOPPED; + } + + @GetMapping + public ResponseEntity health() { + return ResponseEntity.status(status.code).body(Health.builder().status(status.code).message(status.message).build()); + } + + private enum Status { + STARTING(503, "Application starting"), + STARTED(200, "Application ready"), + STOPPED(503, "Application shutdown"); + + int code; + String message; + + Status(int code, String message) { + this.code = code; + this.message = message; + } + } +} diff --git a/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java b/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java new file mode 100644 index 000000000..ee82113ba --- /dev/null +++ b/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java @@ -0,0 +1,60 @@ +package nl.vpro.monitoring.web; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.ContextStoppedEvent; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.hamcrest.Matchers.is; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +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; + +@ExtendWith(SpringExtension.class) +@WebAppConfiguration +@ContextConfiguration("/manage-servlet.xml") +class HealthControllerTest { + @Autowired + private HealthController healthController; + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @BeforeEach + public void setup() { + // Testing start-up with MockMvc seems complicated. + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + void statusReady() throws Exception { + mockMvc.perform( + get("/health") + .accept(APPLICATION_JSON_VALUE) + ).andExpect(status().is(200)) + .andExpect(jsonPath("$.status", is(200))) + .andExpect(jsonPath("$.message", is("Application ready"))); + } + + @Test + void statusStopping() throws Exception { + healthController.onApplicationEvent((ContextStoppedEvent) null); + + mockMvc.perform( + get("/health") + .accept(APPLICATION_JSON_VALUE) + ).andExpect(status().is(503)) + .andExpect(jsonPath("$.status", is(503))) + .andExpect(jsonPath("$.message", is("Application shutdown"))); + } +} diff --git a/vpro-shared-monitoring/src/test/resources/manage-servlet.xml b/vpro-shared-monitoring/src/test/resources/manage-servlet.xml new file mode 100644 index 000000000..769bc79c7 --- /dev/null +++ b/vpro-shared-monitoring/src/test/resources/manage-servlet.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vpro-shared-test/pom.xml b/vpro-shared-test/pom.xml index dc57cff9a..bb09d4acd 100644 --- a/vpro-shared-test/pom.xml +++ b/vpro-shared-test/pom.xml @@ -25,6 +25,11 @@ com.fasterxml.jackson.core jackson-databind + + com.jayway.jsonpath + json-path-assert + 2.4.0 + org.xmlunit xmlunit-core @@ -45,6 +50,10 @@ junit-jupiter-params true + + org.hamcrest + hamcrest-all + org.skyscreamer jsonassert From 7ee01e1f21c1816182e4adf637bfc52c49221b42 Mon Sep 17 00:00:00 2001 From: Michiel Meeuwissen Date: Wed, 7 Oct 2020 23:48:27 +0200 Subject: [PATCH 2/3] Cleaned up dependencies a bit. --- pom.xml | 6 ++++++ vpro-shared-monitoring/pom.xml | 6 +++--- vpro-shared-test/pom.xml | 6 +----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 1f3c8af89..c986b6a8d 100644 --- a/pom.xml +++ b/pom.xml @@ -395,6 +395,12 @@ ${assertj.version} test + + com.jayway.jsonpath + json-path-assert + 2.4.0 + test + org.springframework spring-web diff --git a/vpro-shared-monitoring/pom.xml b/vpro-shared-monitoring/pom.xml index 50719898c..e9911adbc 100644 --- a/vpro-shared-monitoring/pom.xml +++ b/vpro-shared-monitoring/pom.xml @@ -10,13 +10,13 @@ This modules contains utilities and endpoints for application deployments and monitoring. - nl.vpro.shared - vpro-shared-test + com.jayway.jsonpath + json-path-assert + test javax.servlet javax.servlet-api - 3.1.0 test diff --git a/vpro-shared-test/pom.xml b/vpro-shared-test/pom.xml index bb09d4acd..b47086f7d 100644 --- a/vpro-shared-test/pom.xml +++ b/vpro-shared-test/pom.xml @@ -25,11 +25,7 @@ com.fasterxml.jackson.core jackson-databind - - com.jayway.jsonpath - json-path-assert - 2.4.0 - + org.xmlunit xmlunit-core From 44ca099b06d67ad38532776fd16d92c2d41938b1 Mon Sep 17 00:00:00 2001 From: Roelof Jan Date: Thu, 8 Oct 2020 10:27:31 +0200 Subject: [PATCH 3/3] PIS-30 Shared health endpoint --- vpro-shared-monitoring/pom.xml | 11 ++++++++++- .../vpro/monitoring/web/HealthController.java | 11 +++++------ .../monitoring/web/HealthControllerTest.java | 18 +++++++++++++++++- vpro-shared-test/pom.xml | 5 ----- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/vpro-shared-monitoring/pom.xml b/vpro-shared-monitoring/pom.xml index e9911adbc..7657a2373 100644 --- a/vpro-shared-monitoring/pom.xml +++ b/vpro-shared-monitoring/pom.xml @@ -12,13 +12,22 @@ com.jayway.jsonpath json-path-assert - test + 2.4.0 + + + nl.vpro.shared + vpro-shared-test javax.servlet javax.servlet-api + 3.1.0 test + + org.hamcrest + hamcrest-all + org.slf4j slf4j-api diff --git a/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java b/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java index 9b7196e27..494a30e01 100644 --- a/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java +++ b/vpro-shared-monitoring/src/main/java/nl/vpro/monitoring/web/HealthController.java @@ -1,6 +1,5 @@ package nl.vpro.monitoring.web; -import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Lazy; import org.springframework.context.event.*; import org.springframework.http.MediaType; @@ -17,13 +16,13 @@ public class HealthController { private Status status = Status.STARTING; @EventListener - public void onApplicationEvent(ContextRefreshedEvent contextStartedEvent) { - status = Status.STARTED; + public void onApplicationEvent(ContextRefreshedEvent refreshedEvent) { + status = Status.READY; } @EventListener public void onApplicationEvent(ContextStoppedEvent stoppedEvent) { - status = Status.STOPPED; + status = Status.STOPPING; } @GetMapping @@ -33,8 +32,8 @@ public ResponseEntity health() { private enum Status { STARTING(503, "Application starting"), - STARTED(200, "Application ready"), - STOPPED(503, "Application shutdown"); + READY(200, "Application ready"), + STOPPING(503, "Application shutdown"); int code; String message; diff --git a/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java b/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java index ee82113ba..a89316846 100644 --- a/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java +++ b/vpro-shared-monitoring/src/test/java/nl/vpro/monitoring/web/HealthControllerTest.java @@ -4,7 +4,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextStoppedEvent; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.web.WebAppConfiguration; @@ -12,6 +14,9 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import nl.vpro.monitoring.domain.Health; + +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.is; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -32,12 +37,23 @@ class HealthControllerTest { @BeforeEach public void setup() { - // Testing start-up with MockMvc seems complicated. this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } + @Test + void initialValues() { + // Pragmatic testing of initial values. Using #wac and #mockMvc is more or less impossible. + ResponseEntity response = new HealthController().health(); + assertThat(response.getStatusCodeValue()).isEqualTo(503); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().getStatus()).isEqualTo(503); + assertThat(response.getBody().getMessage()).isEqualTo("Application starting"); + } + @Test void statusReady() throws Exception { + healthController.onApplicationEvent((ContextRefreshedEvent) null); + mockMvc.perform( get("/health") .accept(APPLICATION_JSON_VALUE) diff --git a/vpro-shared-test/pom.xml b/vpro-shared-test/pom.xml index b47086f7d..dc57cff9a 100644 --- a/vpro-shared-test/pom.xml +++ b/vpro-shared-test/pom.xml @@ -25,7 +25,6 @@ com.fasterxml.jackson.core jackson-databind - org.xmlunit xmlunit-core @@ -46,10 +45,6 @@ junit-jupiter-params true - - org.hamcrest - hamcrest-all - org.skyscreamer jsonassert