Professional Documents
Culture Documents
Theo Stolker
HL7®, FHIR® and the flame Design mark are the registered trademarks of Health Level Seven International and are used with per mission.
Agenda
• Intro
• Setting the Stage
• Where to start?
• Q&R
Intro
• Theo Stolker
• Principal Integration Architect at
Philips VitalHealth.
• Electrical Engineer by training
• Active in Software Development
since 1987
• Active in Application Integration
since 1998
• Implementing FHIR since 2014
Why this presentation?
• As part of my work I am involved in building
facades for a number of applications
• Goals:
• Share Findings
• Define Best Practices
Setting the Stage
Assumptions: (Smart)
• You want to expose Your HealthCare App Bridge/Broker Client
through a FHIR REST API App
Your
FHIR Event
Healthcare DB
Store Channel
App
Internal structure
• Dynamically loaded “plugin” class to implement
mapping to/from internal storage per FHIR
resource
1. void Read(FHIRRequestContext FRC, FHIRResponse FR);
2. Resource GetResourceFromObject(XmlObject
bodyMeasurement);
3. bool AddSearchColumn(TypeMetadata typeMetadata,
List<ISearchFilterItem> LSC, QueryParam queryParam);
4. void InsertOrUpdate(FHIRRequestContext FRC, FHIRResponse
FR, Resource ResourceToBeUpdated, XmlObject Observation);
5. void InvokeOperation(FHIRRequestContext FRC, FHIRResponse
FR, Parameters parameters);
What FHIR version(s) are you going to support?
• Current version = R4
• Markets and/or partners may
require supporting a previous
version
• Support multiple versions if
needed
• Be ready for known/planned
changes in later version(s)!
Resource Mapping – What resources
1. What data / resources must be exposed?
Start identifying key resources!
2. Be as specific as possible
Not everything is an Observation,
QuestionnaireResponse or Basic resource
3. FHIR is about Healthcare resources
Not everything maps to FHIR
Resource Mapping – Be predictable!
• Imperfections:
• Multiple internal object types map to
the same FHIR resource
• A single internal object type maps to
multiple FHIR resources
Reduce the supported scope to
something that works consistently
Imperfect Mapping Example 1 – Vital Signs
• Blood pressure - diastolic and systolic
values stored as 2 separate records
• GET /Observation without code
would lead to duplicate BP resources
being returned.
• Possible solutions
• Always require client to filter for a [set
of] specific codes
• Filter so that by default only diastolic
values are returned
Imperfect Mapping Example 2 – Observation flavors
• Labs might be stored different from
patient self measurements, vitals or
device measurements.
• Works as long as supported codes for
each subset are unique
• Use “micro-facades” where each
data type is represented using a
different endpoint
Element Mapping – it is not just semantics
• Only use an element if the
meaning of the data matches
according to the spec.
Use an extension instead of
incorrectly using an existing
element.
Guidelines for Resource Mapping – Choose your profile
• Use existing profiles as much as
possible
• Standard (e.g. vital-signs)
• (Inter)national e.g.
https://simplifier.net/NictizSTU3-
Zib2017/ZIB-BloodPressure
• Define / extend profiles with peers
& partners when nothing suitable
exists; try to avoid app-specific
profiles
Using contained resources
• Only when the contained
resources have no life outside the
resource these are contained in
• Examples:
• DiagnosticReport with contained
Observations (matching HL7v2 ORU
etc.)
• …
Resource.meta, tags and security labels
• Does your application have a:
• Version
• Last modified timestamp
• Source
If so fill in Resource.meta
• Tags and Security Labels
• Adding and removing should not
affect the resource version
so store separately.
Study the spec (1) - RESTful API – http.html
What interactions do you
need to support?
• delete – medical history
should remain with a status
e.g. “entered-in-error”
• history – who needs it?
• patch – too many options
• system-wide search – not
so hard, use _type
Study the spec (2) - search.html
• Filtering
• Choose standard parameters ()
• _id to search for specific Resource.id
• Incremental queries e.g.
?_lastUpdated=gt2019-11-01
• Choose resource-specific parameters
• ?identifier={system}|{identifier}
• ?patient={id} etc.
• Chaining examples:
• Observation?patient.name=Smith
• Observation?patient.general-practitioner.name=Jones
Our implementation loads target plugin for chained search
Paging – an undervalued part of the specification
• Paging is of critical importance for
building performant and scalable
solutions
• Choose a relatively low default
value for _count (our choice: 20)
• Repeat _count in the returned
paging links
• Returning OperationOutcome to
say “there are more results” is
lame.
Including resources is very powerful!
• Examples
• Observation?_include=Observation:patient
• Observation?_revinclude=Provenance:target
• Parameter values have three parts, separated by a : character:
• The name of the source resource from which the join comes
• The name of the search parameter which must be of type reference
(can be *)
• (Optional) A specific of type of target resource (for when the search
parameter refers to multiple possible target types)
• Use “_include:iterate” for deep inclusion (STU3 had “:recurse”)
Conditional create, update and delete
• External applications will not know
and use your Resource.id
• Avoid expensive tight coupling
(search/update etc.)
• Conditional create, update or
delete allow to use identifiers for
resource matching
Use Conditional Create unless you
want to explicitly overwrite data in an
integration
Managing Resource Contention – see concurrency
• How to avoid changes made by one
client be overwritten by another?
• FHIR supports version-aware
updates
• Doesn’t work so good for batch
requests from a loosely coupled
system.
Implementing Referential Integrity
• Do you need to enforce it?
• Use logical references for loose coupling
<Observation>
<subject>
<identifier>
<system value="http://hl7.org/fhir/sid/us-ssn" />
<value value="000111111" />
</identifier>
</subject>