Thursday, May 31, 2012

Fixing an OpenMRS module-loading bug (and the awesomeness of the UI Framework)

First off, I should say that developing the Kenya EMR module using the UI Framework has been awesome. Being able to add and modify controllers and views without having to redeploy the module is just a massive productivity boost. Particularly when it comes to adding ajax functionality, which is really not one of my fortés, it's great to be able to quickly add a method that returns some json, write some javascript to call it, and quickly tweak the json output because I got it wrong at first. :-)

However, since the UI Framework module is still beta, I occasionally need to make some tweaks. And I've been running into a really annoying OpenMRS bug (TRUNK-3384) where whenever I update the UI Framework module, it tries to restart other modules in the wrong order, and I end up having to manually restart the App Framework and Kenya EMR modules.

So, I finally got fed up, and decided to fix it. And I hope the couple of hours I spent on it pays for itself in reduced annoyance. :-)

Wednesday, May 30, 2012

Master Facility List

I don't love Wednesdays, because I have 4+ hours of scheduled calls. There's nothing wrong with any individual call, it's when you put them together...

Anyway, after 6 hours on the phone today, I figured I'd look into a smaller task, namely writing some code to upload the master Kenya Health Facilities List into OpenMRS so I could include it in our distro as a Metadata Sharing package.

So I opened the spreadsheet up for the first time and really looked at it. It's amazing to see that all this data is codified at all. But for some reason (lack of imagination I guess) I wasn't expecting to find 8110 facilities. So, pretty awesome. But I guess I'll need some guidance about what fraction of the facility list we actually include in the database...

Tuesday, May 29, 2012

Reworked the Registration App

I spent most of today reworking the registration app based on Bill and Jan's feedback from Friday. Originally I had devoted too much code and screen real estate to showing a patient's complete visit history, which is really not relevant to the main workflow of the front desk clerk. So I've simplified things.

Also I added a header bar that we'll use whenever there's a patient selected.

I updated the demo server--comments are welcome.
user: demo
password: demo
The main To-Dos that I already know about are that:

  1. the Create Patient page needs to be based on the MoH 257 form
  2. we need Edit buttons on the patient and visit boxes on the left side
Here's a screenshot:

Friday, May 25, 2012

Check out our first demo!

Want to see a demo of the work we've been doing? Well, now you can!
username: demo
password: demo
This is a first pass at wiring everything together. Bill, Jan, Jim, and I had some discussions today, and we have a list of UI changes that I'll work on next week. One key realization is that we probably want to split what I'd previously been thinking of as one "Medical Chart" app into two: one for the clinician to document the current visit, and another for in-depth review of a patient's full history.

Another next step is to actually incorporate the MoH 257 data points, rather than the placeholder ones (weight, height, BP) I put in.

Also, sadly, setting up the demo server wasn't quite as easy as I hoped. For some reason the metadata sharing package that included the HTML Form didn't install when I uploaded the distro zip, and I had to manually create it. I'll need to look into that soon, so that others can install this demo locally just by using OpenMRS standalone plus this zip file. :-)

Thursday, May 24, 2012

Viewable progress! Development Site Now Hosted

As of yesterday, we now have a site hosted with a base installation of OpenMRS 1.9 RC4 and the MVP concept dictionary (pre-customization for the national Kenya implementation).  To be updated by Darius soon with the Kenya development.

Check it out at

(Username and password coming shortly)

Tuesday, May 22, 2012

Overriding the OpenMRS homepage

I've seen some pretty ugly attempts to override the page you see when you go to .../openmrs/index.htm. And I was in the middle of doing yet another of those ugly attempts when I remembered "Mike has done this recently...".

And good thing I asked. It turns out to be as trivial as just doing this:
 * Takes over /index.htm so users don't see the legacy OpenMRS UI
