Skip to main content

Configuration

Environment variables

VariableDefaultRequired in prodDescription
SMART_CLIENT_IDaj-fhir-immunizationThe client_id registered on the auth server
SMART_REDIRECT_URIhttp://localhost:8084/callbackMust match the auth server registration exactly
AUTH_SERVER_URLhttp://localhost:9000Auth server base URL — used for SMART discovery
FHIR_BASE_URLhttp://localhost:8080/fhirHAPI FHIR JPA base URL

No other environment variables are required. All remaining properties have sensible defaults.

Full application.yml reference

immunization:
# OAuth2 client registration
client-id: ${SMART_CLIENT_ID:aj-fhir-immunization}
redirect-uri: ${SMART_REDIRECT_URI:http://localhost:8084/callback}

# SMART scopes requested on every launch
scopes: >
launch openid fhirUser
patient/Patient.rs
patient/Immunization.rs
patient/ImmunizationRecommendation.rs

# Service URLs
auth-server-url: ${AUTH_SERVER_URL:http://localhost:9000}
fhir-base-url: ${FHIR_BASE_URL:http://localhost:8080/fhir}

# Proactive token refresh: fires when less than this many seconds remain
token-refresh-buffer-seconds: 120

# SMART discovery cache TTL per ISS — avoids repeated calls to /.well-known/
discovery-cache-ttl-seconds: 600

# WHO schedule resource path (bundled JSON, used by future schedule advisor)
who-schedule-path: classpath:who-vaccine-schedule.json

Scopes

The app always requests exactly these six scopes and no others:

ScopePurpose
launchEHR launch context — receives the launch token from the portal
openidOIDC — enables id_token issuance
fhirUserClinician Practitioner reference in id_token
patient/Patient.rsRead patient demographics for the certificate header
patient/Immunization.rsRead vaccination history
patient/ImmunizationRecommendation.rsRead forecast / due dates

If the patient has a Consent Manager record that does not cover patient/Immunization.rs, the token exchange succeeds but HAPI FHIR returns 403 on the Immunization query — the Consent Manager's scope interceptor blocks the request. The app handles this gracefully by returning an empty vaccination list.

Caching

application.yml configures a Caffeine cache:

spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=500,expireAfterWrite=600s

Five separate cache regions are used:

Cache nameKeyTTLWhat it stores
immunizationspatientId600 sList<VaccinationRecord>
recommendationspatientId600 sList<VaccineRecommendation>
patientpatientId600 sHAPI Patient resource
smartDiscoveryiss600 sSMART configuration document

The dashboard, history, schedule, and certificate pages all share the same cache — navigating between views does not trigger additional HAPI FHIR requests within a 10-minute window.

Session

spring:
session:
timeout: 3600s

The HTTP session timeout matches the access token TTL. For Redis-backed sessions (multi-instance deployments), add:

spring:
session:
store-type: redis
data:
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}

All session objects implement Serializable with pinned serialVersionUID.

Test profile

Activate with -Dspring.profiles.active=test or @ActiveProfiles("test"). The test profile:

  • Points auth-server-url at http://localhost:9999 (WireMock)
  • Points fhir-base-url at http://localhost:9998/fhir (WireMock)
  • Disables Thymeleaf template cache
  • Uses test-immunization-client as the client ID

Next: Platform Registration →