Thursday, October 10, 2024

Public Sector Day Singapore 2024


I was delighted to be invited by AWS to share how we designed and implemented robust tech foundation for Singapore Healthier SG and Age Well SG at recent Public Sector Day Singapore 2024 on 03 Oct 202

It is hard to design robust future ready tech foundation for such large scale solution with extremely high throughout and fast performance, in generally all the APIs are performing at around 0.2 to 0.3 second even at peak volume. It is also relatively easy if the team has been consciously investing in the following four areas

  1. Deeper understanding of business domains, ability to shape the requirements, and ability to predict what will come next
  2. Deeper understanding of technologies - products/solutions and industry trend, set future ready technology direction, be ready to transform your team, the organisation and the industry
  3. Once you are equipped with deep understanding of business and technology, you will be naturally have the courage and determination to hold the vision and direction
  4. Build strong team whom you can count on so that you are confident that things will work out well even though some parts are not clear or fully sorted out yet at beginning
The two pillars of our strong tech foundation are AWS cloud platform and HL7 FHIR
  1. AWS has the broadest and richest cloud services for us to build modern cloud native and highly resilient applications
    • Use API GW, AWS EKS, RDS,SQS, Lambda and ActiveMQ for transactional part of the application
    • Use AWS Glue, AWS Data Lake for Operational Data Store 
    • Use AWS BedRock for RAG implementation
  2. HL7 FHIR provides suite of framework for us to build future proof applications
    • Use HL7 Extended Operation to define fined grained APIs to be accessed by external systems
    • Use HL7 FHIR data model as basis for our internal data model, so that it can support any future business needs without change to the data model
    • HL7 FHIR Profile as data validation control for API, any ongoing changes are handled with simple update to the profile without single line of code at all. For example, if we need to support different set of goals and activities for Health Plan, we can just update the profile for Health Plan API
    • Use "SQL On FHIR" to have universal transformation to transform any data subject to any data format required by data analysis and visualisation tool


Below are some photos taken during the public sector day  and the slides (in MP4 format at the bottom of this post)

Enjoy!
















Wednesday, September 25, 2024

HL7 FHIR difficult to implement - Misperception or truth?

Recently I am approached by one project team, who stated that it is very difficult to implement HL7 FHIR API with the following two reasons

1) Their system only supports RESTful with JSON

2) They are not familiar with HL7 FHIR

For technical people who has some basic understanding of HL7 FHIR, you must be laughing,  since HL7 FHIR API is using RESTful with JSON, and only difference between HL7 FHIR and other proprietary API is that the format and syntax in HL7 FHIR is standardised

Instead of brushing it aside, and knowing that the system is using Java. So I spent 5 minutes to ask Chatgrp, how to implement client side programme in Java to call HL7 FHIR API

Afterward I spent next few mins to try out and validate in Java IDE (Integrated Development Environment) Eclipse.

Below I briefly described the steps provided by chatgrp
1) Create a Maven project in Eclipse
2) Configure the dependent libraries(HAPI FHIR libraries) in Maven POM
3) Copy and paste the sample code provided by chatgpt into my Java application, and updated the remote FHIR server to FHIR server hosted by Firely (its FHIR server is written in .NET)
Below is the source code of the java application, you can run the application to create patient resource, once it is created, you can check the created resources at Firely Server using this URL - https://server.fire.ly/

package synapxe.fhir.demo;

import java.util.Calendar;

import java.util.Random;

import org.apache.commons.lang3.RandomStringUtils;

import org.hl7.fhir.r4b.model.Bundle;

import org.hl7.fhir.r4b.model.Enumerations;

import org.hl7.fhir.r4b.model.Identifier;

import org.hl7.fhir.r4b.model.Patient;

import ca.uhn.fhir.context.FhirContext;

import ca.uhn.fhir.rest.api.MethodOutcome;

import ca.uhn.fhir.rest.client.api.IGenericClient;

/**

* Sample FHIR Client using HAPI open source library https://github.com/hapifhir/hapi-fhir

*

* @author victorchai

*

*/

