第69章 HL7


HL7 コンポーネント

HL7 コンポーネントは、HAPI ライブラリー を使用して HL7 MLLP プロトコルおよび HL7 v2 メッセージ を操作するために使用されます。
このコンポーネントは以下をサポートします。
  • HL7 MLLP codec ( Mina)
  • Camel 2.15 以降の Netty4 の HL7 MLLP コーデック
  • HAPI および文字列間の 型コンバーター
  • HAPI ライブラリーを使用した HL7 DataFormat
  • さらに使いやすいため、105章MINA2 - 非推奨 コンポーネントと統合されています。
Maven ユーザーは、このコンポーネントの pom.xml に以下の依存関係を追加する必要があります。
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-hl7</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
Copy to Clipboard Toggle word wrap

Camel on EAP デプロイメント

このコンポーネントは、Red Hat JBoss Enterprise Application Platform (JBoss EAP) コンテナー上で簡素化されたデプロイメントモデルを提供する Camel on EAP (Wildfly Camel) フレームワークによってサポートされます。このモデルの詳細は、Deploying into a Web Server の Apache Camel on JBoss EAP の章を参照してください

HL7 MLLP プロトコル

HL7 は、テキストベースの TCP ソケットベースのプロトコルである HL7 MLLP プロトコルでよく使用されます。このコンポーネントには、MLLP プロトコルに準拠する Mina および Netty4 Codec が同梱されるため、TCP トランスポート層で HL7 リクエストを受け入れる HL7 リスナーを簡単に公開できます。
HL7 リスナーサービスを公開するには、camel-mina2 または camel-netty4 コンポーネントが HL7MLLPCodec (mina2)または HL7MLLPNettyDecoder/HL7MLLPNettyEncoder (Netty4)とともに使用されます。
HL7 MLLP コーデックには、以下のオプションがあります。
Expand
名前 デフォルト値 説明
startByte 0x0b HL7 ペイロードにまたがる開始バイト。
endByte1 0x1c HL7 ペイロードにまたがる最初のエンドバイト。
endByte2 0x0d HL7 ペイロードにまたがる 2 番目の終了バイト。
charset JVM のデフォルト codec に使用するエンコーディング( 文字セット名)。指定しない場合、Camel は JVM のデフォルト Charset を 使用します。
produceString true Camel 2.14.1: true の場合、コーデックは定義された charset を使用して文字列を作成します。false の場合、コーデックはプレーンなバイトアレイをルートに送信し、HL7 Data Format が HL7 メッセージコンテンツから実際の文字セットを決定できるようにします。
convertLFtoCR false は、\n\r (0x0d、13 進数)に変換します。HL7 は、セグメントターミネーターとして \r を使用します。HAPI ライブラリーには \r を使用する必要があります。

Mina を使用した HL7 リスナーの公開

Spring XML ファイルでは、ポート 8888 で TCP を使用して HL7 要求をリッスンするように Mina2 エンドポイントを設定します。
<endpoint id="hl7MinaListener" uri="mina2:tcp://localhost:8888?sync=true&amp;codec=#hl7codec"/>
Copy to Clipboard Toggle word wrap
sync=true は、このリスナーが同期されているため、呼び出し元に HL7 応答を返すことを示します。HL7 コーデックが codec=#hl7codec で設定されている。hl7codec は Spring Bean ID であるため、mygreatcodecforhl7 または任意の名前を付けることができます。codec も Spring XML ファイルで設定されます。
    <bean id="hl7codec" class="org.apache.camel.component.hl7.HL7MLLPCodec">
        <property name="charset" value="iso-8859-1"/>
    </bean>
Copy to Clipboard Toggle word wrap
この Java DSL の例が示すように、エンドポイント hl7MinaListener はルートでコンシューマーとして使用できます。
    from("hl7MinaListener").beanRef("patientLookupService");
Copy to Clipboard Toggle word wrap
これは、HL7 をリッスンし、HL7 という名前のサービスにルーティングする非常に単純 なルートです。これは Spring Bean ID で、以下のように Spring XML で設定されます。
    <bean id="patientLookupService" class="com.mycompany.healthcare.service.PatientLookupService"/>
