Skip to main contentIBM® FHIR® Server

IBM FHIR Server on the Raspberry Pi 4

IBM FHIR Server on Raspberry Pi 4

Usage

This installation is for curiosity only and should not be used with PHI, only synthetic test data. Production instances require additional hardening which is outside the scope of this guide.

The default password used throughout is change-password and this is configured as clear-text in the configuration files to make it even more obvious that it should be changed as part of any hardening. Refer to the FHIRServerUsersGuide for more details.

Introduction

The IBM FHIR Server runs as a web application in the Open Liberty application server. By default persistence is provided with a Derby database, but it can also be configured to use IBM Db2 on Cloud. This example shall use the default Derby instance.

ComponentDetails
HardwareRaspberry Pi 4
Memory4GB
OSRaspbian (Buster)
Storage64GB microSD
Javaopenjdk11
Apache Maven3.6.1
Application ServerOpen Liberty 19.0.0.8
HTTPS Port9443
Default userfhiruser
Default passwordchange-password

Set up your Raspberry Pi 4 (4GB model) using Raspbian (https://www.raspberrypi.org/downloads/).

TIP: Under load, the Raspberry Pi 4 CPU throttles when it reaches a critical temperature, so a case with cooling is recommended. Without naming products, an aluminum case which acts as a heat sink could be a good choice. The CPU definitely throttles during the build using the official (plastic) Raspberry Pi 4 case.

Development Environment and Prerequisites

To build we need three things:

  1. openjdk11 (already available)
  2. Apache Maven
  3. Access to the internet (for Maven dependencies)

Install Maven

You can use apt-get to install Apache Maven but if you want to avoid all the dependencies which come along with it, just grab the binary release and unpack it

OPTION A:

sudo apt-get install maven

OPTION B:

wget https://www-us.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz -P /tmp
sudo mkdir -p /opt/tools && cd /opt/tools && tar xzvf /tmp/apache-maven-3.6.1-bin.tar.gz

If installing Maven manually, add it to your PATH:

# Add Maven to PATH
export PATH="/opt/tools/apache-maven-3.6.1/bin:${PATH}"

Check

pi@raspberrypi:~/git/FHIR $ mvn -version
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T15:00:29-04:00)
Maven home: /opt/tools/apache-maven-3.6.1
Java version: 11.0.3, vendor: Raspbian, runtime: /usr/lib/jvm/java-11-openjdk-armhf
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.19.66-v7l+", arch: "arm", family: "unix"

Environment

ComponentDetails
Liberty Home/opt/ibm/fhir-server/wlp
JAVA_HOME/usr/lib/jvm/java-11-openjdk-armhf

Building

Set up your development environment and clone the repository:

mkdir -p ~/git && cd ~/git && git clone https://github.com/IBM/FHIR.git

Now you should be ready to build:

cd ~/git/FHIR
mvn clean install -f fhir-parent/pom.xml

Be patient. A lot of unit tests are executed, including processing a number of the FHIR specification examples in various contexts which is fairly CPU intensive. Unit tests in the fhir-persistence-jdbc project use a functional schema deployed in a Derby database, exercising the bulk of the persistence code except for the REST layer.

Some exceptions from negative tests may appear in the build log. As long as the build completes, these shouldn’t be a concern. Success should look like this:

[INFO] Reactor Summary for IBM FHIR Server FHIR 4.0.0-SNAPSHOT:
[INFO]
[INFO] IBM FHIR Server ...................... SUCCESS [ 8.537 s]
[INFO] fhir-core .......................................... SUCCESS [ 7.478 s]
[INFO] fhir-task-api ...................................... SUCCESS [ 0.583 s]
[INFO] fhir-task-core ..................................... SUCCESS [ 9.217 s]
[INFO] fhir-database-utils ................................ SUCCESS [ 16.877 s]
[INFO] fhir-config ........................................ SUCCESS [ 12.278 s]
[INFO] fhir-audit ......................................... SUCCESS [ 13.421 s]

Installation

The above build creates an installable artifact:

~/git/FHIR/fhir-install/target/fhir-server-distribution.zip

Unpack the archive into a working directory:

mkdir -p ~/unpack && cd ~/unpack && unzip ~/git/FHIR/fhir-install/target/fhir-server-distribution.zip

Decide where you want to install. As this isn’t a production server, installing it under the pi user is convenient.

mkdir -p ~/runtime/fhir-server && sh ~/unpack/fhir-server-dist/install.sh ~/runtime/fhir-server

Check that the Liberty runtime was installed correctly:

~/runtime/fhir-server/wlp/bin/server status fhir-server
Server fhir-server is not running.

