I recently had one of my students in our FHIR Bootcamp struggle with setting up HAPI FHIR so that when they post a FHIR Resource that belongs to a certain profile, it validates it before committing it to the server.
For example, if you make a POST request to /Patient
with:
{
"meta": {
"profile": [
"https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient"
]
},
"resourceType": "Patient"
}
You'd expect that the server validates against the https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient
profile automatically - because it's a URL on the internet. Right?!
Well, not really.
The above request just creates the resource by default, even though the identifier is mandatory.
We'll walk through how you can configure HAPI FHIR to do profile validation for you, and also cover a few fundamental concepts of FHIR Profiles so you don't get stuck.
We're using v7.4.0
of HAPI FHIR here. The following environment variables should be set on the runtime running HAPI FHIR:
HAPI_FHIR_VALIDATION_REQUESTS_ENABLED=true
HAPI_FHIR_SERVER_VALIDATION_FLAG_FAIL_ON_SEVERITY=error
HAPI_FHIR_SERVER_VALIDATION_FLAG_ENFORCE_REQUIREMENT=true
If you're using docker-compose, you can use this docker-compose.yml
services:
hapi-fhir-server:
image: hapiproject/hapi:v7.4.0-tomcat
container_name: hapi-fhir-server
ports:
- 8080:8080
environment:
HAPI_FHIR_VALIDATION_REQUESTS_ENABLED: 'true'
HAPI_FHIR_SERVER_VALIDATION_FLAG_FAIL_ON_SEVERITY: error
HAPI_FHIR_SERVER_VALIDATION_FLAG_ENFORCE_REQUIREMENT: 'true'
When posting a FHIR Resource with meta.profile
set to https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient
or http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient
, the FHIR server does know what this means!
This is because although it looks like a URL, according to the FHIR specification, this is just a URI (Uniform Resource Identifier) that acts as a "global identifier".
⚠️I repeat: The url
field which a FHIR StructureDefinition (profile) is referenced by is not always a RESOLVABLE URL. It acts more as a global identifier.
So we need to manually upload the StructureDefinition resource to your FHIR Server first.
You can use the StructureDefinition for ABDM FHIR Patient Profile.
POST /StructureDefinition
{
"resourceType": "StructureDefinition",
...grab the rest from the link
}
Or if you're interested in creating your own profile's StructureDefinition, check out this video:
Once you've done this, now you can actually post the FHIR resource against a profile, and the HAPI FHIR Server will validate it for you.
POST /Patient
{
"meta": {
"profile": [
"https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient"
]
},
"resourceType": "Patient"
}
will now return:
{
"resourceType": "OperationOutcome",
"issue": [
{
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-line",
"valueInteger": 1
},
{
"url": "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-col",
"valueInteger": 2
},
{
"url": "http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id",
"valueString": "Validation_VAL_Profile_Minimum"
}
],
"severity": "error",
"code": "processing",
"details": {
"coding": [
{
"system": "http://hl7.org/fhir/java-core-messageId",
"code": "Validation_VAL_Profile_Minimum"
}
]
},
"diagnostics": "Patient.identifier: minimum required = 1, but only found 0 (from https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient|6.0.0)",
"location": [
"Patient",
"Line[1] Col[2]"
]
}
]
}
as it should. Because identifier
is now mandated by the profile (1..1
). Look at our guide on cardinality.
Let's fix that error:
POST /Patient
{
"meta": {
"profile": [
"https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient"
]
},
"resourceType": "Patient",
"identifier": [
{
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR",
"display": "Medical record number"
}
]
},
"system": "https://healthid.ndhm.gov.in",
"value": "22-7225-4829-5255"
}
]
}
and voila! It works!