Data Model
The app uses three domain objects. All are immutable Java record types (except SmartLaunchContext which is mutable session state). There is no database — all data comes from HAPI FHIR R4 via the ImmunizationFhirService.
VaccinationRecord
Wraps one FHIR Immunization resource, flattened for template rendering and JSON serialisation.
| Field | Type | FHIR source | Notes |
|---|---|---|---|
fhirId | String | Immunization.id | HAPI logical ID |
vaccineCode | String | Immunization.vaccineCode.coding[0].code | CVX (US), SNOMED CT, ICD-11 |
vaccineName | String | Immunization.vaccineCode.coding[0].display or .text | Human-readable name |
vaccineSystem | String | Immunization.vaccineCode.coding[0].system | e.g. http://hl7.org/fhir/sid/cvx |
occurrenceDate | LocalDate | Immunization.occurrenceDateTime | Converted from HAPI DateTimeType |
lotNumber | String | Immunization.lotNumber | For safety recalls |
performerOrganisationRef | String | Immunization.performer[0].actor.reference | FHIR Organisation reference |
performerDisplay | String | Immunization.performer[0].actor.display | Facility name |
doseNumber | String | Immunization.protocolApplied[0].doseNumber | "1", "2", "Booster" |
seriesName | String | Immunization.protocolApplied[0].series | Groups related doses |
status | String | Immunization.status.toCode() | completed, entered-in-error, not-done |
route | String | Immunization.route.coding[0].display | "IM", "SC", "PO" |
site | String | Immunization.site.coding[0].display | "Left deltoid" |
note | String | Immunization.note[0].text | Clinician notes or reactions |
patientReported | boolean | Immunization.reportedBooleanType | True for self-reported vaccinations |
Business methods
isValid() — returns true when status == "completed" AND occurrenceDate != null. Used to filter records for the VDS-NC certificate (only completed records with a known date are included).
shortLabel() — returns the vaccineName truncated to 40 characters if needed, falling back to vaccineCode, then "Unknown vaccine". Used in the dashboard recent-history card and certificate table.
VaccineRecommendation
Wraps one entry from a FHIR ImmunizationRecommendation.recommendation[] array.
| Field | Type | FHIR source | Notes |
|---|---|---|---|
fhirId | String | ImmunizationRecommendation.id | Parent resource ID |
vaccineCode | String | recommendation.vaccineCode[0].coding[0].code | |
vaccineName | String | recommendation.vaccineCode[0].coding[0].display | |
forecastStatus | String | recommendation.forecastStatus.coding[0].code | due, overdue, immune, contraindicated |
dateCriterionDue | LocalDate | dateCriterion where code = 30100 | Earliest recommended date |
dateCriterionLatest | LocalDate | dateCriterion where code = 30101 | Latest recommended date |
doseNumber | String | recommendation.doseNumber | |
seriesName | String | recommendation.series | |
seriesDosesRequired | String | recommendation.seriesDoses | Total doses in the series |
description | String | recommendation.description | Forecast narrative |
Business methods
isOverdue() — true if forecastStatus == "overdue" OR dateCriterionDue is before today AND the patient is not immune.
isDueWithin30Days() — true if due date is within the next 30 days (inclusive).
statusBadgeClass() — returns a CSS class string for the status badge: badge-overdue, badge-due, badge-immune, badge-contraindicated, or badge-neutral.
SmartLaunchContext
Mutable session object stored in the HTTP session under the key "SMART_LAUNCH_CONTEXT". Contains both pre-handshake data (cleared after /callback) and post-handshake data.
Post-handshake fields (used by views and services)
| Field | Source |
|---|---|
accessToken | access_token from token response |
refreshToken | refresh_token from token response |
patientId | patient top-level field in token response |
encounterId | encounter top-level field (may be null) |
needPatientBanner | need_patient_banner top-level field |
scope | scope from token response (space-separated) |
expiresAt | Instant.now() + expires_in seconds |
fhirBaseUrl | iss from the /launch request |
clinicianName | name claim from id_token |
fhirUser | fhirUser claim from id_token |
Pre-handshake fields (cleared after /callback)
| Field | Purpose |
|---|---|
pkceVerifier | 96-byte S256 verifier, sent in token exchange |
pkceState | 32-byte CSRF state, validated on callback |
nonce | 32-byte nonce, validated in id_token |
iss | ISS from launch, used for token exchange |
Session serialisation
All fields are primitives, String, or Instant. The class implements Serializable with serialVersionUID = 1L for Redis-based session replication in multi-instance deployments.
Next: Caching →