Copy to Clipboard Toggle word wrap
Camel のもう 1 つの強力な機能は、以下のように Camel に関連付けられていない POJO クラスにビジネスロジックを持つことができることです。
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v24.segment.QRD;

public class PatientLookupService {
    public Message lookupPatient(Message input) throws HL7Exception {
        QRD qrd = (QRD)input.get("QRD");
        String patientId = qrd.getWhoSubjectFilter(0).getIDNumber().getValue();

        // find patient data based on the patient id and create a HL7 model object with the response
        Message response = ... create and set response data
        return response
    }
Copy to Clipboard Toggle word wrap
このクラスは Camel からではなく HAPI ライブラリーからのインポートのみを使用することに注意してください。

Netty を使用した HL7 リスナーの公開(Camel 2.15 以降から利用可能)

Spring XML ファイルでは、ポート 8888 で TCP を使用して HL7 リクエストをリッスンするように Netty4 エンドポイントを設定します。
<endpoint id="hl7NettyListener" uri="netty4:tcp://localhost:8888?sync=true&amp;encoder=#hl7encoder&amp;decoder=#hl7decoder"/>
Copy to Clipboard Toggle word wrap
sync=true このリスナーが同期されているため、呼び出し元に HL7 応答を返すことを示します。HL7 コーデックは、encoder=#hl7encoder および decoder=#hl7decoder で設定されます。hl7encoder および hl7decoder は Bean ID のみであるため、名前が異なる可能性があることに注意してください。Bean は Spring XML ファイルで設定できます。
<bean id="hl7decoder" class="org.apache.camel.component.hl7.HL7MLLPNettyDecoderFactory"/>
<bean id="hl7encoder" class="org.apache.camel.component.hl7.HL7MLLPNettyEncoderFactory"/>
Copy to Clipboard Toggle word wrap
この Java DSL の例が示すように、hl7NettyListener エンドポイントはコンシューマーとしてルートで使用できます。
from("hl7NettyListener").beanRef("patientLookupService");
Copy to Clipboard Toggle word wrap

java.lang.String または byte[] を使用した HL7 モデル

HL7 MLLP コーデックは、プレーン String をデータ形式として使用します。Camel は Type Converter を使用して文字列を HAPI HL7 モデルオブジェクトに変換しますが、データを独自に解析する場合は、プレーン String オブジェクトを使用できます。
Camel 2.14.1 の時点で、produceString プロパティーを false に設定すると、Mina および Netty コーデックの両方がプレーン byte[] をデータ形式として使用することもできます。Type Converter は、byte[] を HAPI HL7 モデルオブジェクトとの間で変換することもできます。

HAPI を使用した HL7v2 モデル

HL7v2 モデルは、HAPI ライブラリーの Java オブジェクトを使用します。このライブラリーを使用すると、HL7v2 で主に使用される EDI 形式(ER7)からエンコードおよびデコードできます。
以下の例は、リフォルト ID 0101701234 で発行者を検索するリクエストです。
MSH|^~\\&|MYSENDER|MYRECEIVER|MYAPPLICATION||200612211200||QRY^A19|1234|P|2.4
QRD|200612211200|R|I|GetPatient|||1^RD|0101701234|DEM||
Copy to Clipboard Toggle word wrap
HL7 モデルを使用すると、ca.uhn.hl7v2.model.Message オブジェクトを使用して作業できます。 たとえば、音声 ID を取得することができます。
Message msg = exchange.getIn().getBody(Message.class);
QRD qrd = (QRD)msg.get("QRD");
String patientId = qrd.getWhoSubjectFilter(0).getIDNumber().getValue();  // 0101701234
Copy to Clipboard Toggle word wrap
byte[], String またはその他の単純なオブジェクト形式を使用する必要がないため、HL7 リスナーと組み合わせると便利です。HAPI HL7v2 モデルオブジェクトのみを使用できます。事前にメッセージタイプが分かっている場合は、よりタイプセーフになります。
QRY_A19 msg = exchange.getIn().getBody(QRY_A19.class);
String patientId = msg.getQRD().getWhoSubjectFilter(0).getIDNumber().getValue();
Copy to Clipboard Toggle word wrap

HL7 DataFormat

HL7 コンポーネントには、HL7 モデルオブジェクトのマーシャリングまたはアンマーシャリングに使用できる HL7 データフォーマットが同梱されています。
  • marshal = メッセージからバイトストリームへ(HL7 MLLP コーデックを使用して応答する場合に使用できます)
  • unmarshal = バイトストリームからメッセージへ(HL7 MLLP からストリームデータを受信する場合に使用できます)
データフォーマットを使用するには、インスタンスをインスタンス化し、ルートビルダーで marshal または unmarshal 操作を呼び出します。
DataFormat hl7 = new HL7DataFormat();
...
from("direct:hl7in").marshal(hl7).to("jms:queue:hl7out");
Copy to Clipboard Toggle word wrap
上記の例では、HL7 は HAPI Message オブジェクトからバイトストリームにマーシャリングされ、JMS キューに配置されます。以下の例は、逆になります。
DataFormat hl7 = new HL7DataFormat();
...
from("jms:queue:hl7out").unmarshal(hl7).to("patientLookupService");
Copy to Clipboard Toggle word wrap
ここでは、プロキシールックアップサービスに渡される HAPI Message オブジェクトにバイトストリームをアンマーシャリングします。
注記
HAPI 2.0 (Camel 2.11 で使用される)の時点で、HL7v2 モデルクラスは完全にシリアライズ可能です。そのため、HL7v2 メッセージを JMS キューに直接配置できます(例: marshal() を呼び出しずに)、キューから直接再度読み取ることができます(例: unmarshal()を呼び出さずに)。
重要
Camel 2.11 の時点で、unmarshal\n から \r に変換してセグメント区切り文字を自動的に修正しません。この変換が必要な場合は、org.apache.camel.component.hl7.HL7#convertLFToCR で便利な Expression が提供されます。
重要
Camel 2.14.1 の時点で、marshal および unmarshal の両方が MSH-18 フィールドで提供された charset を評価します。このフィールドが空の場合、デフォルトでは、対応する Camel charset プロパティー/ヘッダーに含まれる charset が想定されます。HL7DataFormat クラスから継承する際に guessCharsetName メソッドを上書きすると、このデフォルトの動作を変更することもできます。
Camel には、よく知られているデータ形式用の簡略化された構文があります。HL7DataFormat オブジェクトのインスタンスを作成する必要はありません。
from("direct:hl7in").marshal().hl7().to("jms:queue:hl7out");
from("jms:queue:hl7out").unmarshal().hl7().to("patientLookupService");
Copy to Clipboard Toggle word wrap

メッセージヘッダー

unmarshal 操作は、MSH セグメントから以下のフィールドを Camel メッセージのヘッダーとして追加します。
Expand
キー MSH フィールド
CamelHL7SendingApplication MSH-3 MYSERVER
CamelHL7SendingFacility MSH-4 MYSERVERAPP
CamelHL7ReceivingApplication MSH-5 MYCLIENT
CamelHL7ReceivingFacility MSH-6 MYCLIENTAPP
CamelHL7Timestamp MSH-7 20071231235900
CamelHL7Security MSH-8 null
CamelHL7MessageType MSH-9-1 ADT
CamelHL7TriggerEvent MSH-9-2 A01
CamelHL7MessageControl MSH-10 1234
CamelHL7ProcessingId MSH-11 P
CamelHL7VersionId MSH-12 2.4
CamelHL7Context -
Camel 2.14: メッセージの解析に使用された HapiContext が含まれます。
CamelHL7Charset MSH-18
Camel 2.14.1: Unicode UTF-8
CamelHL7Context 以外のヘッダーはすべて String 型です。ヘッダー値がない場合、その値は null になります。

オプション

HL7 データ形式は以下のオプションをサポートします。
Expand
オプション デフォルト 説明
validate true デフォルトの検証ルールを使用して HAPI Parser がメッセージを検証するかどうか。parser オプションまたは hapiContext オプションを使用して、目的の HAPI ValidationContext で初期化することが推奨されます。
parser ca.uhn.hl7v2.parser.GenericParser 使用されるカスタムパーサー。タイプ ca.uhn.hl7v2.parser.Parser である必要があります。GenericParser では、XML でエンコードされた HL7v2 メッセージの解析も許可されることに注意してください。
hapiContext ca.uhn.hl7v2.DefaultHapiContext
Camel 2.14: カスタムパーサー、カスタム ValidationContext などを定義できるカスタム HAPI コンテキスト。これにより、HL7 の解析およびレンダリングプロセスを完全に制御できます。

Dependencies

Camel ルートで HL7 を使用するには、上記の camel-hl7 の依存関係を追加して、このデータ形式を実装する必要があります。
HAPI ライブラリーは、HL7v2 メッセージバージョンごとに 1 つずつ、ベースライブラリー と複数の構造ライブラリーに分割されました。
デフォルトでは、camel-hl7 は HAPI ベースライブラリー のみを参照します。アプリケーションは、構造ライブラリー自体を含めます。たとえば、アプリケーションが HL7v2 メッセージバージョン 2.4 および 2.5 で機能する場合は、以下の依存関係を追加する必要があります。
<dependency>
    <groupId>ca.uhn.hapi</groupId>
    <artifactId>hapi-structures-v24</artifactId>
    <version>2.2</version>
    <!-- use the same version as your hapi-base version -->
</dependency>
<dependency>
    <groupId>ca.uhn.hapi</groupId>
    <artifactId>hapi-structures-v25</artifactId>
    <version>2.2</version>
    <!-- use the same version as your hapi-base version -->
</dependency>
Copy to Clipboard Toggle word wrap
または、ベースライブラリーを含む OSGi バンドル、すべての構造ライブラリーおよび必要な依存関係(バンドルクラスパス上)は、中央の Maven リポジトリー からダウンロードできます。
<dependency>
    <groupId>ca.uhn.hapi</groupId>
    <artifactId>hapi-osgi-base</artifactId>
    <version>2.2</version>
</dependency>
Copy to Clipboard Toggle word wrap

Terser 言語

HAPI は、一般的に使用される場所の仕様構文を使用してフィールドへのアクセスを提供する Terser クラスを提供します。Terser 言語を使用すると、この構文を使用してメッセージから値を抽出し、フィルターリング、コンテンツベースのルーティングなどの式および述語として使用できます。
例:
import static org.apache.camel.component.hl7.HL7.terser;
...

