[JAVA] Introduction to EHRbase 2-REST API

Introduction

The second time, we will exchange data with EHRbase using REST API. EHRbase has many REST APIs, including those under development. This time, I will introduce the following APIs related to Template and Composition.


Work environment

To handle the REST API of EHRbase, it is easy to use the Swagger UI of the Web provided by EHRbase. However, I think it is better to use Postman for development because there is no leftover.

There are many tools for creating openEHR templates, some of which can be created on the web, but Ocean Template Designer has a long history and many users.


openEHR REST API

Interfaces were implemented in RPC and SOAP from the 1990s to the early 2000s when the development of openEHR began. As an external interface, a calling language called AQL (Archetype Query Language) is prepared, and it was common in openEHR to use it to communicate with the outside. However, in the 2010s, REST API became mainstream, and each company that implemented openEHR, including cooperation with FHIR, implemented REST API.

As openEHR, REST API is standardized and released as follows.

https://specifications.openehr.org/releases/ITS-REST/latest

However, an API using the simplified JSON format was announced by Marand, and as a result of following other implementations because it is convenient, there are variations in parameters and simplification methods. As a result of discussions at the openEHR specification development committee, the simplified data format has also been standardized and is published as follows.

Simplified data template standard https://specifications.openehr.org/releases/ITS-REST/latest/simplified_data_template.html

Marand EHR Cape API https://dev.ehrscape.com/api-explorer.html

EtherCIS, one of the predecessors of EHRbase, had its own simplifications, but it has now been removed and is being implemented based on the new simplified data template standard. (Scheduled to be released around December 2020)


REST API notation

I will not explain the REST API again. To simplify it tremendously, access a specific URL using the HTTP method and exchange data, but I think that EHRbase is deployed in each environment, so it is not possible to write a unified URL notation. .. Therefore, this time, omit the part from http: // to ehrbase / in the URL below and write the REST API as shown below (please let me know if there is a good way to write it).

Example: When trying to incorporate information related to ehr_id with parameters using the GET method at http: // localhost: 8080 / ehrbase / rest / openehr / v1 / ehr

GET /rest/openehr/v1/ehr/{{ehr_id}}

Parameters

key value
subject_id ins01
subject_namespace ehr_craft

The actual request issued is as follows. The {{}} that appears in the URL indicates that it is a variable part.

curl -X GET "http://localhost:8080/ehrbase/rest/openehr/v1/ehr/f2e3ebf3-596b-4067-9f76-8f4f19c0c474?subject_id=ehr_craft&subject_namespace=ins01" -H  "accept: application/xml"

EHR class openEHR manages data on a patient-by-patient basis. The unit that stores data for each patient is EHR. Imagine making a box to store patient data, not the EHR system itself. Therefore, creating an EHR using the REST API does not mean creating an EHR system. In the openEHR architecture, attribute information such as patient name, address, and gender is not stored directly in EHR, but is linked by calling the EHR class ID from an external patient information database.

This is designed with the assumption that EHR will be used as an anonymous database.


POST EHR (Create EHR record)

If you just want to create a new EHR record, just POST with no parameters as below.

POST /rest/openehr/v1/ehr

Please replace the part of localhost: 8080 in the URL in each environment. You will receive a response as shown below, so you need to save the ehr_id.

{
    "system_id": {
        "_type": "HIER_OBJECT_ID",
        "value": "b1718dd8-a45a-4ebf-a1d6-9a9fd7ca36fb"
    },
    "ehr_id": {
        "_type": "HIER_OBJECT_ID",
        "value": "fa95a254-feb0-4b03-9fe3-193d7d485d45"
    },
    "ehr_status": {
        "_type": "EHR_STATUS",
        "subject": {
            "_type": "PARTY_SELF",
            "external_ref": {
                "_type": "PARTY_REF",
                "namespace": "default",
                "id": {
                    "_type": "HIER_OBJECT_ID",
                    "value": "a258c07e-7b64-4062-b449-f96504e54a94"
                }
            }
        },
        "uid": {
            "_type": "HIER_OBJECT_ID",
            "value": "1220e446-b637-4c39-a62b-1e53f479ffea"
        },
        "is_queryable": true,
        "is_modifiable": true
    },
    "time_created": "2020-09-26T02:11:21.214052"
}

The EHR ID is the following part.

    "ehr_id": {
        "_type": "HIER_OBJECT_ID",
        "value": "fa95a254-feb0-4b03-9fe3-193d7d485d45"
    },

Save the EHR ID as you will need it when reading the EHR data. If you don't know, EHRbase doesn't have an API to get a list of EHR IDs, so you have to look inside PostgreSQL.


