Bahmni OpenMRS Platform Upgrade from 2.1.6 to 2.5.0

Hello All @ibacher @dkayiwa

We are from Bahmni Team started analysis on the OMRS platform upgrade from 2.1.6 to 2.5.0. Please find initial analysis documentation here

Approach: We’ve bump up the openmrs version in one of the Bahmni module directly to 2.5.0 and tried to fix all the API breaking changes. But there are bunch of bean creation errors as the 2.4.0 platform also has many library changes(like Spring, Hibernate, Junit etc). At one point of time we couldn’t proceed further because of the bean creation errors. Then we started with incremental upgrade of OpenMRS. The approach is to upgrade one version at a time from 2.1.6 (eg: 2.1.6 to 2.2.0) in all the Bahmni modules and build the module successfully, and eventually upgrade to OpenMRS platform 2.5.0.

Current Status: We are done with the OpenMRS platform 2.2.0 upgrade successfully.

We want to do this on a fast pace. Please let us know if you have any suggestion for the OpenMRS platform upgrade. Thanks !

@angshuonline @gsluthra @n0man @kalavatisingh @swatigogia @mohant @rohit.yawalkar @vmalini @buvaneswariarun @akhilmalhotra @atish1603

2 Likes

This is a really important initiative, and many community members in the Bahmni community have been asking for an OpenMRS upgrade – so it’s great to see you are driving this @binduak!! Looking forward to the findings and hopefully no unexpected hurdles (fingers crossed)!

#java #database #security #upgrade

1 Like

A couple of notes on this:

  1. Some Bahmni artefacts have been updated to support Log4J2. We currently haven’t forward or back-ported the Log4J2 updates to either the 2.2 or 2.3 branches.
  2. Most likely from a library perspective, you could go from 2.1.x to 2.3.x with no problems as I don’t think we did any major overhaul of core libraries.
  3. It’s worth considering the changing Liquibase versions. In particular, I note that the openmrs-module-appointments runs Liquibase changes through SQL scripts and there have been some changes to how these are supported. Prior to 2.4.0, it should still be using the same version of Liquibase (e.g., the 2.x branch).
  4. JUnit-wise everything should still be runnable as JUnit 4 test cases. Although we’ve added JUnit 5, the the base classes for using it are in a different package. (Most community-based modules are developed against pre-2.4.0 versions of OpenMRS and remain compatible with both).

I’m really excited to see this moving ahead!

2 Likes

It would also help to share the bean creation errors, just in case we have come across them before, and hence have solutions.

Iam personally curious and excited to see how it goes for Bahmni to run on 2.5.0 . Iam keeping a close watch on this :smiling_face: :smiling_face:

2 Likes

sure @ibacher we are planning functional testing on 2.4 considering log4j2 changes are not back ported to 2.2 or 2.3 OMRS

updated the same in analysis doc. We will take this up as part of upgrade.

Thanks @ibacher for your valuable pointers.

Hi @dkayiwa We were facing few bean creation errors. Below is the last one with which we couldn’t proceed further with 2.5.0 OMRS upgrade.

java.lang.IllegalStateException: Failed to load ApplicationContext

	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'allFreeStandingExtensions' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/appframework-api/2.16.0/appframework-api-2.16.0.jar!/org/openmrs/module/appframework/repository/AllFreeStandingExtensions.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validatorFactory' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/appframework-api/2.16.0/appframework-api-2.16.0.jar!/moduleApplicationContext.xml]: Invocation of init method failed; nested exception is javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emrVisitService' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/emrapi-api/1.31.0/emrapi-api-1.31.0.jar!/moduleApplicationContext.xml]: Cannot resolve reference to bean 'emrVisitServiceImpl' while setting bean property 'target'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'emrVisitServiceImpl' available
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emrVisitService' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/emrapi-api/1.31.0/emrapi-api-1.31.0.jar!/moduleApplicationContext.xml]: Cannot resolve reference to bean 'emrVisitServiceImpl' while setting bean property 'target'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'emrVisitServiceImpl' available
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appFrameworkService' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/appframework-api/2.16.0/appframework-api-2.16.0.jar!/moduleApplicationContext.xml]: Cannot create inner bean 'org.openmrs.module.appframework.service.AppFrameworkServiceImpl#4c531172' of type [org.openmrs.module.appframework.service.AppFrameworkServiceImpl] while setting bean property 'target'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.openmrs.module.appframework.service.AppFrameworkServiceImpl#4c531172' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/appframework-api/2.16.0/appframework-api-2.16.0.jar!/moduleApplicationContext.xml]: Cannot resolve reference to bean 'allAppTemplates' while setting constructor argument; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'allAppTemplates': Unsatisfied dependency expressed through field 'validator'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validatorFactory' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/appframework-api/2.16.0/appframework-api-2.16.0.jar!/moduleApplicationContext.xml]: Invocation of init method failed; nested exception is javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:799)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1361)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1208)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:127)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:275)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:243)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	... 25 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validatorFactory' defined in URL [jar:file:/Users/admin/.m2/repository/org/openmrs/module/appframework-api/2.16.0/appframework-api-2.16.0.jar!/moduleApplicationContext.xml]: Invocation of init method failed; nested exception is javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1799)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:886)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:790)
	... 43 more
