Top Banner
© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office. HAPI-FHIR for Java Developers James Agnew FHIR Developer Days November 16, 2016
82

hapi fhir java beginner and advanced for dev days

Jan 25, 2017

Download

Healthcare

DevDays
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI-FHIR for Java Developers

James AgnewFHIR Developer DaysNovember 16, 2016

Page 2: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Who am I?

● Name: James Agnew● Company: Centre for Global eHealth Innovation (University Health Network)

● Background:● Software Development Manager● Project lead for HAPI for 11 years

2

Page 3: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

About this Presentation

● All code samples are available on GitHub in fully working form

https://github.com/furore-fhir/fhirstarters

● HAPI is too big a topic for 45 minutesso…● I will be around! Let’s talk!

3

Page 4: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Show of Hands

● Who here is new to FHIR?● Who here is new to HAPI FHIR?

Page 5: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR: A Quick Recap

● There are two key parts of FHIR to consider:● The first is a data model for healthcare Resources

and supporting Datatypes

5

Page 6: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● The second is a RESTful API for interacting with that model

6

FHIR: A Quick Recap (2)

Page 7: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● FHIR has had several releases● FHIR DSTU1 (Released 2014)● FHIR DSTU2 (Released 2015)● FHIR STU3 (Will be released early 2017?)

● This presentation focuses on STU3 but the concepts apply to all versions

7

FHIR: A Quick Recap (3)

Page 8: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

The HAPI Project

● HAPI started in 2001 as an HL7 v2 Library● Built to support a simple web portal, now used

in applications around the world

HL7 v2 - http://hl7api.sourceforge.net FHIR - http://hapifhir.io

8

Page 9: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR: What is it?

● Not a client or a server, but a toolkit for building either

9

Page 10: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR: Why did we build it?● Two use cases at our hospital:

● As a unified clinical data access layer● As a backend for our mobile apps

10

Page 11: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR in Java

● HAPI is now the Java Reference Implementation● Many RI features are “copied in” for each release

11

Page 12: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Design Goals

● Use Anywhere● Apache 2.0 License for all components● Minimal dependencies

● Be Flexible● Loosely coupled, pluggable components

● Be Powerful● “Steal” all the best ideas from existing frameworks:

JAX-WS, Springframework, .NET FHIR API ☺..etc..

12

Page 13: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

ComponentsHAPI FHIR Modules

Page 14: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Today (Beginner)Tomorrow (Advanced)

Page 15: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Structures Classes:The FHIR Model

Page 16: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Structures Classes:The FHIR Model

● HAPI supports multiple versions of FHIR via different “structures JARs”

hapi-fhir-structures-dstu-2.1.jar

hapi-fhir-structures-dstu2-2.1.jar

hapi-fhir-structures-dstu3-2.1.jar

FHIR Version HAPI Version

ca.uhn.fhir.model.dstu.resources.Patient

ca.uhn.fhir.model.dstu2.resources.Patient

org.hl7.fhir.dstu3.model.Patient

Patient Resource ModelsPatient Resource ModelsPatient Resource Models

Page 17: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Structures Classes:The FHIR Model

● HAPI Defines several sets of classes which form the data model

● Resource definition classes implement IBaseResource

● Examples: Patient, CarePlan, Encounter, Practitioner, Medication

17

Page 18: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Structures Classes: The FHIR Model (2)

● HAPI also defines a class for each data type

● Primitive classes are named [name]Type

● Primitive types include: StringType, BooleanType

● Composite types include: Address, Ratio, HumanName

18

Page 19: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Structures Classes: The FHIR Model (3)

● JavaDocs for structures are available here: http://hapifhir.io/apidocs-dstu3/index.html

19

Page 20: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Using the Structures:Creating a Resource

20