POST EHR (Create EHR record with external ID)

If the patient ID already exists like the medical examination ticket number, attach the following JSON message and POST to / rest / v1 / ehr to save the external ID as well.

POST /rest/openehr/v1/ehr

body

{
  "_type": "EHR_STATUS",
  "subject": {
    "external_ref": {
      "id": {
        "_type": "GENERIC_ID",
        "value": "ins11",
        "scheme": "id_scheme"
      },
      "namespace": "ehr_craft",
      "type": "PERSON"
    }
  },
  "is_modifiable": "true",
  "is_queryable": "true"
}

Please note that in the EHRbase sample and Swagger UI, ITEM contains blank other_details, which gives an error.

If the external ID is duplicated, the following error will be returned, so don't worry too much and issue EHR more and more.

{
    "error": "Specified party has already an EHR set (partyId=ce8bf586-125d-4c28-9970-465eacbaa8c4)",
    "status": "Conflict"
}

GET EHR (Read EHR record by EHR ID)

Let's call the EHR created by POST by EHR ID. In place of {{EHR ID}}, specify the ehr_id returned earlier.

GET /rest/openehr/v1/ehr/{{EHR ID}}

If it has been created, the same data as the registered contents will be returned. The default is JSON, but if you specify Accept application / xml in the HTTP Header as shown below, the data will be returned in XML format.

HTTP header

key value
Accept application/xml

GET EHR (read EHR record with external ID)

GET /rest/openehr/v1/ehr/

Parameters

key value
subject_id 0001
subject_namespace NPO openEHR Japan

Creating Template

In openEHR, the unit of data registered in EHR is Composition, and medical record records, various reports, inspection results, etc. are recorded as Composition. Various constraints are described in Template based on Composition.

As an example, create a template to monitor body temperature and symptoms. The Archetypes used are:

After creating a template using Ocean Template Designer, export it as an "Available Template". The file whose file identifier is output as opt is called Operational Template (hereinafter referred to as OPT). All the data to be handled is defined in this file and written in XML.

If you put a space in the Tempate ID, problems such as EHRbase not being able to read it occurred, so please avoid it at this time.

The OPT used this time is released as symptom_screening.opt.


POST Template (Registration of Template)

Let's register Template (OPT) in EHRbase by POST.

POST /rest/openehr/v1/definition/template/adl1.4

Paste the contents of the opt file created earlier into the body. Template is identified by template_id and uid, so if either one is worn, an error will be returned.

  <uid>
    <value>17bed299-2c1e-42cc-afb3-6d78002dcce3</value>
  </uid>
  <template_id>
    <value>symptom_screening</value>
  </template_id>

GET Template (reading individual templates)

Use the GET method to check if the POSTed Template is registered in EHRbase. Let's read it using the template_id of the template registered earlier. Enter symptom_screening in place of {{template_id}}.

GET /rest/openehr/v1/definition/template/adl1.4/{{template_id}}

The registered OPT will be returned as a response.


GET Template (Read template list)

Get and check the currently registered list.

GET /rest/openehr/v1/definition/template/adl1.4/

A list like the one below will be returned

[
    {
        "concept": "symptom_screening",
        "template_id": "symptom_screening",
        "archetype_id": "openEHR-EHR-COMPOSITION.health_summary.v1",
        "created_timestamp": "2020-09-25T03:17:54.134Z"
    }
]

Creating a Template-enabled JSON instance

Creating an instance of JSON or XML based on the contents defined in Template is not so easy, so I am creating an automatic tool.

EHRbase provides openEHR-SDK, which can generate a group of classes that can access EHRbase from OPT.

I was developing a group of tools that automatically generate a template for the JSON instance used this time, but it took a long time to investigate because the JSON instance was not published so much in the first place. Finally, I created an instance that works one day ago, so this time I will perform Composition access based on it.

The created procedure is as follows.

  1. Register OPT via API of EHR Cape (Marand)
  2. Get the JSON template via the EHR Scape API
  3. I used the FLAT format first, but it doesn't work, so I parsed the EHRbase code and understood that it doesn't support the FLAT format at this time.
  4. Specify the STRUCTURED format and get the JSON template from EHR Cape.
  5. I created an instance and registered it in EHRbase, but I got an error in the category, so I rebuilt EHRbase and analyzed the code and reported it as a bug.
  6. Christian Chevalley's comment was faint, so I adjusted the instance based on it and moved.

The created instance is published to GIST.

https://gist.github.com/skoba/cca9f69004a229e5922a0e3e73dca53e


POST Composition (Composition registration)

