Ringholm-Logo Ringholm
 Whitepaper
Ringholm page header
Training    Services   |   Whitepapers    Blog    Events    Links   |   About us    Partners    Clients    Contact

A Java-based RIMBAA Reference Implementation

The contents of this whitepaper are published under the Creative Commons Attribution-Share Alike license.
See http://www.ringholm.com/docs/03110_en_HL7_RIMBAA_Java_Reference_Implementation.htm for the latest version of this document.
Author: René Spronk, Sr. consultant
Document status: Draft, version 0.8 (2009-04-23)
Please send questions and comments to rene.spronk@ringholm.com.


Summary

The open source Java-based RIMBAA reference implementation serves as an example of the use of the HL7 RIM as the basis for an application architucture. It supports the HL7 RIM both at the persistence layer as well as at the in-memory business object layer.

1. Introduction

This paper assumes the reader is familiar with the basic concepts of RIMBAA, as well as the "Technology Matrix".

The open source Java-based RIMBAA reference implementation was created years before the term RIMBAA was even introduced. The reference implementation was (and is) mostly referred to using the previous name of the responsible working group in HL7: Java SIG. The name was changed from Java SIG in June 2008 to RIMBAA to reflect its scope, which is about the use of the RIM as an architectural model, and not primarily about the Java programming language.

Peter Hendler, one of the co-chairs of The Java SIG/RIMBAA explains some of the background of the Java SIG and the reference implementation in the following interview:

2. Reference Java RIMBAA implementation

The HL7 RIMBAA group has created a Java based reference implementation. The architecture of this implementation is based on the RP-RO-CS cells (as defined in the "Technology Matrix").

The work product starts in RO and uses an object-relational mapping solution (Hibernate) for the transition to RP. When it comes to the RP cell the reference implementation uses the Table per Hierarchy strategy. All internal objects are completely RIM based. We use Hibernate to generate the Schema for the database, and it is also used to persist the RIM objects. The transition between RO to CS is supported using MIFs (the reference implementation contains a MIF parsing API). The direct transition from RO to CS is the most complex part of the API and at every step it is guided by the parsed MIF file.

It works almost perfectly in the direction from CS to RO, it works almost perfectly between RP and RO using Hibernate, and it works fairly well in the direction of RO to CS. The V3 XML generated is 90% plus perfect but there are little quirks which require tweaking. The XML generated is so close to correct it can be mostly be tweaked using XSLT.

The advantage of using an object-relational mapping tool is the fact that database queries can be formulated using RIM classes/attributes. All SQL-details are hidden from the programmer. The following is an example of an SQL statement (RP style) that, based on the CDA model expressed in pure RIM terms, will pull all pulmonary function test results for patient 1234567 from the pure RIM based database:

 

MIF

What’s the MIF, and how is it used in this context? The MIF (model interchange format) is a full definition of an abstract message model. MIFs are generated from the HL7 version 3 model repository which contains all RIM-derived models published in the HL7 version 3 standard.

CO and RO may be generated based on MIFs (a formal description of RIM-based models) or on XML-schema (a derivation of the MIF).

   SELECT  new list(i.extension, name.givenName, name.familyName, clinicalStatement.value, 
     clinicalStatement.value.unit,  clinicalStatement.code.displayName) 
    FROM PatientImpl patient 
    INNER JOIN patient.id AS i
    inner join patient.player as person
    inner join person.name as name
    inner join patient.participation as part
    inner join part.act as document
    inner join document.outboundRelationship as component
    inner join component.target as body
    inner join body.outboundRelationship as component2
    inner join component2.target as section
    inner join section.outboundRelationship as entry
    inner join entry.target as clinicalStatement
    where component.typeCode='COMP' 
      and i.extension='1234567'

Advertisement for Ringholm training.

Another example which pulls all of the "Glucose Level" (using its code 64544) values from the pure RIM based database:
    SELECT DISTINCT obs.Value_Number AS number, 'mg/dl' AS units,  
      SUBSTR(obs.Effectivetime_low,5,4) AS time, patientid.extension AS patientid 
    FROM ACT obs
    INNER JOIN PARTICIPATION participant ON(obs.internalId = participant.actInternalId)
    INNER JOIN Role_id patientid ON(patientid.roleInternalId = participant.roleInternalId)
    WHERE  obs.Code_code = '64544' 
       AND patientid.root ='2.16.840.1.113883.19.5'
       AND patientid.extension =  '12345'
Does the use of large numbers of Joins scale, without additional tuning of the database? Part of the answer is to automatically "conduct" a copy of certain data elements (e.g. the patient identifier) to an optional more proximal spot in memory before you do the query - the logic of adding/overriding context would be a nightmare to do in a query. That eliminates the majority of the joins. It takes some time in memory to do the context conduction when we are processing the message before we persist it. Once it's persisted we can get what we want with fewer joins.

The above query examples are relatively simple, a production system would more likely retrieve lists of clinicalStatement objects (see first example) instead of a list of string and number values. The query language used allows you to query for any object.

For any given use case, you can create a one off database that would perform better, but then you need a different schema for each use case. One of the big advantages of a RIMBAA approach is that you use the same schema for everything. You might sacrifice some performance, but you'd avoid creating countless new schemas. So we might be willing to sacrifice some peformance for the saved costs of not having to create and maintain numerous database schemas though out the enterprise.

Generating messages is really not that hard to accomplish if you have the data. Using any one of a number of XML generating API's (RO to CS) you create the XML which can be sent. Receiving any data if it's in HL7 V3 format is also not complicated - if you have the corresponding MIF file it will "magically" be converted to RO objects and magically transition to RP cell.

3. See also


About Ringholm bv

Ringholm bv is a group of European experts in the field of messaging standards and systems integration in healthcare IT. We provide the industry's most advanced training courses and consulting on healthcare information exchange standards.
See http://www.ringholm.com or call +31 33 7 630 636 for additional information.