Tag: ibm-fhir-server

  • Question: How do I configure fhir-notification Kafka so I don’t have to use a keystore?

    The IBM FHIR Server provides an eventing service that notifies about persistence events – CUD (Create-Update-Delete). The notification service can trigger specific actions in a downstream application. You can configure these events to flow to Apache Kafka.

    If you want to configure the IBM FHIR Server without a keystore, you can configure SASL_SSL like the below (notice there is no keystore specified).

    {
        "fhirServer":{
            "notifications":{
                "kafka": {
                    "enabled": true,
                    "topicName": "FHIR_NOTIFICATIONS",
                    "connectionProperties": {
                        "bootstrap.servers": "broker-1.mybroker.com:9093,broker-2.mybroker.com:9093,broker-0.mybroker.com:9093,broker-5.mybroker.com:9093,broker-4.mybroker.com:9093,broker-3.mybroker.com:9093",
                        "security.protocol": "SASL_SSL",
                        "sasl.mechanism": "PLAIN",
                        "ssl.protocol": "TLSv1.2",
                        "ssl.enabled.protocols": "TLSv1.2",
                        "ssl.endpoint.identification.algorithm": "HTTPS",
                        "security.inter.broker.protocol": "SSL",
                        "sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"token\" password=\"MYPASSWORD\";",
                        "acks": "all",
                        "retries": "60",
                        "request.timeout.ms": "10000",
                        "max.block.ms": "60000",
                        "max.in.flight.requests.per.connection": "5",
                        "client.dns.lookup": "use_all_dns_ips"
                    }
                }
            }
        }
    }
    

    If you run a workload against IBM FHIR Server, it’ll generate a set of notifications…

    1. Download Kafka from https://kafka.apache.org

    2. Create a client-ssl.properties

    cat << EOF > client-ssl.properties
    bootstrap.servers=broker-2.mybroker.com:9093,broker-5.mybroker.com:9093,broker-0.mybroker.com:9093,broker-3.mybroker.com:9093,broker-4.mybroker.com:9093,broker-1.mybroker.com:9093
    sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="token" password="MYPASSWORD";
    sasl.mechanism=PLAIN
    security.protocol=SASL_SSL
    ssl.protocol=TLSv1.2
    EOF
    
    1. Unzip the kafka archive

    2. Check the Kafka Console Consumer

    bash bin/kafka-console-consumer.sh --bootstrap-server broker-4.mybroker.com:9093,broker-5.mybroker.com:9093,broker-3.mybroker.com:9093,broker-2.mybroker.com:9093,broker-1.mybroker.com:9093,broker-0.mybroker.com:9093 --topic FHIR_NOTIFICATION --max-messages 25 --property print.timestamp=true --consumer.config client-ssl.properties
    
  • Question: Can I validate a batch of FHIR resources?

    Yes, you can use the Batch API.

    1. The Bundle.entry must include a request object pointing at URL <RESOURCE>/$validate with method POST.

    2. The Resource that is validated must be wrapped in a Parameters object and added to the Parameters.parameter.resource

    {
        "resourceType": "Parameters",
        "parameter": [
            {
                "name": "resource",
                "resource": <COPY HERE>
            }
        ]
    }
    
    1. Embed it at Bundle.entry.resource, and make a request to the server root.
    curl --location --request POST 'https://localhost:9443/fhir-server/api/v4' \
    --header 'Authorization: Basic ...' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "resourceType": "Bundle",
        "type": "transaction",
        "entry": [
            {
                "fullUrl": "Patient/$validate",
                "resource": {
                    "resourceType": "Parameters",
                    "parameter": [
                        {
                            "name": "resource",
                            "resource": {
                                "resourceType": "Patient",
                                "id": "example",
                                "name": [
                                    {
                                        "use": "official",
                                        "family": "Chalmers",
                                        "given": [
                                            "Peter",
                                            "James"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "meta": {
                        "tag": [
                            {
                                "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason",
                                "code": "HTEST",
                                "display": "test health data"
                            }
                        ]
                    }
                },
                "request": {
                    "method": "POST",
                    "url": "Patient/$validate"
                }
            }
        ]
    }'
    
    1. You’ll get a response like this, note the HTTP Status Code is 200 coming back… You have to look at Bundle.entry.resource.response.issue to check the severity and details to see why the validation is failing.
    {
        "resourceType": "Bundle",
        "type": "transaction-response",
        "entry": [
            {
                "resource": {
                    "resourceType": "OperationOutcome",
                    "id": "NoError",
                    "text": {
                        "status": "additional",
                        "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p>No error</p></div>"
                    },
                    "issue": [
                        {
                            "severity": "warning",
                            "code": "invariant",
                            "details": {
                                "text": "dom-6: A resource should have narrative for robust management"
                            },
                            "expression": [
                                "Patient"
                            ]
                        }
                    ]
                },
                "response": {
                    "status": "200",
                    "outcome": {
                        "resourceType": "OperationOutcome",
                        "id": "NoError",
                        "text": {
                            "status": "additional",
                            "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p>No error</p></div>"
                        },
                        "issue": [
                            {
                                "severity": "warning",
                                "code": "invariant",
                                "details": {
                                    "text": "dom-6: A resource should have narrative for robust management"
                                },
                                "expression": [
                                    "Patient"
                                ]
                            }
                        ]
                    }
                }
            }
        ]
    }
    

    You should add entries for each Resource you want to validate in the Batch.

  • IBM FHIR Server – Using the Docker Image with Near Feature and FHIR Examples from Jupyter Notebooks

    Hi Everyone.

    Thanks for sitting down and watching this video. I’m going to show you how to quickly spin up a Docker image of IBM FHIR Server, check the logs, make sure it’s healthy, and how to use the fhir-examples module with the near search.

    The following are the directions followed in the video:

    Navigate to DockerHub: IBM FHIR Server

    Run the Server docker run -p9443:9443 ibmcom/ibm-fhir-server

    Note, startup may take 2 minutes as the image is bootstrapping a new Apache Derby database in the image. To use Postgres or IBM Db2, please review the documentation.

    Review the docker logs

    Check the server is up and operational curl -k -i -u 'fhiruser:change-password' 'https://localhost:9443/fhir-server/api/v4/$healthcheck'

    You now have a running IBM FHIR Sever.

    Let’s load some data using a Jupyter Notebook.

    The IBM FHIR Server team wraps specification and service unit tests into a module called fhir-examples and posts to Bintray: ibm-fhir-server-releases or go directly to the repository.

    We’re going to use the python features and Jupyter Notebook to process the fhir-examples.

    We’ll download the zip, filter the interesting jsons, and upload to the IBM FHIR Server in a loop.

    entries = z.namelist()
    for entry in entries:
    if entry.startswith('json/ibm/bulk-data/location/'):
    f = z.open(entry);
    content = f.read()
    r = requests.post('https://localhost:9443/fhir-server/api/v4/Location',
    data=content,
    headers=headers,
    auth=httpAuth,
    verify=False)
    print('Done uploading - ' + entry)
    

    We’re going to query the data on the IBM FHIR Server using the Search Query Parameter near to search within 10Km of Cambridge Massachusetts.

    queryParams = {
    'near': '42.373611|-71.110558|10|km',
    "_count" : 200
    }
    

    Note, the IBM FHIR Server includes some additional search beyond the UCUM and WS48 units and it’s listed in at the Conformance page.

    We’ll normalize this data and put in a Pandas dataframe.

    From the dataframe, we can now add markers to the page.

    cambridge = [ 42.373611, -71.11000]
    map_cambridge_locs_from_server = folium.Map(location=cambridge, zoom_start=10)
    
    # Iterate through the Rows
    for location_row in location_rows :
    # print(location_row)
    # Cast the values into the appropriate types as FOLIUM will die weirdly without it.
    lat_inc = float(location_row['resource.position.latitude'])
    long_inc = float(location_row['resource.position.longitude'])
    name_inc = str(location_row['resource.name'])
    #print(lat_inc)
    #print(long_inc)
    #print(name_inc)
    label = folium.Popup(name_inc, parse_html=True)
    folium.CircleMarker(
    [lat_inc, long_inc],
    radius=5,
    popup=label,
    fill=True,
    fill_color='red',
    fill_opacity=0.7).add_to(map_cambridge_locs_from_server)
    map_cambridge_locs_from_server
    

    You can see the possibilities with the IBM FHIR Server and the near search.

    Reference

  • Release 4.1.0 – Lessons Learned in Development

    Using IBM Db2 with IBM FHIR Server

    I spent a lot of time documenting the multi-tenancy schema and how the migration works in Db2.

    Some of the critical links, the team updated, and I authored are:

    Interestingly, I spent the most time documenting the schema and how it supports the multi-tenancy with the following pattern:

    Using ibm/db2 docker and using with IBM FHIR Server

    Use the following Dockerfile from this folder fhir-install/docker.

    docker build -t fhirdb Dockerfile-db2 --squash
    

    If you create the Db2 container without the above Dockerfile, please be sure to do the following:

    1. Add the trial license.

    /opt/ibm/db2/V11.5/adm/db2licm -a /var/db2/db2trial.lic

    1. Update the Instance Memory Configuration
    su - db2inst1 -c "db2 update dbm cfg using INSTANCE_MEMORY AUTOMATIC"
    
    1. Create the Db2 database with 32K pagesize
    su - db2inst1 -c "db2 CREATE DB FHIRDB using codeset UTF-8 territory us PAGESIZE 32768"
    
    1. Add a Db2 user
    groupadd -g 1002 fhir && \
        useradd -u 1002 -g fhir -M -d /database/config/fhirserver fhirserver && \
        echo "change-password" | passwd --stdin fhirserver
    su - db2inst1 -c "db2 \"connect to fhirdb\" && db2 \"grant connect on database TO USER fhirserver\""
    
    1. Run the Schema creation with a small pool
    –prop-file fhir-persistence-schema/db.properties
    –schema-name FHIRDATA
    –pool-size 2
    –update-schema
    
    1. Create a new tenant
    –prop-file fhir-persistence-schema/db.properties
    –schema-name FHIRDATA
    –allocate-tenant TNT1
    
    1. Contents of db.properties are
    db.host=localhost
    db.port=50000
    db.database=fhirdb
    user=db2inst1
    password=change-me
    sslConnection=false
    

    Good luck with Docker/IBM FHIR Server

  • Release 4.0.1 – Lessons Learned in Development

    My team just released IBM FHIR Server 4.0.1.

    A few things, I learned:

    To Reset a Tag

    git tag -d 4.0.1
    git push origin --delete 4.0.1
    git tag 4.0.1
    git push --tags
    

    End to End Windows Tests

    I used a powershell and added an archive step.

    # Create the Zip File
    $compress = @{
    LiteralPath= $pre_it_logs
    CompressionLevel = 'Fastest'
    DestinationPath = $zip_file
    }
    
    Compress-Archive @compress -Force
    

    Ignoring Self-Signed Certs with Powershell

    Also a step to test our server, but hit an issue with the certificate
    
    # Ignore Self Signed Certificates and use TLS
    # Reference https://stackoverflow.com/a/46254549/1873438
    $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
    [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
    Add-Type -TypeDefinition @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
    ServicePoint srvPoint, X509Certificate certificate,
    WebRequest request, int certificateProblem) {
    return true;
    }
    }
    "@
    $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
    [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
    

    Break it down into individual parts

    Release Tricks and Tips break it down into different workflows.