1: public class Example01_CreateAPatient { 2: public static void main(String[] theArgs) { 3: // Create a resource instance 4: Patient pat = new Patient(); 5: 6: // Add a "name" element 7: HumanName name = pat.addName(); 8: name.addFamily("Simpson").addGiven("Homer").addGiven("J"); 9: 10: // Add an "identifier" element11: Identifier identifier = pat.addIdentifier();12: identifier.setSystem("http://acme.org/MRNs").setValue("7000135");13: 14: // Model is designed to be chained15: pat.addIdentifier().setSystem("http://acme.org/MRNs").setValue("12345");16: }17: }

Page 21: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

1: public class Example01_CreateAPatient { 2: public static void main(String[] theArgs) { 3: // Create a resource instance 4: Patient pat = new Patient(); 5: 6: // Add a "name" element 7: HumanName name = pat.addName(); 8: name.addFamily("Simpson").addGiven("Homer").addGiven("J"); 9: 10: // Add an "identifier" element11: Identifier identifier = pat.addIdentifier();12: identifier.setSystem("http://acme.org/MRNs").setValue("7000135");13: 14: // Model is designed to be chained15: pat.addIdentifier().setSystem("http://acme.org/MRNs").setValue("12345");16: }17: }

Using the Structures:Use the Autocomplete!

21

Page 22: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Using the Structures:Enumerated Types

22

1: public class Example02_EnumeratedTypes { 2: public static void main(String[] theArgs) { 3: 4: Patient pat = new Patient(); 5: 6: pat.addName().addFamily("Simpson").addGiven("Homer").addGiven("J"); 7: pat.addIdentifier().setSystem("http://acme.org/MRNs").setValue("7000135"); 8: 9: // Enumerated types are provided for many coded elements10: ContactPoint contact = pat.addTelecom();11: contact.setUse(ContactPointUse.HOME);12: contact.setSystem(ContactPointSystem.PHONE);13: contact.setValue("1 (416) 340-4800");14: 15: pat.setGender(AdministrativeGender.MALE);16: }17: }

Page 23: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Using the Structures:Add Extensions

23

1: public class Example03_AddSomeExtensions { 2: public static void main(String[] theArgs) { 3: Patient pat = new Patient(); 4: pat.addName().addFamily("Simpson").addGiven("Homer").addGiven("J"); 5: 6: // Add an extension on the resource 7: pat.addExtension() 8: .setUrl("http://hl7.org/fhir/StructureDefinition/patient-importance") 9: .setValue(new CodeableConcept().setText("Patient is a VIP"));10: 11: // Add an extension on a primitive12: pat.getBirthDateElement().setValueAsString("1955-02-22");13: pat.getBirthDateElement().addExtension()14: .setUrl("http://hl7.org/fhir/StructureDefinition/patient-birthTime")15: .setValue(new TimeType("23:30"));16: }17: }

Page 24: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Parsers:Serializing & Deserializing

Page 25: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Playing with Parsers

25

● The starting point for much of the HAPI-FHIR API is the FhirContext class

● FhirContext acts as a factory for the rest of the API, including the two parsers:● XmlParser● JsonParser

● FhirContext is designed to be created once and reused (important for performance!)

Page 26: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Playing with Parsers:Encoding Resources

26

1: public class Example04_EncodeResource { 2: public static void main(String[] theArgs) { 3: 4: // Create a Patient 5: Patient pat = new Patient(); 6: pat.addName().addFamily("Simpson").addGiven("Homer").addGiven("J"); 7: pat.addIdentifier().setSystem("http://acme.org/MRNs").setValue("7000135"); 8: pat.addTelecom().setSystem(ContactPointSystem.PHONE).setValue("1 (416) 340-4800"); 9: pat.setGender(AdministrativeGender.MALE);10: 11: // Create a context12: FhirContext ctx = FhirContext.forDstu3();13: 14: // Create a XML parser15: IParser parser = ctx.newJsonParser();16: parser.setPrettyPrint(true);17: 18: String encode = parser.encodeResourceToString(pat);19: System.out.println(encode);20: 21: }22: }

Page 27: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Playing with Parsers:Encoding Resources (2)

27

// Create a contextFhirContext ctx = FhirContext.forDstu3();

// Create a XML parserIParser parser = ctx.newJsonParser();parser.setPrettyPrint(true);

String encode = parser .encodeResourceToString(pat);System.out.println(encode);

1: { 2: "resourceType": "Patient", 3: "identifier": [ { 4: "system": "http://acme.org/MRNs", 5: "value": "7000135" 6: } ], 7: "name": [ { 8: "family": [ "Simpson" ], 9: "given": [ "Homer", "J" ]10: } ],11: "telecom": [ {12: "system": "phone",13: "value": "1 (416) 340-4800",14: "use": "home"15: } ],16: "gender": "male"17: }

Page 28: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Playing with Parsers:Parsing Resources

28

1: public class Example05_ParseResource { 2: public static void main(String[] theArgs) { 3: String resourceBody = "{\"resourceType\":\"Patient\",\"identifier\":[{\"system\":\"http://acme.org/MRNs\",\"value\":\"7000135\"}],\"name\":[{\"family\":[\"Simpson\"],\"given\":[\"Homer\",\"J\"]}]}"; 4: 5: // Create a context 6: FhirContext ctx = FhirContext.forDstu3(); 7: 8: // Create a JSON parser 9: IParser parser = ctx.newJsonParser();10: Patient pat = parser.parseResource(Patient.class, resourceBody);11: 12: List<Identifier> identifiers = pat.getIdentifier();13: String idSystemString = identifiers.get(0).getSystem();14: String idValueString = identifiers.get(0).getValue();15: 16: System.out.println(idSystemString + " " + idValueString);17: }18: } http://acme.org/MRNs - 7000135

Page 29: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Clients:Moving Data Around

Page 30: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Clients:Recap on REST● FHIR defines basic CRUD operations that

can be performed on a FHIR compliant server (*not a complete list)

30

Name HTTP URL

type create POST http://base/[type]

instance read GET http://base/[type]/[id]

instance update PUT http://base/[type]/[id]

instance delete DELETE http://base/[type]/[id]

type search GET http://base/[type]?[params]

Page 31: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Clients:Basic CRUD - Create

31

1: public class Example06_ClientCreate { 2: public static void main(String[] theArgs) { 3: Patient pat = new Patient(); 4: pat.addName().addFamily("Simpson").addGiven("Homer").addGiven("J"); 5: pat.addIdentifier().setSystem("http://acme.org/MRNs").setValue("7000135"); 6: pat.setGender(AdministrativeGender.MALE); 7: 8: // Create a context 9: FhirContext ctx = FhirContext.forDstu3();10: 11: // Create a client12: String serverBaseUrl = "http://fhirtest.uhn.ca/baseDstu3";13: IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);14: 15: // Use the client to store a new resource instance 16: MethodOutcome outcome = client.create().resource(pat).execute();17: 18: // Print the ID of the newly created resource19: System.out.println(outcome.getId());20: }21: } http://fhirtest.uhn.ca/base/Patient/4529/_history/1

Page 32: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

1: public class Example07_ClientReadAndUpdate { 2: public static void main(String[] theArgs) { 3: // Create a client 4: String serverBaseUrl = "http://fhirtest.uhn.ca/baseDstu3"; 5: FhirContext ctx = FhirContext.forDstu3(); 6: IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl); 7: 8: // Use the client to read back the new instance using the ID 9: Patient patient = client.read(Patient.class, "190002");10: 11: // Print the ID of the newly created resource12: System.out.println("Found ID: " + patient.getId());13: 14: // Change the gender and send an update to the server15: patient.setGender(AdministrativeGender.FEMALE);16: MethodOutcome outcome = client.update().resource(patient).execute();17: 18: System.out.println("Now have ID: " + outcome.getId());19: }20: }

FHIR Clients:Basic CRUD - Read/Update

http://fhirtest.uhn.ca/base/Patient/190002/_history/2

http://fhirtest.uhn.ca/base/Patient/190002/_history/1

Page 33: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● FHIR defines a powerful search mechanism● Searches are specially crafted URLs to

express queries such as:● Find a Patient with the given Identifier● Find all Patients with given gender and

DOB● Find all lab reports for a given patient

identifier with an “abnormal” interpretation33

FHIR Clients:Searching

Page 34: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● Searching is powerful! Learn about it athttp://hl7.org/fhir/search.html

● For now, let’s imagine a search for a Patient named “Test” whose birthdate is before 2014

34

FHIR Clients:Searching (2)

=

Page 35: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

1: public class Example08_ClientSearch { 2: public static void main(String[] theArgs) { 3: FhirContext ctx = FhirContext.forDstu3(); 4: IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu3"); 5: 6: // Log requests and responses (very verbose for testing!) 7: client.registerInterceptor(new LoggingInterceptor(true)); 8: 9: // Build a search and execute it10: Bundle response = client.search()11: .forResource(Patient.class)12: .where(Patient.NAME.matches().value("Test"))13: .and(Patient.BIRTHDATE.before().day("2014-01-01"))14: .count(100)15: .returnBundle(Bundle.class)16: .execute();17: 18: // How many resources did we find?19: System.out.println("Responses: " + response.getTotal());20: 21: // Print the ID of the first one22: System.out.println(response.getEntry().get(0).getResource().getId());23: }24: }

FHIR Clients:Searching (3)

http://fhirtest.uhn.ca/baseDstu3/Patient/82599/_history/1

27

Page 36: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

9: // Build a search and execute it10: Bundle response = client.search()11: .forResource(Patient.class)12: .where(Patient.NAME.matches().value("Test"))13: .and(Patient.BIRTHDATE.before().day("2014-01-01"))14: .count(100)15: .returnBundle(Bundle.class)16: .execute();

FHIR Clients:Searching (4)

36

Many more available options for searching!

See:http://hapifhir.io/doc_rest_client.html#SearchQuery_-_Type

Page 37: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Clients:Lots More● You can follow a similar pattern to do many

more operations:● Delete, Validate, History, Tags, etc…

● Client logging interceptor can be very helpful● http://hapifhir.io/hapi-fhir/doc_rest_client_interceptor.html#Lo

gging:_Log_Requests_and_Responses

37

Page 38: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server in a boxhapi-fhir-cli

Page 39: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Questions?

We will cover more tomorrow at HAPI Advanced Tutorial. Any requests?

Page 40: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI-FHIR for Java Developers -

AdvancedJames Agnew

FHIR Developer DaysNovember 17, 2016

Page 41: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Today’s Agenda

We will cover more tomorrow at HAPI Advanced Tutorial

Page 42: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Validation

Page 43: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Error checking vs Validation in HAPIError Checking during Parsing (learn more: hapifhir.io)

● Parser can be configured with an “Error Handler” which logs or fails on error

● Only catches structural issues

43

Validation

(our focus for today)

● Applies a complete set of rules to a resource instance

● Currently far more powerful

Page 44: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Validation in FHIR

Schema (XSD) and Schematron (SCH)

● Uses XSD+SCH files● Covers base FHIR

specification● XML validation only

(HAPI will convert)● Simpler to use

44

Profile Validation

● Uses FHIR resources:● StructureDefinition● ValueSet / CodeSystem

● Native JSON/XML support

● Profile validation● Slicing validation● Terminology

validation

Page 45: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Validation in HAPI

● HAPI’s validator uses modules and collects the results from any that are enabled

● Create your own if you want!

Page 46: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Schema/Schematron Validation

Dependencies:● hapi-fhir-validation-resources-dstu3-2.1.jar● phloc-schematron-2.7.0.jar

Inputs (pick one):● Resource Java model object● Raw JSON Resource● Raw XML Resource

Page 47: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Using Schema Validator1: public class Example09_ValidateResource { 2: public static void main(String[] args) { 3: 4: // Create an incomplete encounter (status is required) 5: Encounter enc = new Encounter(); 6: enc.addIdentifier().setSystem("http://acme.org/encNums").setValue("12345"); 7: 8: // Create a new validator 9: FhirContext ctx = FhirContext.forDstu3();10: FhirValidator validator = ctx.newValidator();11: 12: // Did we succeed?13: ValidationResult result = validator.validateWithResult(enc);14: System.out.println("Success: " + result.isSuccessful());15: 16: // What was the result17: OperationOutcome outcome = (OperationOutcome) result.toOperationOutcome();18: IParser parser = ctx.newXmlParser().setPrettyPrint(true);19: System.out.println(parser.encodeResourceToString(outcome));20: }22: }

Page 48: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Using Schema Validator1: public class Example09_ValidateResource { 2: public static void main(String[] args) { 3: 4: // Create an incomplete encounter (status is required) 5: Encounter enc = new Encounter(); 6: enc.addIdentifier().setSystem("http://acme.org/encNums").setValue("12345"); 7: 8: // Create a new validator 9: FhirContext ctx = FhirContext.forDstu3();10: FhirValidator validator = ctx.newValidator();11: 12: // Did we succeed?13: ValidationResult result = validator.validateWithResult(enc);14: System.out.println("Success: " + result.isSuccessful());15: 16: // What was the result17: OperationOutcome outcome = (OperationOutcome) result.toOperationOutcome();18: IParser parser = ctx.newXmlParser().setPrettyPrint(true);19: System.out.println(parser.encodeResourceToString(outcome));20: }22: }

<OperationOutcome xmlns="http://hl7.org/fhir"> <issue> <severity value="error"/> <code value="processing"/> <diagnostics value="cvc-complex-type.2.4.b: The content of element 'Encounter' is not complete. One of '{&quot;http://hl7.org/fhir&quot;:identifier, &quot;http://hl7.org/fhir&quot;:status}' is expected."/> <location value="Line[1] Col[140]"/> </issue></OperationOutcome>

false

Page 49: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Using Schema Validator with String input

1: public class Example10_ValidateResourceString { 2: public static void main(String[] args) { 3: 4: String input = "<Encounter xmlns=\"http://hl7.org/fhir\"></Encounter>"; 5: 6: // Create a new validator 7: FhirContext ctx = FhirContext.forDstu3(); 8: FhirValidator validator = ctx.newValidator(); 9: 10: // Did we succeed?11: ValidationResult result = validator.validateWithResult(input);12: System.out.println("Success: " + result.isSuccessful());13: 14: // What was the result15: OperationOutcome outcome = (OperationOutcome) result.toOperationOutcome();16: IParser parser = ctx.newXmlParser().setPrettyPrint(true);17: System.out.println(parser.encodeResourceToString(outcome));18: }19: }

String is also fine as input

Page 50: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Profile Validation

● FhirInstanceValidator module requires an instance of IValidationSupport

● Several implementations are supplied with HAPI FHIR

● You can also create your own

Page 51: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Profile Validation

Use built-in FHIR definitions and terminology

Load your own definitions and terminology

Chain multiple providers together

Page 52: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Profile Validation1: public class Example11_ValidateResourceInstanceValidator { 2: public static void main(String[] args) { 3: // Create an incomplete encounter (status is required) 4: Encounter enc = new Encounter(); 5: enc.addIdentifier().setSystem("http://acme.org/encNums").setValue("12345"); 6: 7: // Create a new validator 8: FhirValidator validator = FhirContext.forDstu3().newValidator(); 9: 10: // Cache this! Supplies structure definitions11: DefaultProfileValidationSupport support = new DefaultProfileValidationSupport();12: 13: // Create the validator14: FhirInstanceValidator module = new FhirInstanceValidator(support);15: validator.registerValidatorModule(module);16: 17: // Did we succeed?18: IParser parser = FhirContext.forDstu3().newXmlParser().setPrettyPrint(true);19: System.out.println(parser.encodeResourceToString(validator.validateWithResult(enc).toOperationOutcome()));20: }21: }

Page 53: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Profile Validation1: public class Example11_ValidateResourceInstanceValidator { 2: public static void main(String[] args) { 3: // Create an incomplete encounter (status is required) 4: Encounter enc = new Encounter(); 5: enc.addIdentifier().setSystem("http://acme.org/encNums").setValue("12345"); 6: 7: // Create a new validator 8: FhirValidator validator = FhirContext.forDstu3().newValidator(); 9: 10: // Cache this! Supplies structure definitions11: DefaultProfileValidationSupport support = new DefaultProfileValidationSupport();12: 13: // Create the validator14: FhirInstanceValidator module = new FhirInstanceValidator(support);15: validator.registerValidatorModule(module);16: 17: // Did we succeed?18: IParser parser = FhirContext.forDstu3().newXmlParser().setPrettyPrint(true);19: System.out.println(parser.encodeResourceToString(validator.validateWithResult(enc).toOperationOutcome()));20: }21: }

13:25:41.843 INFO Loading structure definitions from classpath: /org/hl7/fhir/instance/model/dstu3/profile/profiles-resources.xml13:25:43.962 INFO Loading structure definitions from classpath: /org/hl7/fhir/instance/model/dstu3/profile/profiles-types.xml13:25:44.085 INFO Loading structure definitions from classpath: /org/hl7/fhir/instance/model/dstu3/profile/profiles-others.xml

<OperationOutcome xmlns="http://hl7.org/fhir"> <issue> <severity value="error"/> <code value="processing"/> <diagnostics value="Profile http://hl7.org/fhir/StructureDefinition/Encounter, Element 'Encounter.status': minimum required = 1, but only found 0"/> <location value="Encounter"/> </issue></OperationOutcome>

LoadingProfiles

Friendly Errors

Page 54: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Creating a Server

Page 55: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server: Architecture

● HAPI provides a REST Server framework● Based on standard JEE/Servlet 2.5+

(Tomcat, Glassfish, Websphere, JBoss, etc)● Inspired by (but not based on) JAX-RS, RestEasy,

Spring REST, etc.

55

Page 56: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server: Architecture (2)● Architecture is based

on “Resource Providers” which are custom classes you write to interact with your resources

● This is a “low level” API for building servers, not an “off the shelf” solution

56

Page 57: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server:Defining Resource Providers

● Resource Providers implement your server logic

57

1: public class Example01_StubResourceProvider implements IResourceProvider { 2: public Class<? extends IBaseResource> getResourceType() { 3: return Patient.class; 4: } 5: 6: @Read 7: public Patient read(@IdParam IdType theId) { return null; /* populate this */ }10: 11: @Create 12: void create(@ResourceParam Patient thePatient) { /* save the resource */ }15: 16: @Search17: List<Patient> search(18: @OptionalParam(name="family") StringParam theFamily,19: @OptionalParam(name="given") StringParam theGiven20: ) {21: return null; // populate this22: }23: }

Page 58: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● The following slides show a simple example building a FHIR server using HAPI

● Resources are stored in a HashMap (could just as easily be a database or something else!)

● These samples can be downloaded and executed on your laptop very easily

58

FHIR Server:A Simple Example

Page 59: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server:A simple resource provider

59

1: public class Example02_PatientResourceProvider implements IResourceProvider { 2: 3: private Map<String, Patient> myPatients = new HashMap<String, Patient>(); 4: 5: /** Constructor */ 6: public Example02_PatientResourceProvider() { 7: Patient pat1 = new Patient(); 8: pat1.setId("1"); 9: pat1.addIdentifier().setSystem("http://acme.com/MRNs").setValue("7000135");10: pat1.addName().addFamily("Simpson").addGiven("Homer").addGiven("J");11: myPatients.put("1", pat1);12: }13: 14: /** Simple implementation of the "read" method */15: @Read(version=false)16: public Patient read(@IdParam IdType theId) {17: Patient retVal = myPatients.get(theId.getIdPart());18: if (retVal == null) {19: throw new ResourceNotFoundException(theId);20: }21: return retVal;22: }23: 24: @Override25: public Class<? extends IBaseResource> getResourceType() {26: return Patient.class;27: }28: 29: 30: }

Page 60: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server:A simple server

60

1: @WebServlet("/*") 2: public class Example03_SimpleRestfulServer extends RestfulServer { 3: 4: @Override 5: protected void initialize() throws ServletException { 6: // Create a context for the appropriate version 7: setFhirContext(FhirContext.forDstu3()); 8: 9: // Register resource providers10: registerProvider(new Example02_PatientResourceProvider());11: }12: }

● The servlet is very simple: it creates an instance of each resource provider and declares the servlet path

Page 61: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● Console 1: Start Server

61

FHIR Server:Trying the server out

james$ mvn jetty:run[INFO] Scanning for projects...2014-11-21 12:27:37.622:WARN:oejsh.RequestLogHandler:main: !RequestLog2014-11-21 12:27:37.669:INFO:oejs.ServerConnector:main: Started ServerConnect[INFO] Started Jetty Server

● Console 2: Try it out!james$ curl “http://localhost:8080/Patient/1"<Patient xmlns="http://hl7.org/fhir"><identifier><system value="http://acme.com/MRNs"/><value value="7000135"/></identifier><name><family value="Simpson"/><given value="Homer"/><given value="J"/></name></Patient>

Page 62: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

62

FHIR Server:Trying the server out (2)

Page 63: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

63

1: public class Example04_PatientResourceProviderWithCreate implements IResourceProvider { 2: // ---- not all methods shown ---- 3: @Create 4: public MethodOutcome create(@ResourceParam Patient thePatient) { 5: // Give the resource the next sequential ID 6: int id = myNextId++; 7: thePatient.setId(new IdType(id)); 8: 9: // Store the resource in memory10: myPatients.put(Integer.toString(id), thePatient);11: 12: // Inform the server of the ID for the newly stored resource13: return new MethodOutcome().setId(thePatient.getIdElement());14: }15: 16: @Search17: public List<Patient> search() {18: List<Patient> retVal = new ArrayList<Patient>();19: retVal.addAll(myPatients.values());20: return retVal;21: }22: }

FHIR Server:Adding Create and Search

Page 64: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● The following command executes a ‘create’

64

curl -H "Content-Type: application/xml+fhir" \ -X POST \ -d '<Patient xmlns="http://hl7.org/fhir"><name><family value="Fireman"/><given value="John"/></name></Patient>' \ "http://localhost:8080/Patient"

FHIR Server:Testing out Create

curl "http://localhost:8080/Patient?_pretty=true"

[ … snip … ]<Bundle xmlns="http://hl7.org/fhir"> <type value="searchset"/> <total value="3"/>

● Now perform a search

Page 65: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

65

FHIR Server:Adding Search Params

https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-tutorial/simple-server

1: @Search 2: public List<Patient> search(@RequiredParam(name = Patient.SP_FAMILY) StringParam theParam) { 3: List<Patient> retVal = new ArrayList<Patient>(); 4: 5: // Loop through the patients looking for matches 6: for (Patient next : myPatients.values()) { 7: String familyName = next.getNameFirstRep().getFamilyAsSingleString().toLowerCase(); 8: if (familyName.contains(theParam.getValue().toLowerCase()) == false) { 9: continue;10: }11: retVal.add(next);12: }13: 14: return retVal;15: }

“family”

Page 66: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

FHIR Server:Much more is available● Combining multiple parameters● Parameters for sorting, limiting, paging, etc.

66

Page 67: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Today’s Agenda

We will cover more tomorrow at HAPI Advanced Tutorial

Page 68: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR JPA:Introduction

● HAPI JPA Server is a complete FHIR Server implementation based on Hibernate & Hibernate Search

● This is the module that powers http://fhirtest.uhn.ca

Page 69: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR JPA:Components

Generated ResourceProviders for all resource types

Implementation of most operations, search types, terminology svc, etc.

Database of your choosing

The same server from the previous section

Page 70: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR JPA:Features

● Supports most of the basic FHIR HTTP specification (create, search, conditionals, etc)

● Supports many advanced features too (subscriptions, patch, etc)

● Includes full validator and terminology server

Page 71: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR JPA:Databases

● HAPI examples typically use Apache Derby database● Derby is very convenient but not scalable

● HAPI is known to work with MySQL, Postgres, Oracle, SQL Server

Page 72: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

HAPI FHIR JPA:Lucene

● HAPI uses Apache Lucene to provide two features:● Fulltext searching within resources (_text

and _content parameters)● Terminology Services

● Lucene stores its files on the filesystem● Lucene can be safely disabled

Page 73: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Create your own JPA Server

Page 74: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Trying out HAPI FHIR JPA

There is a complete sample project available here:

https://github.com/furore-fhir/fhirstarters/tree/master/java/hapi-fhirstarters-jpaserver-example

Page 75: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Taking the Example for a Spin...

Page 76: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

An Even Easier Way to Try HAPI FHIR JPA

HAPI-FHIR-CLI Bundles this

Page 77: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Get Help!

● See our website for documentation:http://hapifhir.io

● We also have a Google Group / Mailing Listhttps://groups.google.com/d/forum/hapi-fhir

77

Page 78: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Get Involved!

● HAPI is a large worldwide community of developers

● Today most are working on HL7 v2, but this is changing fast

● We are very grateful to the many people who have contributed so far, maybe you could be next?

78

Page 79: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Thank You!

[email protected]● jamesagnew214 on Skype

79

Page 80: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Some bonus slides follow… :)

Page 81: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

Extensions: The Easy Way● Every element has a collection of

“undeclared” extensions

81

public class Example10_Extensions {

public static void main(String[] args) {Patient pat = new Patient();pat.addName().addFamily("Simpson").addGiven("Homer");

String url = "http://acme.org#eyeColour";boolean isModifier = false;pat.addUndeclaredExtension(isModifier, url).setValue(new CodeDt(“blue"));

IParser p = new FhirContext().newXmlParser().setPrettyPrint(true);String encoded = p.encodeResourceToString(pat);

System.out.println(encoded);}

}

<Patient xmlns="http://hl7.org/fhir"> <extension url="http://acme.org#eyeColour"> <valueCode value="blue"/> </extension> <name> <family value="Simpson"/> <given value="Homer"/> </name></Patient>

Page 82: hapi fhir java beginner and advanced for dev days

© 2014 HL7 ® International. Licensed under Creative Commons. HL7 & Health Level Seven are registered trademarks of Health Level Seven International. Reg. U.S. TM Office.

● HAPI also provides a set of annotations for creating statically typed extensions

82

@ResourceDef(name="Patient")public class Example11_ExtendedPatient extends Patient {

@Child(name = "eyeColour")@Extension(url="http://acme.org/#extpt", definedLocally = false, isModifier = false)private CodeDt myEyeColour;

public CodeDt getEyeColour() {if (myEyeColour == null) {

myEyeColour = new CodeDt();}return myEyeColour;

}

public void setEyeColour(CodeDt theEyeColour) {myEyeColour = theEyeColour;

}

}

Extensions: The “Hard” Way