Wiki

Clone wiki

javarosa / OpenMRSDemo

JavaRosa/OpenMRS Integration Demo

This document describes the steps needed to get integrate JavaRosa's form submissions with OpenMRS's XForms module.

Setting Up OpenMRS

In order for JavaRosa to successfully submit to OpenMRS, an instance of OpenMRS must be successfully installed and running on a server with a public IP address.

The Specific Requirements for the version of OpenMRS's XForm submission described in this document are:

Some important things to configure about the server before it can work:

  • Getting OpenMRS to run in Linux is tricky (due to a lot of implicit files, properties, and configurations that need to exist before it can work properly), but possible. Getting it running on Windows is generally a bit easier if the option is available. There's a good set of helping instructions for running Tomcat on linux [http://openmrs.org/wiki/Troubleshooting_Tomcat here].
  • The modules write files to the local filesystem that will need to be writeable by whatever user the tomcat service is running under. The location of this directory can be configured in the appropriate modules, but is generally in /opt/ on Linux.

Setting up JavaRosa

In order to submit forms to OpenMRS, JavaRosa submits forms as usual as an HTTP POST to a server URL, but utilizes an XForm which is capable of producing an XML instance which the XForms module can use to create OpenMRS encounters.

The URL used to submit to the XForms module (assuming tomcat is running on port 8080) should be set to

http://url.to.your.server:8080/openmrs/moduleServlet/xforms/xformDataUpload?batchEntry=false&uname=admin&pw=test

Creating an OpenMRS XForm

XForms which are submitted from JavaRosa to the server need to follow a certain format in order to be usable by OpenMRS. This includes both the OpenMRS Form XML (encounter/obs/etc xml blocks) as well as XForm Module specific XML. The working example is a pregnancy registration (registering both a pregnant mother and a pregnancy encounter), so that is the example which will be covered in this document.

The sample xform which successfully registers a new mother as a patient in OpenMRS along with a birth encounter is attached along with this document.

OpenMRS Configuration

Keep in mind that OpenMRS must be properly configured with the underlying definitions of any data submitted. Provider/Location/Patient Identifier Types/etc must all be defined in the OpenMRS concept dictionary and other respective locations before they will be recognized in submitted data.

Additionally, the forms you submit must be defined in the Form Import/Export module in order for them to be received.

XForms Tricks

Since OpenMRS and the various modules want a fair amount of redundant data, and want data in a very rigid format, writing XForms to submit to them is a bit tricky. There are a few tricks, though, which make writing xforms for the template instances much easier.

  • Using <bind ... calculate=""/> nodes is an invaluable tool for providing redundant data. providing an xpath to another node (IE:/my_xml/patient/id) will let you copy that node's value into the value of the bound node easily.
  • Calculate can also help you to expand the value of multi-select nodes into independent values. Although XForms standards encode multi-selects into a single node, OpenMRS often wants the result of different possible values in an expanded format like:
    <medications openmrs_concept="13^MEDICATIONS^99DCT" openmrs_datatype="CWE" multiple="0">
        <date xsi:nil="true"/>
        <time xsi:nil="true"/>
        <penicillin openmrs_concept="4322^PENICILLIN^99DCT"/>
        <cipro openmrs_concept="442^CIPROFLOXACIN^99DCT"/>
        <azithromycin openmrs_concept="3152^AZITHROMYCIN^99DCT"/>
        <other openmrs_concept="2543^OTHER^99DCT"/>
    </medications>

JavaRosa can populate each of these nodes by placing the value of the multi-select into a throwaway node in the instances, then a set of calculate binds such as

    <bind nodeset="../medications/penicillin" calculate="if(selected('../scratch/medications_answer','penicillin'),'true','false'"/>
    <bind nodeset="../medications/cipro " calculate="if(selected('../scratch/medications_answer','cipro'),'true','false'"/>

XForm Module Specific Code

The XForms module requires a couple of code blocks to be configured before OpenMRS can properly accept the submission, create a user, and then forward the form along to the form import module. Namely, it requires (at the root level) a '''Patient''' node with specific children. It also requires the form interaction to be wrapped in a '''Form''' node. The '''Form''' node must also contain a '''header''' to provide information about the session.

An example XML structure that needs to exist for the module to work (With commentary):

       <patient id="0" xmlns=" " >  
         <enterer/>                            <!-- OpenMRS ID of the person entering the form -->
         <location_id />                       <!-- OpenMRS ID of location of patient -->
         <patient_identifier_type_id />        <!-- OpenMRS ID type for patient's ID-->
         <family_name />                         
	 <given_name />
	 <birth_date />
 	 <identifier />                        <!-- Identifier of patient in the format specified by patient_identifier_type_id-->
 	 <patient.patient_id />                <!-- Same as previous value -->
 	 <patient_id />                        <!-- Same as previous value -->
 	 <gender />                            <!-- Should be set to 'F', not a snowmed or other concept definition for gender -->
      </patient>
      <form id="14" name="Birth Registration Form" version="0.9" xmlns=" " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:openmrs="http://localhost:8080/openmrs/moduleServlet/formentry/forms/schema/14-13" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"> <!-- The form id should correspond to a schema registered in OpenMRS -->
          <header xmlns=" "> <!-- Header for the actual form -->
             <date_entered/> <!-- Don't set -->
             <session/>      <!-- Don't set -->
             <uid/>          <!-- Don't set -->
             <enterer/>      <!-- Set to the same value as the enterer in the <patient> block -->  
         </header>
      <!-- OpenMRS Encounter/Data Models Go Here -->
      </form>

OpenMRS XML Encounter Data

Inside of the <form></form> block, the Form Import module expects xml in a format which is imported into OpenMRS directly by table (observation, encounter, etc). Some of this data can be set by whatever information is attempting to be provided by your form, and some of it is required by the modules in order to work. Specifically, certain values for the encounter and patient are required.

An example of the required encounter and patient blocks with commentary:

  <encounter xmlns=" " >
    <encounter.encounter_datetime openmrs_table="encounter" openmrs_attribute="encounter_datetime"/>  <!-- The time of the encounter. Make sure is a xsd:dateTime, not just a Date-->
    <encounter.location_id openmrs_table="encounter" openmrs_attribute="location_id"/>                <!-- The OpenMRS location ID for where the encounter took place -->
    <encounter.provider_id openmrs_table="encounter" openmrs_attribute="provider_id"/>                <!-- The OpenMRS provider ID for whoever is responsible for the encounter. -->
  </encounter>
  
  <patient>
    <patient.family_name openmrs_table="patient_name" openmrs_attribute="family_name"/>               <!-- Same as in the patient block above -->
    <patient.given_name openmrs_table="patient_name" openmrs_attribute="given_name"/>                 <!-- Same as in the patient block above -->
    <patient.patient_id openmrs_table="patient" openmrs_attribute="patient_id"/>                      <!-- Same as in the patient block above --> 
  </patient>

Other than these requirements, the other nodes inside of the form definition should follow the structure defined by the XML form in OpenMRS.

Examples

Attached to this document is an XForm used to submit an xml instance for the new birth registration form in OpenMRS.

Updated