Merge pull request #921 from hapifhir/health-check
Standalone Java Health Check & Hibernate Dialect Override Fix
This commit is contained in:
@@ -15,6 +15,9 @@ FROM build-hapi AS build-distroless
|
|||||||
RUN mvn package -DskipTests spring-boot:repackage -Pboot
|
RUN mvn package -DskipTests spring-boot:repackage -Pboot
|
||||||
RUN mkdir /app && cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main.war
|
RUN mkdir /app && cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main.war
|
||||||
|
|
||||||
|
COPY src/main/java/HealthCheck.java /app/HealthCheck.java
|
||||||
|
RUN javac /app/HealthCheck.java
|
||||||
|
|
||||||
|
|
||||||
########### Use the official Tomcat image as base image for the Tomcat variant
|
########### Use the official Tomcat image as base image for the Tomcat variant
|
||||||
########### it can be built using eg. `docker build --target tomcat .`
|
########### it can be built using eg. `docker build --target tomcat .`
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -475,6 +475,20 @@ jpa:
|
|||||||
# Then comment all hibernate.search.backend.*
|
# Then comment all hibernate.search.backend.*
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Docker Health Check
|
||||||
|
|
||||||
|
The distroless Docker image includes a built-in health check that verifies the FHIR server is operational by calling the `/fhir/metadata` endpoint and confirming a valid `CapabilityStatement` is returned. It uses a standalone Java class with no external dependencies, making it compatible with the distroless base image which has no shell or utilities like `curl`.
|
||||||
|
|
||||||
|
To run the health check inside a running container:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec hapi-fhir-jpaserver-start java -cp /app HealthCheck
|
||||||
|
```
|
||||||
|
|
||||||
|
An exit code of `0` indicates the server is healthy. An exit code of `1` indicates a failure, with diagnostic details written to stderr.
|
||||||
|
|
||||||
|
To enable periodic health checks, uncomment the `healthcheck` block in `docker-compose.yml`.
|
||||||
|
|
||||||
## Running hapi-fhir-jpaserver directly from IntelliJ as Spring Boot
|
## Running hapi-fhir-jpaserver directly from IntelliJ as Spring Boot
|
||||||
Make sure you run with the maven profile called ```boot``` and NOT also ```jetty```. Then you are ready to press debug the project directly without any extra Application Servers.
|
Make sure you run with the maven profile called ```boot``` and NOT also ```jetty```. Then you are ready to press debug the project directly without any extra Application Servers.
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,17 @@ services:
|
|||||||
SPRING_DATASOURCE_USERNAME: "admin"
|
SPRING_DATASOURCE_USERNAME: "admin"
|
||||||
SPRING_DATASOURCE_PASSWORD: "admin"
|
SPRING_DATASOURCE_PASSWORD: "admin"
|
||||||
SPRING_DATASOURCE_DRIVER_CLASS_NAME: "org.postgresql.Driver"
|
SPRING_DATASOURCE_DRIVER_CLASS_NAME: "org.postgresql.Driver"
|
||||||
SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
HIBERNATE_DIALECT: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
|
# Uncomment to enable periodic health checks.
|
||||||
|
# Can also be run manually: docker exec hapi-fhir-jpaserver-start java -cp /app HealthCheck
|
||||||
|
# healthcheck:
|
||||||
|
# test: ["CMD", "java", "-cp", "/app", "HealthCheck"]
|
||||||
|
# interval: 30s
|
||||||
|
# timeout: 10s
|
||||||
|
# start_period: 60s
|
||||||
|
# retries: 3
|
||||||
depends_on:
|
depends_on:
|
||||||
hapi-fhir-postgres:
|
hapi-fhir-postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
45
src/main/java/HealthCheck.java
Normal file
45
src/main/java/HealthCheck.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class HealthCheck {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
var port = System.getenv().getOrDefault("SERVER_PORT", "8080");
|
||||||
|
var url = new URL("http://localhost:" + port + "/fhir/metadata");
|
||||||
|
var conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.setRequestProperty("Accept", "application/fhir+json");
|
||||||
|
conn.setConnectTimeout(10000);
|
||||||
|
conn.setReadTimeout(10000);
|
||||||
|
|
||||||
|
var status = conn.getResponseCode();
|
||||||
|
if (status != 200) {
|
||||||
|
System.err.println("Health check failed: HTTP " + status);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var body = new StringBuilder();
|
||||||
|
try (var reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
body.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pattern = Pattern.compile("\"resourceType\"\\s*:\\s*\"CapabilityStatement\"");
|
||||||
|
if (pattern.matcher(body.toString()).find()) {
|
||||||
|
System.exit(0);
|
||||||
|
} else {
|
||||||
|
System.err.println("Health check failed: CapabilityStatement not found in response");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Health check failed: " + e.getMessage());
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -120,7 +120,7 @@ spring:
|
|||||||
# Hibernate dialect is auto-detected except for H2/Postgres.
|
# Hibernate dialect is auto-detected except for H2/Postgres.
|
||||||
# If using H2: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
# If using H2: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||||
# If using Postgres: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
# If using Postgres: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
||||||
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
dialect: ${HIBERNATE_DIALECT:ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect}
|
||||||
|
|
||||||
# --- Optional Hibernate DDL & tuning (commented out from source) ---
|
# --- Optional Hibernate DDL & tuning (commented out from source) ---
|
||||||
hbm2ddl:
|
hbm2ddl:
|
||||||
|
|||||||
Reference in New Issue
Block a user