public class FHIRClient {

public static void main(String[] args) {

try {

createPatient ();

//searchPatientByName ("HapiVictor");

//deletePatient("cfc18bb8-e1dc-4bab-b4e2-83e1d797034f");

}

catch (Exception ex) {

ex.printStackTrace();

}

}

private static void createPatient() {

// Create a FHIR context for the FHIR version you are using (e.g., R4)

FhirContext ctx = FhirContext.forR4B();

// Create a client to connect to the FHIR server

String serverBaseUrl = "https://server.fire.ly"; // Firely FHIR Server which is implemented in .NET

IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);

// Create a Patient resource

Patient patient = new Patient();

Identifier nric = new Identifier();

nric.setSystem("http://fhir.synapxe.sg/Namespace/nric");

String nricDigits = RandomStringUtils.randomNumeric(7).toUpperCase();

nric.setValue("S" +nricDigits + "H");

patient.getIdentifier().add(nric);

patient.addName()

.setFamily("HapiVictor")

.addGiven("John");

patient.setGender(Enumerations.AdministrativeGender.MALE);

Calendar dob= Calendar.getInstance();

Random ran = new Random();

int x = ran.nextInt(10);

dob.set(1970 +x ,Calendar.getInstance().get(Calendar.MONTH), Calendar.getInstance().get(Calendar.DAY_OF_MONTH));

patient.setBirthDate(dob.getTime());

// Send the created patient resource to the server

MethodOutcome outcome = client.create().resource(patient).execute();

// Print the outcome

String patientID = outcome.getId().getIdPart();

System.out.println("Created Patient with ID: " + patientID);

System.out.println("You can access the patient resource at this url - "

+ serverBaseUrl +"/Patient/"+ patientID +"?_format=application/fhir+json");

}

private static void searchPatientByName (String familyName ) {

// Create a FHIR context for the FHIR version you are using (e.g., R4)

FhirContext ctx = FhirContext.forR4B();

// Create a client to connect to the FHIR server

String serverBaseUrl = "https://server.fire.ly"; // Example HAPI FHIR server

IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);

Bundle results = client.search()

.forResource(Patient.class)

.where(Patient.FAMILY.matches().value(familyName))

.returnBundle(Bundle.class)

.execute();

System.out.println("Found " + results.getTotal()+ " patients:");

for (Bundle.BundleEntryComponent entry : results.getEntry()) {

Patient patient = (Patient) entry.getResource();

System.out.println("Patient ID:" + patient.getIdElement().getIdPart());

System.out.println("Patient Name:" + patient.getNameFirstRep().getNameAsSingleString());

}

}

private static void deletePatient(String patientID) {

// Create a FHIR context for the FHIR version you are using (e.g., R4)

FhirContext ctx = FhirContext.forR4B();

// Create a client to connect to the FHIR server

String serverBaseUrl = "https://server.fire.ly"; // Example HAPI FHIR server

IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);

// Send the patient resource ID to the server

MethodOutcome outcome = client.delete().resourceById("Patient", patientID).execute();

// Print the outcome

System.out.println("Deleted Patient with ID: " + patientID + " with status:" + outcome.getResponseStatusCode()) ;

}

}

Below you can also find the libraries included in  Maven POM.xml which specifies the dependent libraries (again this is also provided by Chatgpt)

<dependencies>

<!-- This dependency includes the core HAPI-FHIR classes -->

<dependency>

<groupId>ca.uhn.hapi.fhir</groupId>

<artifactId>hapi-fhir-base</artifactId>

<version>${hapifhir_version}</version>

</dependency>

<!-- Include the client -->

<dependency>

<groupId>ca.uhn.hapi.fhir</groupId>

<artifactId>hapi-fhir-client</artifactId>

<version>${hapifhir_version}</version>

</dependency>

<!-- At least one "structures" JAR must also be included -->

<dependency>

<groupId>ca.uhn.hapi.fhir</groupId>

<artifactId>hapi-fhir-structures-r4b</artifactId>

<version>${hapifhir_version}</version>

</dependency>

<!--

HAPI-FHIR uses Logback for logging support. The logback library is included

automatically by Maven as a part of the hapi-fhir-base dependency, but you

also need to include a logging library. Logback is used here, but log4j

would also be fine.

-->

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>1.2.3</version>

</dependency>

</dependencies>


Btw, there are many many HL7 FHIR open sources libraries available - Java, Net, Python and Javascript, etc, you can find the full list at this URL - https://confluence.hl7.org/.../Open+Source+Implementations
Go explore HL7 FHIR and have fun. Pls msg me if you need have deeper discussion on HL7 FHIR


Tuesday, July 2, 2024

HL7 FHIR DevDays 2024 - Sharing of Singapore's Healthier SG implementation

 Below is the some of the slides from the recent sharing at FHIR DevDays 2024 (https://www.devdays.com/) on Singapore's National Healthier SG implementation.









I am also glad that the implementation got the inaugural FHIR implementers award, below is the finalist pitch I shared during DevDays







For more details, please go to the following Firely site on the highlights of FHIR DevDays 2024



HL7 FHIR APIs can fundamentally transform the rapid development of frontend web application

 Just imagine if all your backend APIs is based on HL7 FHIR API, how it will fundamentally transform your frontend web application developme...