Caused by: javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:102)
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:45)
	at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolator(ConfigurationImpl.java:423)
	at org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.afterPropertiesSet(LocalValidatorFactoryBean.java:275)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 54 more
Caused by: java.lang.NoClassDefFoundError: javax/el/ExpressionFactory
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:98)
	... 59 more

I tried adding javax/el/ExpressionFactory dependency as mentioned in the stack trace but it didn’t change the error. As the error is coming up as part of failing test cases, it doesn’t have full stack trace which can give a clue of source of the file.

Hope this context is helpful. Thanks !

Which exact module is that? I could try it out locally.

@dkayiwa We tried the upgrade of openmrs to 2.5.0 on bahmni-core module. And from the stack trace we could that the bean creation error coming from App Framework Module

Hello @dkayiwa @ibacher We have below questions with respect to the OpenMRS upgrade from 2.2.0 to 2.3.0 on the schema changes done for both diagnosis and condition tables. Please find the OpenMRS JIRA card for the same here.

  1. In encounter_diagnosis table we have condition_coded and condition_coded_name columns. condition_coded storing the concept_id of the coded concept and condition_coded_name storing concept_name_id from concept_name table of the diagnosis coded concept.

We want to understand the significance of having condition_coded_name column in the encounter_diagnosis table as we anyways able to get the concept_name_id from condition_coded field value.

Note: Its the same with conditions table.

  1. Existing Bahmni Diagnosis allows Conditions of non-coded type. We can enter free text in the conditions column and this text value will get saved under condition-non-coded column in the conditions table.

image

But with latest OpenMRS 2.5.0, Conditions is not allowing the free text as the input.

Is this expected behaviour ?

  1. In Emr-api repository most of the mappers from api-1.12 folder are not moved to either api-2.2 folder or api folder and Bahmni-core still using these class for Medication feature from emr-api. With OpenMRS 2.3.0 upgrade these files are no longer available to use. Any specific reason for not adding the files to api folder ?

Requesting your pointers on the above questions. This would help us to move forward with the upgrade. Thanks in advance !

@dkayiwa @ibacher @gsluthra @angshuonline @mksd

The issue here is to ensure that the diagnosis (or problem) can always be displayed with the same name that the clinician choosing the diagnosis or problem used. Since concepts can have multiple synonyms in the same language and those synonyms might have slightly different meanings among them, this allows us to unambiguously display the exact synonym that was chosen.

Could you clarify what you mean by this? The condition_non_coded field is there on the conditions table.

The api-1.12 classes should be available on 2.3+. See here. Note that if you’re writing code against them, you’ll still need to include api-1.12 as a dependency.

Condition behaviour in Bahmni(OpenMRS 2.1.6)

Condition input field would allow us to enter any text value (eg: non coded) from UI and the value gets saved in Conditions table under condition_non_coded field. And the concept_id will have the concept id of the “Non-Coded Condition” concept. Please check demo.mybahmni.org for the existing behaviour.

image

Condition behaviour in OpenMRS 2.5.0

Condition input field is not allowing to enter any free text from UI. We have “Diagnosis or problem, non-coded” concept in the dictionary for non-coded values. And the value in condition_non_coded field is empty here.

image

In which scenario the data will get populated in the condition_non_coded field in the conditions table ?

Is it expected behaviour that Condition input filed doesn’t allow any free text from UI ?

I can’t see anything in core that’s applying logic like that. The ConditionService#save() implementation is a little more complex than I’d maybe like, but ultimately just calls the method to save things to the database. emrapi had to be updated to accomodate the slightly different model in core but the conversion looks like it should preserve the condition non-coded field to me.

So, the question here is: what actual endpoint are you calling? And what data are you sending it? Maybe we can trace through how the data gets lost that way…

Hello @ibacher @dkayiwa,

We raised the PR for upgrading Openmrs version to 2.4.2 in bedmanagement module. Please go through it.

Thank you

Hi @ibacher @dkayiwa Can you please review the below PR raised to bacteriology for OpenMRS 2.4.2 upgrade. Requesting for a release of the bacteriology module with the below PR changes. Thanks !