OpenMRS Packaging: going beyond modules

image

Vision for OpenMRS packages

Imagine a world where content & functionality can easily be distributed, versioned, and added to existing OpenMRS systems, whether to support a single distribution or to share functionality across multiple different implementations or distributions.

We started with OpenMRS modules

OpenMRS started with a modular architecture and OpenMRS modules:

OpenMRS modules

  1. Write Java code following OpenMRS module conventions
  2. “Zip” it into a Java Archive (.jar) file
  3. Change the extension from .jar to .omod (for OpenMRS module)

These can be hot-loaded into a running system to add or change any system behavior.

OpenMRS modules allow implementations to take a base system and adapt it to meet their needs. But we often need to do more than introduce Java code; we need to introduce or share content or, in the case of OpenMRS 3.0, frontend (non-Java) code. There have been several workarounds and new approaches over the years:

  • Modules created to import & export metadata (e.g., metadata sharing, iniz)
  • Modules that deliver embedded metadata (e.g., PIH content modules, refapp demo data)

Proposal for OpenMRS packages

Not only were OpenMRS modules designed in a world where everything was server-rendered (before REST APIs and Javascript frontends), bundling content into a module can work but falls short as a delivery mechanism for content (concepts, forms, reports, etc.). How do we go beyond just delivering Java code, to include content, frontend modules, and other configuration details? Efforts to define distributions for the SDK, Mekom’s iniz module (simplifying the process of introducing metadata into a system), and requirements for OpenMRS 3.0 along with efforts like OHRI have led us to the notion of “OpenMRS packages”:

OpenMRS packages

  1. Combine code and content within a pre-defined folder structure
  2. Zip it up using Maven (or OpenMRS tools)
  3. Distribute as Maven artifact

Use these to add new capabilities to existing system, define the basis for a distribution/deployment, or share capabilities with others.

What is an OpenMRS package?

While an OpenMRS module is Java code, an OpenMRS Package can contain any/all of:

  • Modules
  • ESMs (frontend modules)
  • Metadata (concepts, forms, reports, analytics transforms/rules)
  • Configuration settings
  • Other packages

These assets are arranged into a conventional folder structure (like the 3.x folder structure) and zipped up into an archive that can be used by the SDK and other tooling to deploy or share the content & functionality.

Why use Maven? Maven already provides the mechanism to package artifacts, manage dependencies, etc. We don’t need to be re-inventing or coming up with OpenMRS-specific approaches when widely-adapted established tooling can meet our needs.

Do we need a manifest file? Information about the package (owner, version, etc.) would typically be included in a manifest file. Since we are using Maven to manage and distribute artifacts, we should try to leverage these capabilities within Maven (e.g., the POM file) before creating OpenMRS-specific (bespoke) approaches.

Can packages be installed into a running system (like modules)? Currently, ESMs (frontend modules) are compiled into a unified frontend using Webpack in a compile step that happens before the system is run and we don’t have a mechanism to introduce new frontend modules on the fly to a running system. This means OpenMRS packages (at least any new frontend features) will need to be introduced in a compilation step prior to running a system. We hope we can overcome this and create a path for introducing new frontend modules during runtime in the future in a way that doesn’t compromise performance or security.

What’s the difference between a OpenMRS package and an OpenMRS distribution? An OpenMRS package bundles content & behavior that can be used to build a system or added to an existing system; while a package might declare compatibility with certain versions of the platform, it can work within any compatible platform). A distribution includes the entire stack (including the specific version of platform & framework).

Next Steps

Moving the conversations forward…

  • Reaching consensus on packaging conventions
    • I know others (like @mksd and @grace) have been thinking a lot about packaging and have ideas how this approach can be improved.
  • Adapting the SDK and other tooling to follow and promote those conventions
  • Migrating add-ons to adopt packaging conventions
7 Likes

Can packages be installed into a running system (like modules)? Currently, ESMs (frontend modules) are compiled into a unified frontend using Webpack in a compile step that happens before the system is run and we don’t have a mechanism to introduce new frontend modules on the fly to a running system. This means OpenMRS packages (at least any new frontend features) will need to be introduced in a compilation step prior to running a system. We hope we can overcome this and create a path for introducing new frontend modules during runtime in the future in a way that doesn’t compromise performance or security.

I think this won’t be very hard, when we get to it. It’s just files. Nothing in memory or database to mess with.