   // extract patient ID from field QRD-8 in the QRY_A19 message above and put into message header
   from("direct:test1")
      .setHeader("PATIENT_ID",terser("QRD-8(0)-1"))
      .to("mock:test1");
   // continue processing if extracted field equals a message header
   from("direct:test2")
      .filter(terser("QRD-8(0)-1").isEqualTo(header("PATIENT_ID"))
      .to("mock:test2");
Copy to Clipboard Toggle word wrap

HL7 検証述語

多くの場合、HL7v2 メッセージを解析し、別のステップで HAPI ValidationContext に対して検証することが推奨されます。
例:
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;
...

  // Use standard or define your own validation rules
   ValidationContext defaultContext = new DefaultValidation(); 

   // Throws PredicateValidationException if message does not validate
   from("direct:test1").validate(messageConformsTo(defaultContext)).to("mock:test1");
Copy to Clipboard Toggle word wrap

HapiContext (Camel 2.14)を使用した HL7 検証述語

HAPI コンテキストは常に ValidationContext (または ValidationRuleBuilder)で設定されているため、検証ルールに間接的にアクセスできます。さらに、HL7DataFormat のマーシャリングを解除すると、CamelHL7Context header で設定された HAPI コンテキストが転送され、このコンテキストの検証ルールを簡単に再利用できます。
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import static org.apache.camel.component.hl7.HL7.messageConforms
...

  HapiContext hapiContext = new DefaultHapiContext();
  hapiContext.getParserConfiguration().setValidating(false); // don't validate during parsing
  
  // customize HapiContext some more ... e.g. enforce that PID-8 in ADT_A01 messages of version 2.4 is not empty
  ValidationRuleBuilder builder = new ValidationRuleBuilder() {
      @Override
      protected void configure() {
         forVersion(Version.V24)
              .message("ADT", "A01")
              .terser("PID-8", not(empty()));
         }
      };
  hapiContext.setValidationRuleBuilder(builder);

  HL7DataFormat hl7 = new HL7DataFormat();
  hl7.setHapiContext(hapiContext);

  from("direct:test1")
     .unmarshal(hl7)                // uses the GenericParser returned from the HapiContext
     .validate(messageConforms())   // uses the validation rules returned from the HapiContext
                                    // equivalent with .validate(messageConformsTo(hapiContext))
     // route continues from here
Copy to Clipboard Toggle word wrap

HL7 確認式

HL7v2 処理の一般的なタスクは、たとえば検証結果に基づいて、受信 HL7v2 メッセージへの応答として確認応答メッセージを生成することです。ack 式は、この処理を非常に重要に達成できます。
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import static org.apache.camel.component.hl7.HL7.ack;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;
...

  // Use standard or define your own validation rules
   ValidationContext defaultContext = new DefaultValidation(); 

   from("direct:test1")
      .onException(Exception.class)
         .handled(true)
         .transform(ack()) // auto-generates negative ack because of exception in Exchange
         .end()
      .validate(messageConformsTo(defaultContext))
      // do something meaningful here
      ...
      // acknowledgement
      .transform(ack())
Copy to Clipboard Toggle word wrap

追加のサンプル

以下の例では、プレーンの String HL7 リクエストが応答を返す HL7 リスナーに送信されます。
String line1 = "MSH|^~\\&|MYSENDER|MYRECEIVER|MYAPPLICATION||200612211200||QRY^A19|1234|P|2.4";
String line2 = "QRD|200612211200|R|I|GetPatient|||1^RD|0101701234|DEM||";

StringBuilder in = new StringBuilder();
in.append(line1);
in.append("\n");
in.append(line2);

String out = (String)template.requestBody("mina2:tcp://127.0.0.1:8888?sync=true&codec=#hl7codec", in.toString());
Copy to Clipboard Toggle word wrap
次の例では、HL7 リスナーからの HL7 リクエストはビジネスロジックにルーティングされ、これはレジストリーに登録されているプレーン POJO として hl7service として実装されます。
public class MyHL7BusinessLogic {

    // This is a plain POJO that has NO imports whatsoever on Apache Camel.
    // its a plain POJO only importing the HAPI library so we can much easier work with the HL7 format.

    public Message handleA19(Message msg) throws Exception {
        // here you can have your business logic for A19 messages
        assertTrue(msg instanceof QRY_A19);
        // just return the same dummy response
        return createADR19Message();
    }

    public Message handleA01(Message msg) throws Exception {
        // here you can have your business logic for A01 messages
        assertTrue(msg instanceof ADT_A01);
        // just return the same dummy response
        return createADT01Message();
    }
}
Copy to Clipboard Toggle word wrap
その後、RouteBuilder を使用する Camel ルートは以下のようになります。
DataFormat hl7 = new HL7DataFormat();
// we setup or HL7 listener on port 8888 (using the hl7codec) and in sync mode so we can return a response
from("mina2:tcp://127.0.0.1:8888?sync=true&codec=#hl7codec")
    // we use the HL7 data format to unmarshal from HL7 stream to the HAPI Message model
    // this ensures that the camel message has been enriched with hl7 specific headers to
    // make the routing much easier (see below)
    .unmarshal(hl7)
    // using choice as the content base router
    .choice()
        // where we choose that A19 queries invoke the handleA19 method on our hl7service bean
        .when(header("CamelHL7TriggerEvent").isEqualTo("A19"))
            .beanRef("hl7service", "handleA19")
            .to("mock:a19")
        // and A01 should invoke the handleA01 method on our hl7service bean
        .when(header("CamelHL7TriggerEvent").isEqualTo("A01")).to("mock:a01")
            .beanRef("hl7service", "handleA01")
            .to("mock:a19")
        // other types should go to mock:unknown
        .otherwise()
            .to("mock:unknown")
    // end choice block
    .end()
    // marshal response back
    .marshal(hl7);
Copy to Clipboard Toggle word wrap
HL7 DataFormat を使用すると、Camel メッセージヘッダーに MSH セグメントからのフィールドが入力されることに注意してください。ヘッダーは、上記の例のように、フィルターリングまたはコンテンツベースのルーティングに特に便利です。
トップに戻る
Red Hat logoGithubredditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。 最新の更新を見る.

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

Theme

© 2025 Red Hat