The default configuration uses a 4GB heap size which is too large for the Pi. Edit the jvm.options file and reduce the memory footprint using -Xmx1024M and -Xms1024M:

pi@raspberrypi:~ $ vi ~/runtime/fhir-server/wlp/usr/servers/fhir-server/jvm.options
...
grep -- -Xm ~/runtime/fhir-server/wlp/usr/servers/fhir-server/jvm.options
-Xms1024M
-Xmx1024M

Start the server (the first startup takes some time):

~/runtime/fhir-server/wlp/bin/server start fhir-server
Starting server fhir-server.
Server fhir-server started with process ID 1234.

Smoke Test

Run a basic connectivity check. This is a primitive check to ensure that the application server is accessible and that the FHIR web application is running:

sh ~/unpack/fhir-server-dist/fhirSmokeTest.sh localhost 9443
Checking if server localhost is accessible on port 9443 ... OK!
Checking FHIR server signature... OK!
Checking FHIR API version... OK!
Success! All checks passed.

Clean up

rm -fr ~/unpack/fhir-server-dist
rm -f /tmp/apache-maven-3.6.1-bin.tar.gz

Create a Patient Resource

Create a new patient resource using the following POST. The FHIR server will allocate a unique logical identifier (UUID):

curl -k \
-H 'Content-Type: application/json' \
-u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient' -d '
{
"resourceType" : "Patient",
"active" : true,
"name" : [ {
"family" : "Ortiz",
"given" : [ "David" ]

The FHIR server should respond with a 201 Created status:

HTTP/2 201
location: https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc/_history/1
etag: W/"1"
last-modified: 2019-09-12T19:22:02.159503Z
date: Thu, 12 Sep 2019 19:22:05 GMT
content-length: 0
content-language: en-US

Use the location: value returned from your POST to read back the resource:

Command (example):

curl --silent -k -H 'Accept: application/json' -u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc' | python -m json.tool

Remember to use the patient logical id returned as the location: header in your POST - if you try to use 041786ad-d6a1-42ea-bf47-4dd8eb08a5fc the response status will be Not Found.

Output:

{
"active": true,
"gender": "male",
"id": "041786ad-d6a1-42ea-bf47-4dd8eb08a5fc",
"meta": {
"lastUpdated": "2019-09-12T19:22:02.159503Z",
"versionId": "1"
},
"name": [

Now we can update the resource using a PUT (David => Dave). Again, it is important to use the logical ids from your example, not the values shown here. This includes the “id” field in the body, which should match the logical id of the URL:

curl -k -i \
-X PUT \
-H 'Content-Type: application/json' \
-u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc' -d '
{
"active": true,
"gender": "male",
"id": "041786ad-d6a1-42ea-bf47-4dd8eb08a5fc",
"meta": {

Response:

HTTP/2 200
location: https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc/_history/2
etag: W/"2"
last-modified: 2019-09-12T19:46:24.656131Z
date: Thu, 12 Sep 2019 19:46:26 GMT
content-length: 0
content-language: en-US

Note the location: has now changed to indicate the new version is 2.

Retrieve the latest version:

curl --silent -k -H 'Accept: application/json' -u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc' | python -m json.tool

Response:

curl --silent -k -H 'Accept: application/json' -u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc' | python -m json.tool
{
"active": true,
"gender": "male",
"id": "041786ad-d6a1-42ea-bf47-4dd8eb08a5fc",
"meta": {
"lastUpdated": "2019-09-12T19:46:24.656131Z",
"versionId": "2"
},

Note that the given name is “Dave”.

To see a previous version, perform a vread:

curl --silent -k -H 'Accept: application/json' -u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc/_history/1' | python -m json.tool

Response:

{
"active": true,
"gender": "male",
"id": "041786ad-d6a1-42ea-bf47-4dd8eb08a5fc",
"meta": {
"lastUpdated": "2019-09-12T19:22:02.159503Z",
"versionId": "1"
},
"name": [

In version 1, we see that the given name is the original value of “David”.

All the versions of the resource can be read using a history read operation:

curl --silent -k -H 'Accept: application/json' -u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc/_history' | python -m json.tool

The response is a FHIR bundle resource containing both versions of the Patient. Note the name change from David (version 1) to Dave (version 2):

{
"entry": [
{
"fullUrl": "https://localhost:9443/fhir-server/api/v4/Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc",
"request": {
"method": "PUT",
"url": "Patient/041786ad-d6a1-42ea-bf47-4dd8eb08a5fc"
},
"resource": {

END-OF-DOCUMENT