Just created a Jira ticket to track this here Jira
Hi @jonathan, I’m having trouble building the Standalone in a Gitpod environment. The following are the environment specs:
mvn -v
Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport -XX:ActiveProcessorCount=1
Apache Maven 3.9.10 (5f519b97e944483d878815739f519b2eade0a91d)
Maven home: /home/gitpod/.sdkman/candidates/maven/current
Java version: 17.0.14, vendor: Amazon.com Inc., runtime: /home/gitpod/.sdkman/candidates/java/17.0.14-amzn
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.1.91-060191-generic", arch: "amd64", family: "unix"
I get the following error:
[ERROR] ChangeSet liquibase-ciel-data.xml::20120315-1000::standalone encountered an exception.
liquibase.exception.DatabaseException: Unknown table 'openmrs.concept' [Failed SQL: (1051) DROP TABLE concept]
at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement (JdbcExecutor.java:519)
...
UPDATE SUMMARY
Run: 0
Previously run: 0
Filtered out: 0
-------------------------------
Total change sets: 1
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:4.32.0:update (empty-db-add-ciel-data) on project standalone-02:
[ERROR] Error setting up or running Liquibase:
[ERROR] liquibase.exception.LiquibaseException: liquibase.exception.MigrationFailedException: Migration failed for changeset liquibase-ciel-data.xml::20120315-1000::standalone:
[ERROR] Reason: liquibase.exception.DatabaseException: Unknown table 'openmrs.concept' [Failed SQL: (1051) DROP TABLE concept]
To reproduce this, you can use this link.
Would you know why it fails?
@ruhanga you need to run mvn clean
and then mvn install
seperately.
Thanks @dkayiwa, that seems to have done the trick.
Thanks for the great efforts here @jonathan! A few observations after building and testing the current Standalone (from the master
branch): when it’s built on a Linux machine, it fails to run on macOS or Windows. This seems to be due to the MariaDB binaries being resolved and bundled during the build process, making them OS-specific.
This implies that we’d need separate Standalone builds for each supported OS. Alternatively, we could resolve the appropriate binaries dynamically at runtime. However, doing so would likely require deferring some of the current logic, like initial database population, from build time to runtime. The trade-off is that the first-time setup might take slightly longer
A potentially better solution, building on the proposal above, might be to rely on pre-generated DB dumps or .sql
files(done at build time) that can be used at runtime regardless of the OS, avoiding the need to bundle os-specific binaries altogether.
@dkayiwa We found an Unexpected behaviour talked about by @ruhanga
OpenMRS Standalone Platform 2.8.0-alpha was released — but when trying to run the freshly built standalone on another machine , it fails to start . (Also applies if built on another machine and use the zipped on a newer one)
The Problem:
Artifacts built on Bamboo (the CI system) work fine — until you try to run them on a different system. then they fail.
On Sunday evening, I got a meetup with @ruhanga to debug this. After digging deep, we found the cause:
MariaDB user permissions were being tied to the machine that built the artifact.
Specifically, the embedded MariaDB tables for Demo and CIEL were zipped during build-time, and these include user/system-specific permission metadata.
When moved to another machine, MariaDB rightfully refuses access — since the runtime system wasn’t the one that created the DB.
The Proposed Fix
Together, we came up with a plan:
Solution:
- Instead of zipping MariaDB binaries during the build phase…(pom steps 1-5) and zipping them
- We will zip the SQL dump instead, and initialize the database during runtime for demo separately and Ciel.
Why this works?
The Expert Mode, which builds everything on the fly, already works fine on any machine — because it doesn’t carry any system-bound DB binaries.
This proposed runtime approach will:
- Make Demo and CIEL modes portable across systems
- Ensure future Platform releases (like 2.8.0-alpha) behave consistently
What is your take on this?
For a try out Download from here OpenMRS Platform - OpenMRS Platform 2.8.x Temp Rebuild 9: Artifacts - OpenMRS Bamboo the built Bamboo standalone and try to select the Demo or ciel … and then after the Expert mode
The Demo and ciel fail as explained while Expert mode passes fine
What do you mean by the mariadb binaries? Do you mean the files in the database/bin folder?
yes indeed unzipped from the demo and empty zips
I thought those had nothing to do the CIEL or Demo SQL data.
@dkayiwa , what we observed is that the zipped MariaDB data directories (not binaries like those in database/bin
, but the actual data store folders containing ibdata1
, *.ibd
, mysql/*
, openmrs/*
, etc.) — which are included for the Demo and CIEL modes — carry over machine-specific metadata, including the mysql
system database which defines users, permissions, and hostname bindings.
So although database/bin
has the MariaDB server binaries, the issue lies in the unzipped data
folder contents, which get restored as-is from the zipped demo/CIEL folders during runtime. These data
folders contain:
- Pre-initialized
openmrs
database (Demo/CIEL) - The
mysql
database with root user - Other internal MariaDB server files
That’s why when the Standalone is built (say, on Bamboo), and the zipped demo/CIEL folders are extracted and run on another machine, the embedded MariaDB sees a mismatch and fails — typically throwing errors
Oh i see! Then i am happy with your proposed approach. Looking forward to testing it out.
Am gonna revert to this for Platform, 2.x and 3.x Standalone
Anxiously looking forward to the output.
Hello @dkayiwa @wikumc @mherman22 @ibacher
Am trying to call the Context.updateSearchIndex();
in the standalone after demo and ciel initialized or imported and getting
📥 Importing SQL from: /Users/mutajonathan/openmrs/openmrs-standalone-2.7.4-SNAPSHOT/db/data/openmrs-demo-dump.sql
✅ Successfully imported SQL: /Users/mutajonathan/openmrs/openmrs-standalone-2.7.4-SNAPSHOT/db/data/openmrs-demo-dump.sql
Stopping MariaDB...
Database mode using demo database: DEMO_DATABASE
Exception in thread "main" java.lang.NoClassDefFoundError: org/openmrs/api/context/Context
at org.openmrs.standalone.ApplicationController.init(ApplicationController.java:282)
at org.openmrs.standalone.ApplicationController.<init>(ApplicationController.java:62)
at org.openmrs.standalone.ApplicationController.main(ApplicationController.java:133)
Caused by: java.lang.ClassNotFoundException: org.openmrs.api.context.Context
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
... 3 more
which makes sense since at this stage the openmrs is not yet fully initialised however am wondering how i can do this same thing of refreshing the search index via Rest Api
to be clear will be checking for the session status and then refresh the search index
However using the POST
on http://localhost:8081/openmrs/ws/rest/v1/searchindex
am getting
{
"error": {
"message": "[Required request body is missing: public java.lang.Object org.openmrs.module.webservices.rest.web.v1_0.controller.MainResourceController.create(java.lang.String,org.openmrs.module.webservices.rest.SimpleObject,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws org.openmrs.module.webservices.rest.web.response.ResponseException]",
"code": "org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor:163",
"detail": "org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.Object org.openmrs.module.webservices.rest.web.v1_0.controller.MainResourceController.create(java.lang.String,org.openmrs.module.webservices.rest.SimpleObject,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws org.openmrs.module.webservices.rest.web.response.ResponseException\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:163)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:133)\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:555)\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:623)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:199)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:73)\n\tat org.openmrs.web.filter.GZIPFilter.doFilterInternal(GZIPFilter.java:66)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)\n\tat org.openmrs.module.webservices.rest.web.filter.AuthorizationFilter.doFilter(AuthorizationFilter.java:121)\n\tat org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)\n\tat org.openmrs.module.webservices.rest.web.filter.ContentTypeFilter.doFilter(ContentTypeFilter.java:64)\n\tat org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)\n\tat org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:106)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)\n\tat org.openmrs.module.owa.filter.OwaFilter.doFilter(OwaFilter.java:112)\n\tat org.openmrs.module.owa.filter.OwaFilter.doFilter(OwaFilter.java:90)\n\tat org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)\n\tat org.openmrs.module.web.filter.ModuleFilter.doFilter(ModuleFilter.java:57)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.owasp.csrfguard.CsrfGuardFilter.handleSession(CsrfGuardFilter.java:107)\n\tat org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:97)\n\tat org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:68)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.openmrs.web.filter.OpenmrsFilter.doFilterInternal(OpenmrsFilter.java:114)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.openmrs.web.filter.CookieClearingFilter.doFilterInternal(CookieClearingFilter.java:77)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:156)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:125)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:935)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1826)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\n\tat java.base/java.lang.Thread.run(Thread.java:1447)\n"
}
}
pushed PR for it here