3. Search for Event Streams, and click on Event Streams
Search and Click on Event Streams
4. Choose your Location. I chose us-south. Pick the data center that is closest or co-located with your IBM FHIR Server.
5. Select the Standard plan. A typical bundle which represents a patient history, such as Antonia30_Acosta403.json, include hundreds of resources which correspond to many messages sent over the topic when processed as a Bundle batch. For a Bundle transaction, you get only one notification message.
6. Click I Accept
7. Click Create. You are redirected to the EventStreams resource that is created.
Your Service is Created
8. Click Service Credentials
9. Click New Credentials
10. Click Add
Create Credentials Dialog
11. Copy the Service Credentials and paste it locally (on the right hand-side)
Copy Credentials
12. Click on Topics
13. Click Create Topic
14. Enter Topic Name – FHIR_AUDIT
15. Click Next
Enter Topic Name
16. Select the default number of partitions
Select Number of Partitions
17. Click Next
18. Select Message Retention – 1 Day
19. Click Create Topic
Create Topic
With the IBM EventStreams Kafka Topic setup, it’s now time to connect the IBM FHIR Server and the FHIR Audit module to Kafka.
You see the container id output 60a5f1cae6d677d80772f1736db1be74836a8a4845fcccc81286b7c557bc2d86.
26. Check that the applications are started using the container id.
$ docker logs 60a | grep -i started
[4/21/21, 20:55:58:449 UTC] 00000001 FrameworkMana I CWWKE0002I: The kernel started after 1.43 seconds
[4/21/21, 20:55:58:464 UTC] 0000002a FeatureManage I CWWKF0007I: Feature update started.
[4/21/21, 20:56:01:328 UTC] 00000030 AppMessageHel A CWWKZ0001I: Application fhir-openapi started in 1.588 seconds.
[4/21/21, 20:56:03:141 UTC] 00000031 AppMessageHel A CWWKZ0001I: Application fhir-bulkdata-webapp started in 3.402 seconds.
[4/21/21, 20:56:07:824 UTC] 0000002d AppMessageHel A CWWKZ0001I: Application fhir-server-webapp started in 7.871 seconds.
[4/21/21, 20:56:07:868 UTC] 0000002a TCPPort I CWWKO0219I: TCP Channel defaultHttpEndpoint-ssl has been started and is now listening for requests on host * (IPv4) port 9443.
[4/21/21, 20:56:07:880 UTC] 0000002a FeatureManage A CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 10.885 seconds.
29. Scan the response.json for any status that is not "status": "201". For example, the status is in the family of User Request Error or Server Side Error.
dependency-check is a standalone maven plugin which checks for vulnerable dependencies. It’s hosted on GitHub. I switched to it from the victims-db, which no longer looks like it is updated. I had to carefully analyze the output, it was very helpful finding one issue where we had an unintended include.
I recently attended the HL7 FHIR Connectathon 29. For those that are not familiar with Connectathons, I think they are fairly unique events featuring standards enthusiasts, vendors and implementors doing hands-on standards development (FHIR) and testing. As an attendee I picked one of the tracks – bulk data.
This blog is part of a series on Bulk Data Setup and Testing based on my experience at HL7 FHIR Connectathon 29.
The SMART-on-FHIR team has built a node application to call Bulk Data $export and facilitate the calls to get a bearer token.
$ brew install nvm
Running `brew update --preinstall`...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/core, homebrew/cask and minio/stable).
==> New Formulae
cwb3 erofs-utils netmask scalingo zk
==> Updated Formulae
Updated 390 formulae.
...
nvm 0.35.3 is already installed but outdated (so it will be upgraded).
==> Downloading https://ghcr.io/v2/homebrew/core/nvm/manifests/0.39.1_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/nvm/blobs/sha256:6e14c8a2bf94212545c1ebac9a722df168c318d0e8af2fc75b729a07fea54efe
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:6e14c8a2bf94212545c1ebac9a722df168c318d0e8af2fc75b729a07fea54efe?se=2022-01-13T21%3A30%3A00Z&sig=52CYOAyuxabqLNYih9%2BjMQtHLFrN%2FVyHXf%2FgPuBgi6w%3D&sp=r&spr=https&sr=b&sv=2019-12-12
######################################################################## 100.0%
==> Upgrading nvm
0.35.3 -> 0.39.1_1
==> Pouring nvm--0.39.1_1.all.bottle.tar.gz
...
Bash completion has been installed to:
/usr/local/etc/bash_completion.d
==> Summary
πΊ /usr/local/Cellar/nvm/0.39.1_1: 9 files, 184.1KB
==> Running `brew cleanup nvm`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /usr/local/Cellar/nvm/0.35.3... (7 files, 149.9KB)
Switch to Node 16
$ nvm use 16
Now using node v16.13.0 (npm v8.1.2)
Install Node 16
$ nvm install
Found '/git/wffh/2023/bulk-data-client/.nvmrc' with version <16>
Downloading and installing node v16.13.2...
Downloading https://nodejs.org/dist/v16.13.2/node-v16.13.2-darwin-x64.tar.xz...
############################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v16.13.2 (npm v8.1.2)
Create the binaries
$ npm run clean && npm run build
> bulk-data-client@1.0.0 clean
> rm -rf ./built
> bulk-data-client@1.0.0 build
> tsc
$ AUTO_RETRY_TRANSIENT_ERRORS=1 SHOW_ERRORS=1 node . --config config/ibm-fhir-server.js --_type=Patient
Kick-off started
Got new access token
Kick-off completed
Bulk Data export started
Bulk Data export completed in 10 seconds
Export manifest: {
transactionTime: '2022-01-14T20:56:31.553Z',
request: 'https://bulk.cluster1-blue-x123456.containers.appdomain.cloud/fhir-server/api/v4/Patient/$export?_type=Patient',
requiresAccessToken: false,
output: [
{
type: 'Patient',
url: 'https://x123456.cloud-object-storage.appdomain.cloud/x123456/f1wSMD84-3eRVNTUlyIwctWtNxA33Odz14KiQctry-U/Patient_1.ndjson?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=x123456%2F20220114%2Fus-east%2Fs3%2Faws4_request&X-Amz-Date=20220114T205641Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=abcdefgh',
count: 2
}
],
error: []
}
Downloading exported files: ββββββββββββββββββββββββββββββ 100%
Downloaded Files: 1 of 1
FHIR Resources: 2
Attachments: 0
Downloaded Size: 6.3 kB
Download completed in 0 seconds
Do you want to signal the server that this export can be removed? [Y/n]n
The IBM FHIR Server supports FHIR R4 and is at version 4.10.2.
The conformance page outlines the features and capabilities of the main build link.
The user’s guide outlines the features and configurations link.
The module catalog outlines the features link.
Per Enqueue Zero, Nsenter is a utility enters the namespaces of one or more other processes and then executes the specified program. In other words, we jump to the inner side of the namespace.
Search for the namespace, by searching for S+, and then using the PID to target the namespace, and run the local tools in the namespace. This is very helpful where the docker container does not contain the necessary tools by default.
Never accept the defaults: Lessons Learned using OpenJ9 in a Container
Eclipse OpenJ9 is an efficient virtual machine with a small-dynamic footprint that is used for many cloud applications. Many applications use the OpenJ9 to run their applications, such as the Apache OpenWhisk, IBM FHIR Server and Open Liberty.
I learned a few things about running Java applications with the OpenJ9 VM in Docker:
Eclipse OpenJ9 knows about modern applications
Tweak Your Settings
Review your Settings
1. Eclipse OpenJ9 knows about modern applications
The Eclipse OpenJ9 team smartly realized many Java applications are in a container or namespace or virtual machine which has a runtime determined memory allocation. For instance, Kubernetes may scale the memory available to a Java Container from 4G to 8G. As such, the OpenJ9 VM automatically adjust the minimum and maximum heap sizes based on the available memory in the container.
There are plenty of nobs to tweak. Further, the Eclipse team has some compelling research on performance and places to look to tweak my application.
Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 54838
at org.postgresql.core.PGStream.sendInteger2(PGStream.java:349)
at org.postgresql.core.v3.QueryExecutorImpl.sendParse(QueryExecutorImpl.java:1546)
at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1871)
at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1432)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
... 96 more
I had 54K parameters on my query. It turns out due to public void sendInteger2(int val) throws IOExceptionPGStream.java has a maximum number of Short.MAX_VALUE – 32767
Net for others hitting the same issue in different RDBMS systems:
Postgres – 32767 Parameters
IBM Db2 Limit – Maximum number of host variable references in a dynamic SQL statement -> 32,767 32,767 Parameters and 2,097,152 length of the text in the generated sql. Limits
A colleague of mine is entering into the depths of the IBM FHIR Server’s Bulk Data feature. Each tenant in the IBM FHIR Server may specify multiple storageProviders. The default tenant is assumed, unless specified with the Http Headers X-FHIR-BULKDATA-PROVIDER and X-FHIR-BULKDATA-PROVIDER-OUTCOME. Each tenantβs configuration may mix the different providers, however each provider is only of a single type. For instance, minio is aws-s3 and default is file and az is azure-blob.
Note, type http is only applicable to $import operations. Export is only supported with s3, azure-blob and file.
File Storage Provider Configuration
The file storage provider uses a directory local to the IBM FHIR Server. The fileBase is an absolute path that must exist. Each import inputUrl is a relative path from the fileBase. The File Provider is available for both import and export. Authentication is not supported.
{
"__comment": "IBM FHIR Server BulkData - File Storage configuration",
"fhirServer": {
"bulkdata": {
"__comment" : "The other bulkdata configuration elements are skipped",
"storageProviders": {
"default": {
"type": "file",
"fileBase": "/opt/wlp/usr/servers/fhir-server/output",
"disableOperationOutcomes": true,
"duplicationCheck": false,
"validateResources": false,
"create": false
}
}
}
}
}
The http storage provider uses a set of validBaseUrls to confirm $import inputUrl is acceptable. The Https Provider is available for import. Authentication is not supported.
{
"__comment": "IBM FHIR Server BulkData - Https Storage configuration (Import only)",
"fhirServer": {
"bulkdata": {
"__comment" : "The other bulkdata configuration elements are skipped",
"storageProviders": {
"default": {
"type": "https",
"__comment": "The whitelist of valid base urls, you can always disable",
"validBaseUrls": [],
"disableBaseUrlValidation": true,
"__comment": "You can always direct to another provider",
"disableOperationOutcomes": true,
"duplicationCheck": false,
"validateResources": false
}
}
}
}
}
The azure-blob storage provider uses a connection string from the Azure Blob configuration. The bucketName is the blob storage name. The azure-blob provider supports import and export. Authentication and configuration are built into the Connection string.
"__comment": "IBM FHIR Server BulkData - Azure Blob Storage configuration",
"fhirServer": {
"bulkdata": {
"__comment" : "The other bulkdata configuration elements are skipped",
"storageProviders": {
"default": {
"type": "azure-blob",
"bucketName": "fhirtest",
"auth": {
"type": "connection",
"connection": "DefaultEndpointsProtocol=https;AccountName=fhirdt;AccountKey=ABCDEF==;EndpointSuffix=core.windows.net"
},
"disableBaseUrlValidation": true,
"disableOperationOutcomes": true
}
}
}
}
}```
The aws-s3 storage provider supports import and export. The bucketName, location, auth style (hmac, iam), endpointInternal, endpointExternal are separate values in the configuration. Note, enableParquet is obsolete.