HAPI FHIR JPA Serverのプロジェクトを立ち上げるまでの軌跡

HAPI FHIR JPA Serverを使ってHL7-FHIR®︎準拠のRESTful APIサーバを立ち上げることになった。
HAPI FHIRはJava製のOSSで、オープンソースのFHIRサーバの中で歴史が長く最もポピュラーなもの。
Plain ServerとJPA Serverがあり、前者は既存のヘルスケアレコードをFHIR形式にマッピングすることに特化したFaçade型FHIRサーバ用のパッケージで、後者はFHIR専用の永続化DBを保持するRepository型FHIRサーバ用のパッケージとなっている。
今回はFHIR専用DBを保持するHAPI FHIR JPA Serverを一から構築しようと思う。
実は僕はPythonとRustをかじったことがある程度の日曜プログラマで、Javaは初心者だしデータベースも何もわからん状態である。さらにFHIRサーバについては日本国内の情報が皆無であり、暗中模索状態となることが予想される。
少しでも人の目に触れることで、あわよくば助けてもらおう、という淡い期待を込め、開発記録をここに残していく。

今回DBMSにPostgresSQLを採用する。
HAPI-FHIRのDocumentによれば、JPA Serverは
- SQL Server
- PostgresSQL
- Oracle
のみに対応しているようで、かろうじてPostgresSQLのみ馴染みがあった、というくらいの選定理由である。
「まずは動くものを」というのが人間の性、早速starterキットを見つけた。

上記のレポジトリを会社のGitHubアカウントにフォークした。
README.md
にPostgresSQLを使用する場合のdocker-compose.yml
とhapi.aplication.yaml
の例が書かれているので、その通りに動かしてみる。hapi.application.yaml
はレポジトリにはなかったので新たに作る。
docker-compose.yml
version: '3.7'
services:
fhir:
container_name: fhir
image: "hapiproject/hapi:latest"
ports:
- "8080:8080"
configs:
- source: hapi
target: /app/config/application.yaml
depends_on:
- db
db:
image: postgres
restart: always
environment:
POSTGRES_PASSWORD: admin
POSTGRES_USER: admin
POSTGRES_DB: hapi
volumes:
- ./hapi.postgress.data:/var/lib/postgresql/data
configs:
hapi:
file: ./hapi.application.yaml
hapi.aplication.yaml
spring:
datasource:
url: 'jdbc:postgresql://db:5432/hapi'
username: admin
password: admin
driverClassName: org.postgresql.Driver
jpa:
properties:
hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect
hibernate.search.enabled: false
これで準備ができた。動作確認をしてみよう。
$ docker compose up
fhir | 2023-07-02 11:38:29.548 [main] ERROR com.zaxxer.hikari.pool.HikariPool [HikariPool.java:594] HikariPool-1 - Exception during pool initialization.
fhir | org.postgresql.util.PSQLException: Connection to db:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
fhir | at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:319)
fhir | at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
fhir | at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:247)
fhir | at org.postgresql.Driver.makeConnection(Driver.java:434)
fhir | at org.postgresql.Driver.connect(Driver.java:291)
fhir | at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
fhir | at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359)
fhir | at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201)
DBへのアクセスが拒否されたとのエラーを吐いているが、dockerイメージの初回ビルド時にPostgresDBの立ち上がりがHAPI FHIRの立ち上がりに間に合わなかった様子。一度ctrl-Cして、もう一度起動したらうまくいった。(本来はfhirのdepends onのところにconditionを指定した方が良い。)
ブラウザから、http://localhost:8080/fhir/metadata にアクセスし、以下のような画面が出たため、ひとまずは成功したようだ。
ちなみに http://localhost:8080/fhir/Patient のResponseはnullとなる。PostgresSQLの中身は当然空という意味である。要するに、自分でデータを移行しなければならない。

次はどんな仕組みで動いているのかを明らかにしたい。仕組みがわかれば応用性が増す。
公式DocumentにHAPI FHIR JPA Serverのアーキテクチャが記されている。これによれば、
- HAPI RESTful Server
- Resource Providers
- HAPI DAOs
- Hibernate
- Database
という大きなコンポーネントが分かれているようだ。何となくの予想ではあるが、それぞれをしっかり理解するのが近道に感じる。

Resource Providersとは
Resource ProviderはHL7-FHIR®︎のリソースと1対1対応のシンプルなJavaクラスで、readやsearchなどリソースに対する操作が実装されている。
と、書きはしたが、データベースに対する細かいロジックがResource Providerに実装されている訳ではない。Resource ProviderはHAPI RESTful Serverから渡されたリクエストをHAPI DAOs以下に流しているだけである。
実際の実装を理解する
HAPI FHIR JPA ServerはSpring Frameworkが使われている。そのためSpring Frameworkへの理解が基礎となる。Spring Frameworkについて何も分からん自分にとっては、一旦Spring Frameworkの勉強が必要と感じた。HAPI FHIR JPA ServerにおけるSpring Frameworkの使われ方を理解するという別のスクラップで学んでいくことにする。