Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<module>vpro-shared-hibernate-search</module>
<module>vpro-shared-jackson2</module>
<module>vpro-shared-logging</module>
<module>vpro-shared-monitoring</module>
<module>vpro-shared-persistence</module>
<module>vpro-shared-resteasy</module>
<module>vpro-shared-rs</module>
Expand Down Expand Up @@ -394,6 +395,12 @@
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
Expand Down Expand Up @@ -736,7 +743,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
Expand Down
5 changes: 5 additions & 0 deletions vpro-shared-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@
<artifactId>vpro-shared-logging</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>nl.vpro.shared</groupId>
<artifactId>vpro-shared-monitoring</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>nl.vpro.shared</groupId>
<artifactId>vpro-shared-persistence</artifactId>
Expand Down
62 changes: 62 additions & 0 deletions vpro-shared-monitoring/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>nl.vpro.shared</groupId>
<artifactId>vpro-shared-parent</artifactId>
<version>2.16-SNAPSHOT</version>
</parent>
<artifactId>vpro-shared-monitoring</artifactId>
<description>This modules contains utilities and endpoints for application deployments and monitoring.</description>
<dependencies>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>nl.vpro.shared</groupId>
<artifactId>vpro-shared-test</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package nl.vpro.monitoring.web;

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 refreshedEvent) {
status = Status.READY;
}

@EventListener
public void onApplicationEvent(ContextStoppedEvent stoppedEvent) {
status = Status.STOPPING;
}

@GetMapping
public ResponseEntity<Health> health() {
return ResponseEntity.status(status.code).body(Health.builder().status(status.code).message(status.message).build());
}

private enum Status {
STARTING(503, "Application starting"),
READY(200, "Application ready"),
STOPPING(503, "Application shutdown");

int code;
String message;

Status(int code, String message) {
this.code = code;
this.message = message;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
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.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;
import org.springframework.test.web.servlet.MockMvc;
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;
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() {
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<Health> 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)
).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")));
}
}
29 changes: 29 additions & 0 deletions vpro-shared-monitoring/src/test/resources/manage-servlet.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

<context:annotation-config/>

<bean class="nl.vpro.monitoring.web.HealthController"/>

<bean id="jsonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="nl.vpro.jackson2.Jackson2Mapper" factory-method="getLenientInstance" />
</property>
</bean>

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="jsonHttpMessageConverter"/>
</util:list>
</property>
</bean>

</beans>