Module Conditional Resources

Tags: #<Tag:0x00007f828eb26ef8>

I figured I’d open up a discussion on Talk before I opened a ticket for this.

Currently, when loading a module, we have the concept of a “conditional resource”, generally a JAR file that is supposed to be loaded under specific circumstances. This can be used, e.g., to load code for supporting different OpenMRS resources or loading code based on the presence or absence of other modules. For the most part, this works well, but there’s one “feature” to it that doesn’t seem to be well understood: how resources are matched.

The documentation for modules does state that:

All resources are loaded by default. If a path of a conditionalResource is matched based on a regular expression then OpenMRS version and/or modules must match as well for the resource to be loaded.

But looking at the actual usage, it appears as though the part about this matching based on a regular expression is not widely understood. Usually this is pretty innocuous. E.g., in emr-api, we use conditional resources like this one:

<conditionalResource>
    <path>/lib/emrapi-api-1.12-${project.parent.version}.jar</path>
    <openmrsVersion>1.12.0 - 2.*</openmrsVersion>
</conditionalResource>

The <path> element will be expanded to something like: “/lib/emrapi-api-1.12-1.29.0.jar” and obviously the intention here is to match exactly that pathname (the JAR that corresponds to the api-1.12 submodule of the current build of the emr-api module). And it will match that, but because . is a regex meta-character that matches any character, this would also match a potential resource like /lib/emrapi-api-1112-1129101jar, which is obviously not what is intended. This is a pretty contrived example because obviously something like the resource I just made up is unlikely to actually exist. However, it’s easy to find other examples where using regexes results in very clear mistakes.

The more worrying case is when we get something like [this from the atomfeed module]:

<conditionalResource>
	<path>/lib/jackson-mapper-asl*</path>
	<modules>
		<module>
			<moduleId>uiframework</moduleId>
			<version>!</version>
		</module>
	</modules>
</conditionalResource>

The intention here was clearly to try to not load the jackson-mapper-asl JAR if the uiframework module was loaded. However, because this string is interpretted as a regex, it never actually matches anything and so it’s a bit of a useless directive.

What I’d like to propose is that we create a new version of the module config file (let’s say 2.0) that will treat <path> resources as globs rather than regexes. I think this will result in a more intuitive matching algorithm while allowing packages that already do the right thing (basically, end with .* instead of *) to opt-out of this interpretation so they can continue to work as designed on older versions of OpenMRS.

Any objections? Better ideas?

2 Likes