Skip to main content

Java / Spring Boot Integration

Consul Guardian runs as a sidecar next to your Java application. Your Spring Boot app reads configuration from Consul KV through Spring Cloud Consul. Guardian independently watches those same keys, commits every change to Git, and can restore any key to a previous value.

No code changes are required in your Java application.

How Spring Boot apps read from Consul

Spring Cloud Consul Config maps Consul KV entries to Spring's @Value and @ConfigurationProperties automatically.

Maven dependency

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>

Gradle dependency

implementation 'org.springframework.cloud:spring-cloud-starter-consul-config'

bootstrap.yml

spring:
application:
name: order-service
cloud:
consul:
host: consul
port: 8500
config:
enabled: true
format: YAML
prefix: config
default-context: order-service
watch:
enabled: true
delay: 5000

application.yml

spring:
datasource:
url: ${db.url}
username: ${db.username}
cache:
ttl: ${cache.ttl:300}

Using the config

@RestController
public class OrderController {

@Value("${db.url}")
private String dbUrl;

@Value("${cache.ttl:300}")
private int cacheTtl;

@GetMapping("/orders")
public ResponseEntity<List<Order>> getOrders() {
// Uses dbUrl and cacheTtl from Consul KV
return ResponseEntity.ok(orderService.findAll());
}
}

Your Consul KV structure:

config/order-service/db.url       →  "jdbc:postgresql://db.prod:5432/orders"
config/order-service/db.username → "app_user"
config/order-service/cache.ttl → "600"

Spring Cloud Consul watches for changes and refreshes @RefreshScope beans automatically. The problem: when a bad value lands in Consul, there's no built-in way to see what the previous value was or roll it back.

Adding Guardian

Docker Compose

version: "3.8"

services:
consul:
image: hashicorp/consul:1.17
ports:
- "8500:8500"
command: agent -dev -client=0.0.0.0

order-service:
build: .
ports:
- "8080:8080"
environment:
- SPRING_CLOUD_CONSUL_HOST=consul
- SPRING_CLOUD_CONSUL_PORT=8500
depends_on:
- consul

guardian:
image: ghcr.io/consul-guardian/consul-guardian:latest
environment:
- CONSUL_GUARDIAN_CONSUL_ADDRESS=http://consul:8500
- CONSUL_GUARDIAN_WATCH_PREFIXES=config/
- CONSUL_GUARDIAN_GIT_REPO_PATH=/data/repo
volumes:
- guardian-data:/data
depends_on:
- consul

volumes:
guardian-data:

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: myregistry/order-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_CLOUD_CONSUL_HOST
value: "consul.consul.svc.cluster.local"
- name: SPRING_CLOUD_CONSUL_PORT
value: "8500"

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: consul-guardian
spec:
replicas: 1
selector:
matchLabels:
app: consul-guardian
template:
metadata:
labels:
app: consul-guardian
spec:
containers:
- name: guardian
image: ghcr.io/consul-guardian/consul-guardian:latest
env:
- name: CONSUL_GUARDIAN_CONSUL_ADDRESS
value: "http://consul.consul.svc.cluster.local:8500"
- name: CONSUL_GUARDIAN_WATCH_PREFIXES
value: "config/"
- name: CONSUL_GUARDIAN_GIT_REPO_PATH
value: "/data/repo"
volumeMounts:
- name: guardian-data
mountPath: /data
volumes:
- name: guardian-data
persistentVolumeClaim:
claimName: guardian-pvc

Restore scenario

Someone updates the database URL to a wrong value:

consul kv put config/order-service/db.url "jdbc:postgresql://wrong-host:5432/orders"

Spring Cloud Consul picks up the change. Your app starts throwing PSQLException: Connection refused. All /orders requests return 500.

1. Find the previous value

consul-guardian log --key config/order-service/db.url

# 2024-03-15T14:45:00Z bad1234 config/order-service/db.url modified
# 2024-03-01T10:00:00Z good567 config/order-service/db.url modified
# 2024-01-15T09:00:00Z init890 config/order-service/db.url created

2. Restore

consul-guardian restore --key config/order-service/db.url --commit good567

3. Verify

consul kv get config/order-service/db.url
# jdbc:postgresql://db.prod:5432/orders ← correct value restored

Spring Cloud Consul detects the change and refreshes your beans. The app recovers without a restart.

Zero code changes

Guardian does not integrate with Spring, does not add a dependency to your pom.xml, and does not modify your classpath. It is a separate process that watches Consul KV independently. Your Spring Boot app and Guardian have no awareness of each other.