Design Forum 2017-05-31: Initializer Module

Wednesday’s design forum is around the Initializer Module. If this topic is of interest to you join us from 6-7pm UTC. If you have a topic you would like to discuss during a future call please post it at Propose a Design Forum Topic - Development - OpenMRS Talk.

The next design forum will be on Monday June, 05 @ 4-5pm UTC - Continuing the discussion from Reference Application 2.7 Planning, Ideas, Features and Road Map

To join the call using Audio, Chat, & Screen Sharing please use the latest Firefox, Chrome, or other WebRTC-compatible browser and go to:

Thanks for all who joined and provided input (@ssmusoke, @burke, @wyclif, @darius, @dsurrao, @dkayiwa ; cc @mseaton, @mogoodrich, @mksrom, @ouiliam). I will summarise the next steps for the Initializer module (‘Iniz’).


####Longer term debate One main question was raised: should other modules depend on Iniz and load their configuration by themselves leveraging its API and following its conventions? We started Iniz with the idea that we didn’t want to touch the code of any module to load metadata. We aimed at one module to be responsible to load & edit metadata for “shaping distributions”. In particular, we wanted to get away from having custom modules just serving that very purpose. However nothing prevents to mix both scenarios, as in: Iniz would process the content of the configuration folder, and yet any other module could still process parts of what’s in the configuration folder as well (that’s currently the case with Address Hierarchy although Address Hierarchy doesn’t depend yet on Iniz, some classes have just been “copy/pasted”).

We would need to liaise with module owners and present the Iniz paradigm to them to see if they would be ok to add the dependency and follow its conventions. Obviously that would only happen after the first release.

####Release 1.0 roadmap We would like to have a 1.0 version out somewhere within a month. It is a starting version that fits the needs of one of our implementations using Bahmni. We may still rely a lot on leveraging MDS packages thereby not implementing so many CSV or XML parsers for further domains. From the top of my head though, here are some items on the roadmap:

  • Load messages.properties files - so a ‘messages’ or ‘i18nmessages’ new domain. (Iniz already does that to a certain extent, but only for loading the messages coding address hierarchy entries names when leveraging AH i18n support feature).

  • Remove the hard runtime dependencies on other modules than Core. For the time being:

    • IdGen
    • Address Hierarchy
    • Metadata Sharing

####Reference Application 2.7 @ssmusoke, please feel free to get in touch with us to get this to work on areas of the Ref App metadata management. This should ideally start after the first release but trials can certainly been already done while Iniz is still a SNAPSHOT version.

1 Like

I like the idea of each module having its own configuration files, and depending on Iniz to load them. This is how Gradle works I believe.

The question is, since each module has its own object model, don’t we need a way to map module object properties to configuration file fields (similar to Hibernate), for objects that are to be initialized?

Iniz will just depend and be ‘aware of’ modules that it might initialize. It currently depends on MDS and IdGen for instance. It also currently requires them, which will be dropped as part of version 1.0.

The more I thought about this, the more I believe the dependency between the initializer module and other modules would best be encapsulated using the strategy pattern. Something along the lines of:

public interface InitializerStrategy {
  /* List of domains (domain could be a module ID) to which the strategy applies.
      Could include convention for specifying version(s) or could add a
      supportedVersionsFor Domain(domain) method. */
  public String[] supportedDomains();

  /* Which versions of the initializer are supported by the strategy */
  public String supportedInitializerVersions();

  /* Perform initialization, turning to context for to get path to files, convenience
     methods, etc. */
  public void initialize(InitializationContext context) throws InitializationException;
}

The initializer module could do the heavy lifting for common operations (e.g., reading CSVs) and supply these convenience methods through a context object.

Benefits of this approach

  • The initializer module only needs to find a strategy that supports its version and a given domain.
  • It doesn’t matter if the strategies are put into the initializer module or provided by individual modules.
  • You can have as many strategies as you want & they can change over time.
  • No need for formal (even “aware of”) dependency between modules and the initialize module.
  • You could create a default strategy that does what you’re doing now, so new strategies are only needed for special cases or if a new version of initializer has new/changed features.

@mksd, sorry I missed the design call on this.

@burke, if there is going to be an InitializerStrategy interface, wouldn’t modules need to be aware-of Iniz in order to be able to implement their own strategy? Or if the strategies were put into Iniz, then wouldn’t they need to be aware of the module that they were initializing (if they are going to be using that module’s API)?

Or are you suggesting that these Initializers only provide the plumbing, and the implementation details are more loosely coupled, using some convention?

The way I was thinking about it is that it is mostly convention driven, based on the contents of the .OpenMRS/config directory. Here, we might have some reserved files or folders for specific built-in configuration options that we want to support, but we would also allow any module to support initialization via a subfolder named after the module id.

Mike

@mksd A question is there any design approach for the Initializer module to support:

  1. Loading of HTML Form Entry forms (XML files) from the omod/resources/webapp/resources/htmlforms directory

  2. Loading from a configured resources/configuration custom path in the api submodule. This is important for a distribution like UgandaEMR where the metadata is shipped with the distribution

In Java 8 on Windows the application path is now C:\Windows\system32\config\systemprofile\Application Data\OpenMRS but seems to be deleted when the user logs off… How can the config files be consistently deployed then?

For the record @ssmusoke and I spoke about this on IRC and the second point contravenes Initializer’s design. While it would be awesome for the module to handle the HFE forms resources as a new ‘domain’, they can’t be loaded from within another module, they must be provided as part of the standalone configuration (so called “OpenMRS config”).

Initializer enables to strictly separate binaries and configuration. Loading forms shipped through another module means that there is already a custom module, and in that case that module should just handle its own resources.

1 Like

I could be wrong, but doesn’t the htmlformentry (or htmlformentryui) module already automatically load the forms from these resources (perhaps the first time they are accessed)?