Repository navigation
Add Actuator health, readiness and info endpoints (#335) - #343
Merged
Merged
Conversation
The backend had no way to tell whether a running instance is up or can reach the services it depends on. - spring-boot-starter-actuator with only health and info exposed over HTTP; env, beans, heapdump and the rest stay closed. - /actuator/health/liveness reflects the JVM only. readiness also covers PostgreSQL and two new indicators, keycloak (the realm's OpenID discovery document) and setupService (its /actuator/health), probed with their own 3 s client so a dead upstream reports DOWN instead of hanging. - /actuator/info reports build info and the git commit (git-commit-id-maven-plugin, which tolerates a missing .git). - Anonymous callers get the status only; components need a token. - SecurityConfiguration permits GET /actuator/health/** and requires the user role for every other /actuator path. The catch-all permitAll would otherwise have left them open, since actuator endpoints carry no @PreAuthorize. - The management settings live in application.properties so they apply to every profile, including the one the server runs. - Dockerfile HEALTHCHECK on liveness, so an upstream outage never gets the container restarted. Compose gets health checks for both databases and Keycloak (bash /dev/tcp against its management port, the image has no curl) and service_healthy ordering for Keycloak and the backend. - README section on the endpoints and `docker compose up --wait`. Closes #335
uiysg
approved these changes
Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #335
This adds Spring Boot Actuator so we can finally tell whether a running backend is alive and whether it can reach the things it depends on.
/actuator/health/livenessonly reflects the JVM and is what the DockerHEALTHCHECKuses, so a database or setup-service outage never gets the container restarted in a loop./actuator/health/readinessalso checks PostgreSQL, Keycloak and the setup-service and returns 503 if any of them is unreachable. Both work without a token;/actuator/healthshows the individual components only to logged-in users./actuator/inforeturns the version and the git commit the instance was built from and needs a token. Nothing else is exposed.One thing worth a look in
SecurityConfiguration: the chain ends inanyRequest().permitAll()and relies on@PreAuthorizein the controllers. Actuator endpoints don't have that, so without extra rules everything exposed would have been public. I addedpermitAllforGET /actuator/health/**andhasRole("user")for the rest of/actuator/**.The Keycloak and setup-service checks use their own client with a 3 s timeout, so a dead upstream shows up as DOWN instead of hanging the health endpoint. The management settings go in
application.propertiesrather than a profile file, because the server picks its profile in a compose file that isn't in this repo. In compose, both databases and Keycloak now have health checks, and Keycloak and the backend wait for their dependencies. Keycloak's image has no curl, so its check talks to the management port through bash.Heads-up for local setups: Keycloak keeps its data inside its own container, not in
keycloak-db, which has no tables. Since thekeycloakservice changes here, the nextdocker compose uprecreates that container and the realm and test users are gone, so you'll need to import the realm again.docker starton the existing containers avoids that.I tested it with the full build (418 tests), a security test that hits the real actuator endpoints (everything except health returns 401 anonymously), and by running the jar locally. Stopping the setup-service or Keycloak flipped readiness to 503 while liveness stayed 200, and both recovered once the service was back. The image built from the
Dockerfilewent healthy after about 20 s.Not included: Prometheus metrics (no scraper yet) and fixing the
methodologistcompose service itself, which still doesn't build as written.