Register the created Composition instance using the REST API. It will be linked to the EHR ID that has already been registered.

POST /rest/openehr/v1/ehr/{{EHR ID}}/composition

Let's paste the JSON of GIST into the body.

The respose header is important. The ETag contains data in the format "89b114ea-59bd-4d98-b9b8-ad8f819a5aa3 :: local.ehrbase.org :: 1", which is called the Versioned Object UID. The UUID assigned to the Composition record and the unique URL and version number registered in the EHR are written separated by ::. This UUID will be the ID of the Composition record.


GET Composition (reading Composition)

Read the data registered using the EHR ID and Composition ID.

GET /rest/openehr/v1/ehr/{{EHR ID}}/composition/{{Composition ID}}

Enter the registered EHR ID and Composition ID in {{EHR ID}} and {{Composition ID}}, respectively. The same data as the registered JSON will be returned.


PUT Composition (Updated Composition)

Use PUT to change the content if there is a correction.

PUT /rest/openehr/v1/ehr/{{EHR ID}}/composition/{{Composition ID}}

For boody, use a modified version of JSON.

The important thing here is the Coposition VersionObjectUID that was also in the Etag earlier. Specify as follows in HTTP request header.

key value
If-Match version_object_uid

If successful, the new version object uid will be returned in the ETag of the response header.


GET COMPOSITION (Read Composition for each version)

All COMPOSITION is versioned in openEHR. If you use the versioned object uid mentioned earlier, you can retrieve the data before and after the composition you updated earlier.

GET /rest/openehr/v1/ehr/{{EHR ID}}/composition/{versioned object uid}}

Change the version at the end to see the difference in the data.


DELETE Composition (logical deletion of composition)

In openEHR, deleting a record is only a logical deletion, it just becomes unreadable and continues to be saved as a database. It's a rare feature, but if you want to delete it, use DELETE with the latest versioned oject uid.

DELETE /rest/openehr/v1/ehr/{{EHR ID}}/composition/{versioned object uid}}

If you specify a version other than the latest version, that version will be deleted, but you can still read other versions. If you delete the latest version, you will not be able to access it from the API including the old version.


Summary

Recommended Posts

Introduction to EHRbase 2-REST API
[Java] Introduction to Stream API
[Introduction to Java] About Stream API
Introduction to Ruby 2
Introduction to SWING
Introduction to web3j
Introduction to Micronaut 1 ~ Introduction ~
Introduction to EHRbase 1-Overview and Environmental Improvement
[Java] Introduction to Java
Introduction to migration
Introduction to java
Introduction to Doma
How to implement optimistic locking in REST API
Introduction to Ratpack (8)-Session
Introduction to RSpec 1. Test, RSpec
Introduction to bit operation
Introduction to Ratpack (6) --Promise
Introduction to Ratpack (9) --Thymeleaf
Introduction to PlayFramework 2.7 ① Overview
Introduction to Android Layout
Introduction to design patterns (introduction)
Introduction to Practical Programming
Introduction to javadoc command
Introduction to jar command
Introduction to Ratpack (2)-Architecture
Introduction to lambda expression
Introduction to java command
Introduction to RSpec 2. RSpec setup
Introduction to Keycloak development
Introduction to javac command
Introduce swagger-ui to REST API implemented in Spring Boot
Introduction to Design Patterns (Builder)
Introduction to RSpec 5. Controller specs
Introduction to RSpec 6. System specifications
Introduction to Android application development
Introduction to RSpec 3. Model specs
Introduction to Ratpack (5) --Json & Registry
Introduction to Metabase ~ Environment Construction ~
Introduction to Ratpack (7) --Guice & Spring
(Dot installation) Introduction to Java8_Impression
Introduction to Design Patterns (Composite)
Introduction to JUnit (study memo)
Introduction to Spring Boot ① ~ DI ~
Introduction to design patterns (Flyweight)
[Java] Introduction to lambda expressions
Introduction to Spring Boot ② ~ AOP ~
What I was addicted to with the Redmine REST API
Introduction to design patterns Prototype
GitHub Actions Introduction to self-made actions
REST API testing with REST Assured
Introduction to Design Patterns (Iterator)
Introduction to Spring Boot Part 1
Introduction to Ratpack (1) --What is Ratpack?
XVim2 introduction memo to Xcode12.3
Introduction to RSpec-Everyday Rails Summary-
Introduction to Design Patterns (Strategy)
[Introduction to rock-paper-scissors games] Java
Introduction to Linux Container / Docker (Part 1)
Spring with Kotorin --4 REST API design
Introduction to swift practice output Chapter5
[Introduction to Java] About lambda expressions