public class HomepageOverrideController {
 public String showOurHomepage() {
  return "forward:/pages/";
No need to do a homepage portlet that does a client-side redirect, or any of the other ugly things I've seen done.

Thanks, Mike, for saving me time, and preventing ugly code.

PS- If you're doing this you should also override the login page at /login.htm

Let's do some User Interface!

Just a quick note to say that after doing a lot of back-end framework-y work for the last couple of weeks, this week I'm going to be working on some front-end user-facing workflows.

Eric is working on setting up a VM suitable for OpenMRS hosting, so hopefully by the end of the week you'll be able to see a non-wireframe demo of this image.

Sunday, May 20, 2012

Metadata Sharing with OpenMRS 1.9

I included some use of the Metadata Sharing module in my end-to-end demonstration last week, but it was partly cheating because I only included Encounter Types and Visit Types in the package, and didn't include Concepts, which haven't yet been shown to work with OpenMRS 1.9.

Hey, one thing at a time.

So I just made a MDS package out of the "Vitals" HTML Form that I used for the screenshots in my last blog post. This includes concepts in it for testing purposes. (Though in practice we'll be writing our forms against MVP/CIEL dictionary codes, so our forms won't actually need to include concepts when we push them to production. We'll be pushing out the updated MVP/CIEL dictionary to our production installations some other way.)

Trying to import that package I ran into two bugs (but only two!):

  1. META-226 - getDeproxiedClass does not work right in OpenMRS 1.9
  2. META-227 - Starting in OpenMRS 1.9 you are not allowed to modify ConceptDatatypes, so we need to stop exporting/importing them
After fixing the first bug, and putting in a quick-hack workaround for the second, I was able to successfully import the MDS package.

I'm glad it was that straightforward, and we're closer than I thought to being able to use MDS with OpenMRS 1.9 for our use case. (To be fair, the database I exported from didn't have any concept mappings on the exported concepts, and I'm pretty sure those would break with a third, more significant, bug. But also to be fair, as long as we can hand-wave and say that we'll be able to update the MVP/CIEL dictionary "some other way", we won't need to deal with this.)

Thursday, May 17, 2012


A couple of days ago I joked that I was just posting text, and no pretty pictures. Today I plan to make up for that in spades. (Though I can't promise the pictures will be pretty.)

After having successfully gotten an already-filled-out HTML Form to display in the new UI Framework we're using, I still needed to allow you to fill out a form. In the end it was a lot easier than I expected, though I still want to review what I did with Mark Goodrich (current owner of the HTML Form Entry module) so we can decide whether this is really the right approach, and how best to package it up for others to use as well.

The commit is here (and more dev-related details are after the jump).

But first, here's a screenshot-based walkthrough of the whole process of filling out an HTML Form and then viewing it:

First we find a patient and open a visit for them

Clicking the "Vitals" button opens the relevant HTML Form

Voilà! The visit now contains a vitals encounter, and the "Vitals" button is gone.

Clicking on the Vitals encounter in the previous  screenshot displays it in a popup
I think it looks pretty snazzy. :-)

For our project, the two main reasons to use HTML Forms rather than just the UI Framework are that:

  1. the technology is well-tested, and behaves consistently. You don't really need to worry about a developer doing something wrong and losing form data.
  2. we can build fancy ajax-y workflows with the UI Framework where they'll provide value, but we can implement arbitrarily large forms for typical data entry tasks without too much effort, and without requiring training on the UI Framework.
(More dev details after the jump.)

Wednesday, May 16, 2012

Proposing an OpenMRS Sprint

A few days ago I mentioned a project I wish I could work on. Today I came across another one that I'd love to work on, and is important to the project in the long-run, but not before our end-of-June deliverable.

In this case, it would be great if we could have our main servers automatically get updated versions of the MVP/CIEL dictionary. (We can do this manually now, but it requires messing around with sql dumps in an annoying way.)

So, I'm proposing it as an OpenMRS sprint. Hopefully others will be able to collaborate when the time comes!

Tuesday, May 15, 2012

Embedding an HTML Form

One of the technologies we're going to be leveraging on this project is HTML Form Entry. It's a great tool, since as long as you can write HTML, it lets you quickly define forms that look exactly like you want them to, and behave consistently.

Two other great features are that it lets you build forms that refer to concepts via mappings to other terminologies, and it lets you import and export your forms via the Metadata Sharing module. Together, these features will let us collaborate remotely on developing forms against the MVP/CIEL dictionary, and also push those forms out to production without having to mess around with sql dumps. XForms and Infopath, you need to catch up :-)

Anyway, I just took the first step towards embedding an HTML Form in the new UI Framework, by creating a fragment that lets you display a filled-out HTML Form in a div. The code is here.

I apologize for my recent updates being so text-heavy (but I've been working on back-end functionality), but for a change of pace, here's what it looks like. (Yes, the form itself is not pretty. I spent exactly 0 seconds on making it look good.)

Viewing an HTML Form in a popup
The next step is to do a fragment that lets you enter forms.

By the way, I wrote the first version of the HTML Form Entry years ago alone in a very focused burst of coding. So it was pretty cool to peek today at the last few versions of the module (1.9.0-1.9.3) and see that those cover 53 fixed tickets, by 10 different people. I only did 7 of the tickets.

Thanks to Mark Goodrich for taking over the module from me. And thanks also to Cordt Byrne, Daniel Kayiwa, Dave Thomas, Ishara Premadasa, Rafal Korytkowski, Stephen Lorenz, and Wyclif Luyima for the recent ticket fixes.

Floss Over the Canyon

At OpenMRS, Burke and Paul like to tell The Story of the Floss. As of today, we have successfully tossed the dental floss across the canyon.

Less figuratively, I have done a successful end-to-end test of:
  1. Start a clean copy of OpenMRS 1.9 RC3 Standalone (with MVP/CIEL dictionary and no data)
  2. Install the Module Distro module.
  3. Upload (including some of the modules we need)
  4. Upload (including more of the modules we need, plus a MDS package)
  5. Upload (just like v2, but with a newer version of the metadata package)
  6. Verify that the modules are all loaded, and the data has been created
  7. Smile
I'm excited!

PS- Burke, if you're reading I wish that Logic 1.0 had taken the floss approach more seriously. :-)

Monday, May 14, 2012

"Distribution" now known as "Module Distro"

Since the code at list didn't like "Distribution" as a module name, I've renamed it to "Module Distro". (The "Module Distro module", whose package is org.openmrs.module.moduledistro. Doesn't exactly trip off the tongue...)

Anyway, the code lives at and you can find the first (completely undocumented) release on the OpenMRS module repository.

A day of staring at the debugger...

Today I sat down to see how well the Metadata Sharing module works with OpenMRS 1.9. We really wan to use OpenMRS 1.9 (to take advantage of the new data model for Visits) and we also want to use MDS (to help us package up new versions of our application content), but they don't fully work together yet.

In the long run we want to use MDS to publish versioned packages containing the metadata and content that makes our application work. I figure we'll have a package for core stuff like Encounter Types, Visit Types, etc, one package for the master list of Locations, and another that contains forms, concepts, and reports. Offhand I think it will be easier to manage changes that way, rather than with a single "everything" package, but time will tell on that front.

Anyway, I was able to get my first example of loading a metadata package when a module starts up (using a placeholder package with a few Encounter Types and Visit Types). You can see the code here. At some point someone in Kenya with domain knowledge is going to have to build the proper first version.

Tomorrow's goals:

  • rename the Distribution module, since Burke didn't like that name) and release it to the OpenMRS module repository.
  • end-to-end test of everything we've built so far:
    • start with an empty standalone installation
    • installing our zip-of-omods (resulting in a running application)
    • installing version 2 of our zip-of-omods (resulting in an updated application)
Yes, it will be as riveting as it sounds. Stay tuned!

Below the fold are a couple of dev issues that took me time to figure out, and I want to document for posterity...

Friday, May 11, 2012

I wish I could work on the Concept Proposal module

One of the things I love about this project is that I get to (try to) use OpenMRS in ways that weren't possible a few years back, when I was heavily involved in PIH's implementations.

One of those is getting to use the MVP/CIEL concept dictionary, instead of building one from scratch. Most people (myself definitely included) aren't very good at building medical terminologies, but Andy Kanter and his group are, so it's far better to leverage their excellent work!

The sad part of that is that there are a ton of sub-projects I'd like to do, but don't have time to address right now. For example getting a working version of a Concept Proposal module, so you can start from the MVP/CIEL dictionary, create a form that requires a few new concepts of your own, and then propose those concepts for addition in the master dictionary via a web service.

If you're interested in reading more, I started a conversation about a simpler workflow for Concept Proposals on the OpenMRS developers mailing list...

Distribution Module 1.0, Ready to Go!

I was a bit too optimistic earlier this week about what I'd be able to get done--a common programmer's curse--but I do have something pretty cool to report. I was able to put together version 1.0 of a new "Distribution module" for OpenMRS, that lets you package multiple OpenMRS modules into a single zip file, and install it in a single operation.

This is really key for us, since our distribution is going to contain a whole bunch of modules (listed below), and we're going to need a consistent way of upgrading them all, for many installations, with as little work as possible.

As an aside, I really want to push the OpenMRS community to make it much easier to build "distributions", that can be deployed widely, and upgraded easily. So hopefully this is a decent-sized first step. :-)

Later on we'll be adding a feature to that module so it can proactively download new versions of the distribution from a server, and alert the sysadmin that they can upgrade with one click. (I'd really like to work on that right now, but I'm afraid it's going to have to wait a few weeks.)

Next week I'll be looking at what needs to happen to make the Metadata Sharing module work with OpenMRS 1.9. Rafal tells me it will load, but we can't share concepts yet because of the concept mapping-related data model changes. We need to make this work, so wish me luck!

If you're interested, we're currently planning for the first release of our distribution to include these modules:

Monday, May 7, 2012

Resources on Dropbox

This may not be the most exciting post for those not close to the project, but we've been organizing materials (MOH form 257, sceenshots and documentation from other implementations, etc., in an internal shared folder.  Contact Bill/Jan if you need access.

Getting started, technically...

Now that you know who I am, and a bit about what we're doing at a high level, it's time to dive into the details. :-)

A quick example app
I spent last week wiring together a new OpenMRS application using:
This week I'm working on a few things:
  1. Instructions for an Ubuntu VM-based development environment, pre-configured with all the Eclipse plugins you need for OpenMRS development.
    • Eclipse-Maven-SVN integration is surprisingly annoying. If only I had time to switch to IntelliJ...
  2. Integrating the HTML Form Entry module with the UI Framework/Library.
  3. Building an "OZIP" module, so all the relevant OpenMRS modules can be packaged as a single file. (My email to the dev list here.)
If all goes according to plan, next week I'll work on integrating the Metadata Sharing module, and we can show a proof-of-concept of a single ZIP file setting up the Kenya OpenMRS EMR application along with the MVP/CIEL concept dictionary.

Hello, World!

Hello, world!

I wanted to take a moment to introduce myself and talk about the exciting work that I get to do on this project, helping to put together a state-of-the-art OpenMRS distribution, that supports rapid development, while also supporting consistent central management and easy updating of of hundreds of installations.

My name is Darius Jazayeri, and I've been working on electronic medical record systems for Partners in Health since 2002. I started while we were building a web-based EMR to support our MDR-TB and HIV programs, I was there when we co-founded the OpenMRS project with the Regenstrief Institute in 2005, and today PIH has been donating me to work full-time as a lead developer of OpenMRS. It's been an exciting 10 years.

My main areas of interest recently have been around how we can build improved and simplified user interfaces, and how we can package OpenMRS up so it can be maintained without needing on-site programmers. But in my regular OpenMRS job I really don't get much time to focus on those interests.

Which brings us to the present moment, and the OpenMRS Kenya project...

When I heard from I-TECH about a project they're working on to put together an OpenMRS-based EMR, for use in Kenya, I was interested. And when I learned we'd get to write some new point-of-care user interfaces and we'd need an architecture for devs in Kenya and Seattle to collaborate while managing updates to hundreds of installations without  on-site IT, I knew I had to work on the project.

So here I am, saying hello. :-)

Friday, May 4, 2012

What's thls blog about anyway?

This is Bill Lober, with a brief note about why we set up this blog...

I-TECH (a unit of the Department of Global Health, University of Washington) is working on a project to widely implement EMRs in public (Ministry-supported) health care facilities in Kenya.  One aspect of that work, which is led by Patrick Odawo, the Nairobi-based Country Director for I-TECH's work in Kenya, is the development and implementation of a standardized configuration of OpenMRS to meet specific content and workflow goals of the Ministry, and the development of a broadly scalable protocol for training, implementation, and support.

And, we've become kind of enthusiastic about the idea of keeping a public, transparent log of our progress.  Sometimes its a bit embarrassing, when things go wrong, or we hit a slow patch, but mostly it's been pretty helpful with our OpenELIS project in Haiti and Cote d'Ivoire, and our collaboaration in Vietnam, because it gives people a way to get oriented to what we're doing, to figure out how it relates to what they're doing, it exposes points for collaboration, and it lets the sponsors of our work know that (even with the occasional misstep!) we're working hard and getting things done...