This is my opinionated guide to OpenMRS (http://openmrs.org) customization for multiple sites, may work for a single site if developer resources are available. This guide is based on 3 years working with the UgandaEMR distribution (https://wiki.openmrs.org/display/docs/UgandaEMR+Distribution) for the Ministry of Health of Uganda, currently in 650 sites across the country (December 2017).
Background to OpenMRS
OpenMRS is a electronic medical records solution, which runs on Java 8, Apache Tomcat 7 and MySQL 5.x (we are using 5.5 and 5.6). The solution is based on openmrs-core (the platform) and modules which extend the platform providing key functionality such as look and feel, REST API, data collection tools, dashboards, patient management workflows.
OpenMRS releases the Reference Application (RefApp) a collection of modules that showcases how the EMR can be setup for clinical workflows, and which is usually the starting point for implementations. The RefApp is released twice a year, April and October, with enhancements that are prioritized by the community and developed leveraging available resources.
I may be somwhat biased due to my role as Reference Application Lead from January 2017.
UgandaEMR
This is one of the nationally approved EMR solutions, which is being actively developed from August 2015, currently supporting HIV Treatment and Care including HIV Exposed Infants (babies born to HIV positive mothers), Safe Male Circumcision, Tuberculosis treatment, Maternal and Child Health (antenatal, maternity and post-natal care), Outpatient services among others.
Guiding Principles
This approach follows the list of principles below:
- Any distribution should only customize workflows, look and feel and provide metadata to the underlying EMR – any custom functionality belongs in the underlying core platform and modules. This rule means that the underlying code grows and evolves with time to meet needs of different implementations, may not be adhered to 100% but even 80% is sufficient
- “If you need to change the core, then you are probably doing something wrong” ~Daniel Kayiwa OpenMRS Core Contributor, which is probably true. There are multiple ways to skin a cat so skin it the “openmrs” way
- Use the OpenMRS SDK – this tool is what an SDK should be, allows you to create, run and test multiple variations and approaches using the openmrs-distro.properties file that allows the distribution to define and build its own war file and docker containers for shipping
- Leverage the new openweb apps (OWAs) approach to provide user interfaces with the REST APIs
- For concepts always refer to the CIEL dictionary (http://openconceptlab.org/) as your primary reference
- Contribute changes back to the platform and modules you are using rather than build your own – stand on the shoulders of giants, but feed them too so that they can grow stronger and carry others. This is a core opensource ethos
- Keep your distribution code public – share with others never know where the knowledge will come from. My personal technology experience has been that at some point in time, you will have to come out and find you missed alot of the magic
- Ask quesitons on design, approaches, best practices and collaborate with the community to grow your knowledge and others – Don’t build a wall fence around your house, raise your neighbors so that you do not need a wall fence
How to setup a Customization
- Setup OpenMRS SDK in your developer environment – by now you have figured that I love this tool
- Use the SDK to create a reference application module usually named openmrs-module-mydistribution using
mvn openmrs-sdk:create-project -Dtype=referenceapplication-module
- Create a new OpenMRS SDK server following the steps at https://wiki.openmrs.org/display/docs/OpenMRS+SDK#OpenMRSSDK-Settingupservers
- Copy openmrs-distro.properties file from the server to api/src/resources for your module
- Add a build plugin in the omod/pom.xml folder such as below extracted from UgandaEMR
-
<build>
<finalName>${project.parent.artifactId}-${project.parent.version}</finalName><plugins><plugin><groupId>org.openmrs.maven.plugins</groupId><artifactId>maven-openmrs-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId></plugin><plugin><groupId>org.openmrs.maven.plugins</groupId><artifactId>openmrs-sdk-maven-plugin</artifactId><version>3.13.1</version><executions><execution><id>build-distro</id><phase>install</phase><goals><goal>build-distro</goal></goals><configuration><dir>${project.build.directory}/docker</dir><bundled>true</bundled><distro>${project.build.directory}/classes/openmrs-distro.properties</distro><batchAnswers><param>n</param></batchAnswers></configuration></execution></executions></plugin></plugins></build> - Set your custom module to be watched by the server, so each time the server is started the latest version of the module is built and deployed also makes live reload of controllers and styling possible
-
mvn openmrs-sdk:watch
- Add a .travis.yml file to provide integration to Travis CI a sample below
-
language: java jdk: - oraclejdk8
- Traditional OpenMRS development approaches now follow 😉
More examples from UgandaEMR can be found at http://bit.ly/ugandaemr-technicalguide
In closing, these are my thoughts on how such customizations should be done, while they may need a developer available, they are bound to start the test of time.
Do share your thoughts and learnings from this and let me know how to improve, I may not be able to change though