FHIR Programming using Java and HAPI FHIR Server - Working with Canadian FHIR Profiles
Introduction
Welcome back to my series on FHIR Programming using Java and HAPI FHIR Server. In this article, we will explore FHIR profiles and demonstrate their practical application using Canadian Core profiles. Profiles are one of FHIR's most powerful features, allowing organizations and jurisdictions to customize the base FHIR specification to meet their specific requirements while maintaining interoperability.
This tutorial builds upon our previous discussions, including our exploration of building SMART on FHIR applications. If you're unfamiliar with creating and validating resources, I recommend reviewing the earlier articles in this series before proceeding. By the end of this article, you'll understand what FHIR profiles are and how to create profile-compliant resources for Canadian healthcare systems.
What Are FHIR Profiles?
A FHIR profile is a set of constraints and extensions applied to a base FHIR resource. Think of the base FHIR specification as a flexible template that covers the broadest possible use cases. Profiles narrow down this template to meet specific needs while maintaining interoperability.
Profiles can:
- Mark optional elements as required (cardinality constraints)
- Restrict the allowed values for coded elements (value set bindings)
- Add extensions for data elements not in the base specification
- Remove elements that aren't needed for a particular use case
- Provide additional documentation and guidance
Profiles are formally defined using StructureDefinition resources and are identified by a canonical URL. When a resource claims conformance to a profile, it includes that profile's URL in the meta.profile element.
Understanding Profile Hierarchies and Implementation Guides
Profiles exist within a hierarchy, with each level adding more specific constraints while maintaining compatibility with the levels above.
Profile Hierarchy
Canadian FHIR implementations typically follow this hierarchy:
Each level inherits all constraints from above and may add additional ones. A resource that conforms to a provincial profile automatically conforms to CA Core and base FHIR.
Extensions: Adding Canadian-Specific Data
FHIR extensions allow adding data elements not defined in the base specification. Extensions are critical for Canadian implementations:
Standard Extensions - Defined by HL7 and widely adopted:
- Part of the FHIR specification or published implementation guides
- Have well-defined semantics and canonical URLs
- Example:
http://hl7.org/fhir/StructureDefinition/patient-birthPlace
Canadian Extensions - Defined by Canada Health Infoway:
- Address Canadian-specific requirements
- Published as part of CA Core
- Example extensions might include Indigenous status, preferred pharmacy, etc.
Custom/Local Extensions - Defined by organizations:
- Should be registered to avoid conflicts
- Must have a StructureDefinition
- Should be documented in local implementation guides
// Example: Adding an extension to a Patient
Extension birthPlaceExt = new Extension();
birthPlaceExt.setUrl("http://hl7.org/fhir/StructureDefinition/patient-birthPlace");
birthPlaceExt.setValue(new Address()
.setCity("Ottawa")
.setState("ON")
.setCountry("CA"));
patient.addExtension(birthPlaceExt);
Canadian Terminology Bindings
Profiles specify which code systems and value sets must be used. Canadian implementations use specific terminology:
- SNOMED CT Canadian Edition - Clinical terminology with Canadian-specific content
- Canadian Drug Dictionary (CCDD) - Medications used in Canada
- pCLOCD - pan-Canadian LOINC Observation Code Database for lab results
- Canadian Clinical Drug Data Set - Drug product information
- PIPEDA Codes - Privacy and consent-related codes
Using the correct Canadian terminology ensures your data is meaningful and interoperable within the Canadian healthcare system.
Canada Health Infoway’s Role
Canada Health Infoway is the key organization driving FHIR adoption in Canada:
- Standards Development - Develops and publishes CA Core profiles
- Identifier Registries - Manages naming systems for provincial health numbers and other identifiers
- Implementation Guidance - Provides resources for implementing FHIR in Canada
- Conformance Testing - Offers tools and services for validating FHIR implementations
- Interoperability Programs - Coordinates pan-Canadian interoperability initiatives
The official CA Core Implementation Guide is available at: https://build.fhir.org/ig/HL7-Canada/ca-core/
Implementation Guides Structure
Implementation Guides (IGs) are comprehensive packages that include:
- StructureDefinitions - The profiles themselves (constraints on resources)
- ValueSets - Collections of codes that are valid for specific elements
- CodeSystems - Definitions of code systems (if custom)
- NamingSystem - Definitions of identifier systems (like provincial health numbers)
- SearchParameter - Custom search parameters
- CapabilityStatement - Expected server capabilities
- Examples - Sample resources showing proper usage
- Narrative Documentation - Human-readable guidance
When implementing against CA Core, you should download and include the IG package in your validation pipeline to ensure full conformance.
Prerequisites
Before you start, ensure your environment is ready:
- Java Development Kit (JDK) is installed and configured.
- Apache Maven is installed and set up for your project.
- HAPI FHIR Server is running and accessible.
- You can find all the code demonstrated in this tutorial on GitHub here
“The aim of argument, or of discussion, should not be victory, but progress.” ~ Joseph Joubert
Canadian Core FHIR Profiles
Canada Health Infoway has developed the CA Core (Canadian Core) FHIR profiles to support healthcare interoperability across Canada. These profiles provide Canadian-specific constraints and extensions on base FHIR resources, ensuring consistency across provincial healthcare systems.
Key aspects of Canadian FHIR profiles include:
- Provincial Health Numbers - Each province issues unique health identifiers with specific formats and naming systems
- Canadian Postal Codes - Address validation following the A1A 1A1 format
- Province/Territory Codes - Standard two-letter codes (ON, BC, QC, AB, SK, etc.)
- Bilingual Support - Communication preferences for English and French
- Professional Licensing - Provincial medical licensing identifiers
Provincial Health Number Systems
Canada's healthcare system is provincially administered, meaning each province issues its own health identifiers. Here are the naming system URIs for major provinces:
| Province | Health Number Name | Naming System URI | Format |
|---|---|---|---|
| Ontario | OHIP | ca-on-patient-hcn | 10 digits |
| British Columbia | PHN | ca-bc-patient-healthcare-id | 10 digits (starts with 9) |
| Quebec | NAM | ca-qc-patient-healthcare-id | 4 letters + 8 digits |
| Alberta | PHN | ca-ab-patient-healthcare-id | 9 digits |
| Saskatchewan | HSN | ca-sk-patient-healthcare-id | 9 digits |
Step 1 of 5: Import Required Classes and Define Constants
First, let's set up our imports and define the constants for Canadian profile URLs and identifier systems. This ensures consistency throughout your application.
package com.saravanansubramanian.fhir;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import org.hl7.fhir.common.hapi.validation.support.*;
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
import org.hl7.fhir.r4.model.*;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class FhirCanadianProfiles {
// Canadian identifier system URLs (from Canada Health Infoway)
private static final String ONTARIO_HEALTH_NUMBER_SYSTEM =
"https://fhir.infoway-inforoute.ca/NamingSystem/ca-on-patient-hcn";
private static final String BRITISH_COLUMBIA_PHN_SYSTEM =
"https://fhir.infoway-inforoute.ca/NamingSystem/ca-bc-patient-healthcare-id";
private static final String ALBERTA_PHN_SYSTEM =
"https://fhir.infoway-inforoute.ca/NamingSystem/ca-ab-patient-healthcare-id";
private static final String QUEBEC_NAM_SYSTEM =
"https://fhir.infoway-inforoute.ca/NamingSystem/ca-qc-patient-healthcare-id";
private static final String SASKATCHEWAN_PHN_SYSTEM =
"https://fhir.infoway-inforoute.ca/NamingSystem/ca-sk-patient-healthcare-id";
// Canadian profile URLs
private static final String CA_CORE_PATIENT_PROFILE =
"http://hl7.org/fhir/ca/core/StructureDefinition/profile-patient";
private static final String CA_CORE_PRACTITIONER_PROFILE =
"http://hl7.org/fhir/ca/core/StructureDefinition/profile-practitioner";
private static final String CA_CORE_ORGANIZATION_PROFILE =
"http://hl7.org/fhir/ca/core/StructureDefinition/profile-organization";
These constants define the official naming systems published by Canada Health Infoway. Using the correct system URI is essential for interoperability, as it allows other systems to recognize and properly interpret the identifiers.
“In the middle of difficulty lies opportunity.” ~ Albert Einstein
Step 2 of 5: Create a CA Core Patient with Ontario Health Number
Now let's create a Patient resource that conforms to the CA Core Patient profile. The key elements include setting the profile in metadata, using the correct provincial health number system, and following Canadian address conventions.
private static Patient createOntarioPatient() {
Patient patient = new Patient();
// Set CA Core Patient profile - this declares conformance to the profile
patient.getMeta().addProfile(CA_CORE_PATIENT_PROFILE);
// Add Ontario Health Number (OHIP) - Format: 10 digits
patient.addIdentifier()
.setSystem(ONTARIO_HEALTH_NUMBER_SYSTEM)
.setValue("1234567890")
.setType(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/v2-0203")
.setCode("JHN")
.setDisplay("Jurisdictional health number")))
.setUse(Identifier.IdentifierUse.OFFICIAL)
.setPeriod(new Period()
.setStart(parseDate("2020-01-01")));
// Add a secondary identifier (Medical Record Number)
patient.addIdentifier()
.setSystem("http://example.org/hospital/mrn")
.setValue("MRN-ON-12345")
.setType(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/v2-0203")
.setCode("MR")
.setDisplay("Medical record number")))
.setUse(Identifier.IdentifierUse.USUAL);
// Add patient name
patient.addName()
.setUse(HumanName.NameUse.OFFICIAL)
.setFamily("Tremblay")
.addGiven("Marie")
.addGiven("Claire")
.addPrefix("Ms.");
// Set demographics
patient.setGender(Enumerations.AdministrativeGender.FEMALE);
patient.setBirthDate(parseDate("1985-03-15"));
patient.setActive(true);
// Add Canadian address with proper formatting
patient.addAddress()
.setUse(Address.AddressUse.HOME)
.setType(Address.AddressType.PHYSICAL)
.addLine("123 Yonge Street")
.addLine("Unit 456")
.setCity("Toronto")
.setState("ON") // Canadian province code
.setPostalCode("M5B 1M4") // Canadian postal code format (A1A 1A1)
.setCountry("CA"); // ISO 3166 country code
// Add contact information
patient.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.PHONE)
.setValue("+1-416-555-0123")
.setUse(ContactPoint.ContactPointUse.HOME);
patient.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.EMAIL)
.setValue("[email protected]")
.setUse(ContactPoint.ContactPointUse.HOME);
// Add bilingual language support (English and French)
patient.addCommunication()
.setLanguage(new CodeableConcept()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("en-CA")
.setDisplay("English (Canada)")))
.setPreferred(true);
patient.addCommunication()
.setLanguage(new CodeableConcept()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("fr-CA")
.setDisplay("French (Canada)")));
return patient;
}
// Helper method to parse date strings
private static Date parseDate(String dateString) {
LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE);
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
Notice how the profile URL is set in the meta.profile element using the fluent API. This declares that the resource conforms to the CA Core Patient profile. The identifier type code "JHN" (Jurisdictional health number) indicates this is a government-issued health identifier.
Step 3 of 5: Create Patients for Different Provinces
Each Canadian province has its own health number format and naming conventions. Let's create patients for Quebec and British Columbia to demonstrate the differences.
private static Patient createQuebecPatient() {
Patient patient = new Patient();
// Set CA Core Patient profile
patient.getMeta().addProfile(CA_CORE_PATIENT_PROFILE);
// Add Quebec NAM - Format: 4 letters + 8 digits (e.g., DUBO75010112)
// The format encodes: first 4 letters of surname + birth date info
patient.addIdentifier()
.setSystem(QUEBEC_NAM_SYSTEM)
.setValue("DUBO75010112")
.setType(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/v2-0203")
.setCode("JHN")
.setDisplay("Jurisdictional health number")))
.setUse(Identifier.IdentifierUse.OFFICIAL);
// Add patient name (French name)
patient.addName()
.setUse(HumanName.NameUse.OFFICIAL)
.setFamily("Dubois")
.addGiven("Jean-Pierre")
.addPrefix("M."); // French honorific
patient.setGender(Enumerations.AdministrativeGender.MALE);
patient.setBirthDate(parseDate("1975-01-01"));
patient.setActive(true);
// Add Quebec address with French street name
patient.addAddress()
.setUse(Address.AddressUse.HOME)
.setType(Address.AddressType.PHYSICAL)
.addLine("456 Rue Sainte-Catherine Ouest")
.setCity("Montreal")
.setState("QC") // Quebec province code
.setPostalCode("H3B 1A2")
.setCountry("CA");
patient.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.PHONE)
.setValue("+1-514-555-0145")
.setUse(ContactPoint.ContactPointUse.HOME);
// Quebec patient - French as preferred language
patient.addCommunication()
.setLanguage(new CodeableConcept()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("fr-CA")
.setDisplay("French (Canada)")))
.setPreferred(true);
return patient;
}
private static Patient createBritishColumbiaPatient() {
Patient patient = new Patient();
// Set CA Core Patient profile
patient.getMeta().addProfile(CA_CORE_PATIENT_PROFILE);
// Add BC Personal Health Number (PHN) - Format: 10 digits starting with 9
patient.addIdentifier()
.setSystem(BRITISH_COLUMBIA_PHN_SYSTEM)
.setValue("9876543210")
.setType(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/v2-0203")
.setCode("JHN")
.setDisplay("Jurisdictional health number")))
.setUse(Identifier.IdentifierUse.OFFICIAL);
// Add patient name
patient.addName()
.setUse(HumanName.NameUse.OFFICIAL)
.setFamily("Wong")
.addGiven("David")
.addGiven("Chen");
patient.setGender(Enumerations.AdministrativeGender.MALE);
patient.setBirthDate(parseDate("1978-08-22"));
patient.setActive(true);
// Add British Columbia address
patient.addAddress()
.setUse(Address.AddressUse.HOME)
.setType(Address.AddressType.PHYSICAL)
.addLine("789 Granville Street")
.setCity("Vancouver")
.setState("BC") // British Columbia
.setPostalCode("V6Z 1K3")
.setCountry("CA");
patient.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.PHONE)
.setValue("+1-604-555-0199")
.setUse(ContactPoint.ContactPointUse.MOBILE);
// Add multiple language capabilities
patient.addCommunication()
.setLanguage(new CodeableConcept()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("en-CA")
.setDisplay("English (Canada)")))
.setPreferred(true);
// BC has a significant Chinese-speaking population
patient.addCommunication()
.setLanguage(new CodeableConcept()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("zh-Hans")
.setDisplay("Chinese (Simplified)")));
return patient;
}
Each province has unique characteristics reflected in the patient data. Quebec uses French names and addresses with "M." as a prefix instead of "Mr.", while British Columbia addresses the multicultural nature of its population with support for multiple languages.
“The secret of change is to focus all of your energy not on fighting the old, but on building the new.” ~ Socrates
Step 4 of 5: Create a CA Core Practitioner
Healthcare practitioners in Canada are licensed by provincial regulatory bodies. The CA Core Practitioner profile includes support for provincial licensing identifiers and professional qualifications.
private static Practitioner createCanadianPractitioner() {
Practitioner practitioner = new Practitioner();
// Set CA Core Practitioner profile
practitioner.getMeta().addProfile(CA_CORE_PRACTITIONER_PROFILE);
// Add College of Physicians and Surgeons of Ontario (CPSO) license number
practitioner.addIdentifier()
.setSystem("https://fhir.infoway-inforoute.ca/NamingSystem/ca-on-license-physician")
.setValue("12345")
.setType(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/v2-0203")
.setCode("MD")
.setDisplay("Medical License Number")))
.setUse(Identifier.IdentifierUse.OFFICIAL)
.setPeriod(new Period()
.setStart(parseDate("2010-06-15")));
// Add practitioner name with credentials
practitioner.addName()
.setUse(HumanName.NameUse.OFFICIAL)
.setFamily("Singh")
.addGiven("Priya")
.addPrefix("Dr.")
.addSuffix("MD, FRCPC"); // Fellow of Royal College of Physicians
practitioner.setGender(Enumerations.AdministrativeGender.FEMALE);
practitioner.setActive(true);
// Add work address
practitioner.addAddress()
.setUse(Address.AddressUse.WORK)
.setType(Address.AddressType.PHYSICAL)
.addLine("200 University Avenue")
.setCity("Toronto")
.setState("ON")
.setPostalCode("M5G 1V2")
.setCountry("CA");
// Add contact information
practitioner.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.PHONE)
.setValue("+1-416-555-0200")
.setUse(ContactPoint.ContactPointUse.WORK);
practitioner.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.EMAIL)
.setValue("[email protected]")
.setUse(ContactPoint.ContactPointUse.WORK);
// Add medical qualifications
practitioner.addQualification()
.setCode(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/v2-0360")
.setCode("MD")
.setDisplay("Doctor of Medicine")))
.setIssuer(new Reference().setDisplay("University of Toronto"))
.setPeriod(new Period()
.setStart(parseDate("2008-05-15")));
// Add specialty qualification (FRCPC - Fellow of Royal College)
practitioner.addQualification()
.setCode(new CodeableConcept()
.addCoding(new Coding()
.setSystem("http://snomed.info/sct")
.setCode("394802001")
.setDisplay("General medicine")))
.setIssuer(new Reference()
.setDisplay("Royal College of Physicians and Surgeons of Canada"))
.setPeriod(new Period()
.setStart(parseDate("2010-06-15")));
// Add language capabilities (multilingual practitioner)
practitioner.addCommunication()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("en-CA")
.setDisplay("English (Canada)"));
practitioner.addCommunication()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("hi")
.setDisplay("Hindi"));
practitioner.addCommunication()
.addCoding(new Coding()
.setSystem("urn:ietf:bcp:47")
.setCode("pa")
.setDisplay("Punjabi"));
return practitioner;
}
The practitioner example demonstrates several Canadian-specific elements: the CPSO (College of Physicians and Surgeons of Ontario) licensing system, the FRCPC credential from the Royal College of Physicians and Surgeons of Canada, and support for multiple languages reflecting Canada's multicultural population.
Step 5 of 5: Create a CA Core Organization and Submit Resources
Healthcare organizations in Canada also follow specific identification patterns. Let's create an organization and then submit our resources to a FHIR server.
private static Organization createCanadianOrganization() {
Organization organization = new Organization();
// Set CA Core Organization profile
organization.getMeta().addProfile(CA_CORE_ORGANIZATION_PROFILE);
// Add Canadian Organization Identifier from Infoway
organization.addIdentifier()
.setSystem("https://fhir.infoway-inforoute.ca/NamingSystem/ca-on-organization-id")
.setValue("12345678")
.setUse(Identifier.IdentifierUse.OFFICIAL);
// Add organization name
organization.setName("Toronto General Hospital");
// Add aliases (alternative names)
organization.addAlias("TGH");
organization.addAlias("University Health Network - Toronto General");
// Set organization type
organization.addType()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/organization-type")
.setCode("prov")
.setDisplay("Healthcare Provider"));
organization.addType()
.addCoding(new Coding()
.setSystem("http://terminology.hl7.org/CodeSystem/organization-type")
.setCode("team")
.setDisplay("Organizational Team"))
.setText("Teaching Hospital");
organization.setActive(true);
// Add address
organization.addAddress()
.setUse(Address.AddressUse.WORK)
.setType(Address.AddressType.PHYSICAL)
.addLine("200 Elizabeth Street")
.setCity("Toronto")
.setState("ON")
.setPostalCode("M5G 2C4")
.setCountry("CA");
// Add contact information
organization.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.PHONE)
.setValue("+1-416-340-4800")
.setUse(ContactPoint.ContactPointUse.WORK);
organization.addTelecom()
.setSystem(ContactPoint.ContactPointSystem.URL)
.setValue("https://www.uhn.ca/TorontoGeneral")
.setUse(ContactPoint.ContactPointUse.WORK);
return organization;
}
public static void main(String[] args) {
String fhirServerUrl = "http://hapi.fhir.org/baseR4";
System.out.println("FHIR Java SDK - Canadian FHIR Profiles Tutorial");
System.out.println("================================================");
try {
// Initialize FHIR context for R4
FhirContext ctx = FhirContext.forR4();
IGenericClient client = ctx.newRestfulGenericClient(fhirServerUrl);
// Create Canadian patients
Patient ontarioPatient = createOntarioPatient();
Patient quebecPatient = createQuebecPatient();
Patient bcPatient = createBritishColumbiaPatient();
// Create practitioner and organization
Practitioner practitioner = createCanadianPractitioner();
Organization organization = createCanadianOrganization();
// Validate resources locally
System.out.println("\nValidating Canadian Resources...");
ValidationSupportChain validationSupportChain = new ValidationSupportChain(
new DefaultProfileValidationSupport(ctx),
new InMemoryTerminologyServerValidationSupport(ctx),
new CommonCodeSystemsTerminologyService(ctx)
);
FhirValidator validator = ctx.newValidator();
FhirInstanceValidator instanceValidator = new FhirInstanceValidator(validationSupportChain);
validator.registerValidatorModule(instanceValidator);
ValidationResult result = validator.validateWithResult(ontarioPatient);
System.out.println("Ontario Patient validation: " + (result.isSuccessful() ? "PASSED" : "FAILED"));
// Submit resources to FHIR server
System.out.println("\nSubmitting resources to FHIR server...");
MethodOutcome outcome = client.create().resource(ontarioPatient).execute();
if (outcome.getId() != null) {
System.out.println("Ontario Patient created with ID: " + outcome.getId().getIdPart());
}
// Search for patients by provincial health number
System.out.println("\nSearching for patients with Ontario health numbers...");
Bundle searchResults = client.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.hasSystemWithAnyCode(ONTARIO_HEALTH_NUMBER_SYSTEM))
.returnBundle(Bundle.class)
.execute();
System.out.println("Found " + searchResults.getTotal() + " patients.");
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
System.out.println("\nTutorial completed.");
}
Canadian FHIR Profile Best Practices
When working with Canadian FHIR profiles, follow these best practices to ensure interoperability and compliance:
- Always use the appropriate provincial health number system URI - Each province has its own naming system URL published by Infoway
- Use Canadian postal code format (A1A 1A1) - Include the space between the two halves
- Reference CA Core profile URLs in meta.profile - This declares your resource's conformance to the profile
- Use standard Canadian province/territory codes - Use two-letter codes: ON, BC, QC, AB, SK, MB, NS, NB, PE, NL, NT, YT, NU
- Include language preferences - Support for both English (en-CA) and French (fr-CA) is important for Canadian healthcare
- Follow Infoway's pan-Canadian standards - Consult the official CA Core implementation guide for detailed requirements
- Validate resources against CA Core profiles before production use - Use the validation techniques covered in earlier tutorials
Conclusion
In this article, we've explored FHIR profiles using Canadian Core profiles as practical examples. You've learned what profiles are and how they constrain base FHIR resources, how Canadian Core profiles support provincial health systems, how to create profile-compliant resources for patients, practitioners, and organizations, and best practices for working with Canadian FHIR implementations.
Profiles are essential for real-world FHIR implementations because they bridge the gap between FHIR's flexibility and the specific requirements of healthcare jurisdictions. By understanding how to work with profiles like CA Core, you're well-equipped to build interoperable healthcare applications that work within Canada's healthcare ecosystem.
The complete code for this tutorial is available on GitHub. For more information on Canadian FHIR profiles, visit the CA Core Implementation Guide.
This concludes the FHIR programming series using Java. Throughout this series, we've covered everything from setting up your environment, through CRUD operations, searching, validation, chaining operations, advanced topics including use of profiles in FHIR, security best practices, and finally building a SMART on FHIR application. You now have a comprehensive foundation for building robust, secure, and interoperable healthcare applications using FHIR and Java. Thank you for following along!