diff --git a/README.md b/README.md
index d647acf..771498e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
OpenMRS Standalone provides a simplified, all-inclusive installation option with both an embedded database and web server.
Read more at: https://wiki.openmrs.org/display/docs/OpenMRS+Standalone
+The current setup uses an embedded MariaDB database with MariaDB4j, while continuing to utilize the MySQL driver for database connectivity. Read more about mariadb4j here: https://github.com/MariaDB4j/MariaDB4j
+
The master branch of the standalone repo is built by our CI as part of the Platform build at https://ci.openmrs.org/browse/OP and the openmrs-emr2 branch as part of the Reference Application build at https://ci.openmrs.org/browse/REFAPP-OMODDISTRO
## Overview
@@ -19,7 +21,7 @@ Depending on what OpenMRS software artifact you are releasing, you may need to c
### Increasing maven memory
-Increase the maven memory: e.g. export MAVEN_OPTS="-Xms1012m -Xmx2024m -XX:PermSize=556m -XX:MaxPermSize=1012m"
+Increase the maven memory: e.g. export MAVEN_OPTS="-Xms1012m -Xmx2024m"
### Running the build in two steps
@@ -69,7 +71,7 @@ just downloaded
### Other tips
-* If running `mvn clean` and `mvn package` second time, ALWAYS check to make sure mysql processes on port 3326 and/or
+* If running `mvn clean` and `mvn package` second time, ALWAYS check to make sure MariaDB processes on port 3326 and/or
3328 and/or 33326 are stopped. If you DON'T do that, then the `mvn clean` will not really clean.
* A good command to use is: "pkill -f standalone" (kills anything with "standalone" in the path)
@@ -124,18 +126,18 @@ NOTE: Using Maven Package will generate the executable jar file in the target fo
## APPLICATION USER INTERFACE
Tomcat Port This is the port at which to run tomcat.
-MySQL Port This is the port at which to run mysql
+MySQL Port This is the port at which to run MariaDB
-File -> Quit This menu item stops tomcat and mysql and then closes the application.
+File -> Quit This menu item stops tomcat and MariaDB and then closes the application.
File -> Launch Browser This menu item opens the openmrs login page for the current web application context.
File -> Clear Output This clears the output log in the user interface text area. But does not clear the log file
written on the file system.
-Start This button runs tomcat, which will automatically start the mysql database engine if it
- was not already running. For the embedded mysql, the first connection automatically starts
- the mysql engine.
+Start This button runs tomcat, which will automatically start the MariaDB database engine if it
+ was not already running. For the embedded MariaDB4j, the first connection automatically starts
+ the MariaDB engine.
-Stop This button stops tomcat and then also stops the mysql database engine, without closing the application.
+Stop This button stops tomcat and then also stops the MariaDB database engine, without closing the application.
NOTE: Minimizing or Maximizing the application window does not have any effect on the server. The window close icon will stop
@@ -147,7 +149,7 @@ NOTE: Minimizing or Maximizing the application window does not have any effect o
Running from command line requires the -commandline switch.
e.g. java -jar standalone-0.0.1-SNAPSHOT.jar -commandline
--mysqlport: Use to override the mysql port in the runtime properties file.
+-mysqlport: Use to override the MariaDB port in the runtime properties file.
-tomcatport: Use to override the tomcat port in the runtime properties file.
start Use to start the server.
stop Use to stop the server.
@@ -166,7 +168,7 @@ browser Use to launch a new browser instance.
5. For the section: "Do you want to also add demo data to your database - openmrs? (This option only available if creating new tables.)", just choose what you want.
-6. For the section: "Do you currently have a database user other than root that has read/write access to the openmrs database?", Choose Yes, and then enter a "openmrs" and "test" as the user name and password. This account will be created by the embedded database engine. The reason to use 'test' is that when the application starts, it checks for the mysql password and if it is test, it is replaced with a randomly generated 12 character password which is written back to the runtime properties file.
+6. For the section: "Do you currently have a database user other than root that has read/write access to the openmrs database?", Choose Yes, and then enter a "openmrs" and "test" as the user name and password. This account will be created by the embedded database engine. The reason to use 'test' is that when the application starts, it checks for the MariaDB password and if it is test, it is replaced with a randomly generated 12 character password which is written back to the runtime properties file.
7. Click "Continue" to go to the next wizard screen, and feel free to fill what you want on this screen.
@@ -221,37 +223,15 @@ NOTE: Without this folder structure, you will get errors while trying to run the
## DATABASE CONNECTION STRING
- jdbc:mysql:mxj://localhost:3316/openmrs?autoReconnect=true&sessionVariables=storage_engine=InnoDB&useUnicode=true&characterEncoding=UTF-8&server.initialize-user=true&createDatabaseIfNotExist=true&server.basedir=database&server.datadir=database/data&server.collation-server=utf8_general_ci&server.character-set-server=utf8
-
-The above default database connection string has all in the openmrs mysql default database connection string plus a
-few additional parameters as explained below:
-
-mxj This is required for the MySQL Connector/MXJ utility which we use for embedding mysql
- More information about it can be found at: http://dev.mysql.com/doc/refman/5.1/en/connector-mxj.html
-
-server.initialize-user The value of true tells the database engine to create the user account that will be specified
- in the openmrs web database setup. This is the account referred to as
- connection.username & connection.password in the runtime properties file.
-
-createDatabaseIfNotExist The value of true tells the database engine to create the database if it does not exist.
+ jdbc:mysql://127.0.0.1:3316/openmrs?autoReconnect=true&sessionVariables=storage_engine=InnoDB&useUnicode=true&characterEncoding=UTF-8
-server.basedir This is the directory where the mysql database server will be installed. The default value
- is a database folder in the current directory where the executable jar file is located.
-
-server.datadir This is the dirrectory where mysql stores the database. The default value is the data folder
- under the database folder in the current directory where the executable jar file is located.
-
-server.collation-server This sets the collation of the database server. If you do not set it to this value, you will
- get problems running the openmrs liquibase files. This is because the default value is swedish
- collation yet openmrs uses utf8
-
-server.character-set-server This is the character set used by the database server.
+The above default database connection string has all in the openmrs mysql default database connection and is used for the MariaDB connection.
NOTE: When creating a new database using the openmrs database setup wizard, remember to replace the default connection string
with the one above in the "Database Connection:" text field.
- The embedded mysql database engine is a fully functional database engine that you can connect too using any database
+ The embedded MariaDB4j database engine is a fully functional database engine that you can connect too using any database
GUI query tools like Navicat, EMS MySQL Manager, etc
@@ -285,9 +265,5 @@ SUMMARY: Using a single package for all (most) platforms approximately tripples
-MySQL MXJ documentation can be found at:
-http://dev.mysql.com/doc/refman/5.1/en/connector-mxj.html
-
-Details on how to add or remove platform specific databases can be found at:
-http://dev.mysql.com/doc/refman/5.1/en/connector-mxj-usagenotes-packaging.html
-http://blog.teamlazerbeez.com/2011/10/03/embedded-mysql-on-java-with-connectormxj-and-64-bit-linux/
+MariaDB4j documentation can be found at:
+https://github.com/MariaDB4j/MariaDB4j
\ No newline at end of file
diff --git a/pom-step-01.xml b/pom-step-01.xml
index 4e0a274..fbab397 100644
--- a/pom-step-01.xml
+++ b/pom-step-01.xml
@@ -35,6 +35,33 @@
+
+ ch.vorburger.mariaDB4j
+ mariaDB4j-maven-plugin
+
+ 33326
+ ${project.build.directory}/emptydatabase
+ ${project.build.directory}/emptydatabase/data
+
+
+
+
+ start-empty-database
+ initialize
+
+ start
+
+
+
+ stop-empty-database
+ process-resources
+
+ stop
+
+
+
+
+
org.apache.maven.pluginsmaven-resources-plugin
@@ -65,9 +92,9 @@
empty-db-create-schemagenerate-resources
- com.mysql.jdbc.Driver
+ com.mysql.cj.jdbc.Driverliquibase-schema-only.xml
-
+ openmrstesttrue
@@ -91,9 +118,9 @@
empty-db-add-core-datagenerate-resources
- com.mysql.jdbc.Driver
+ com.mysql.cj.jdbc.Driverliquibase-core-data.xml
-
+ openmrstesttrue
diff --git a/pom-step-02.xml b/pom-step-02.xml
index 96c622b..52e3ae4 100644
--- a/pom-step-02.xml
+++ b/pom-step-02.xml
@@ -18,6 +18,32 @@
+
+ ch.vorburger.mariaDB4j
+ mariaDB4j-maven-plugin
+
+ 33326
+ ${project.build.directory}/emptydatabase
+ ${project.build.directory}/emptydatabase/data
+
+
+
+
+ start-empty-database
+ initialize
+
+ start
+
+
+
+ stop-empty-database
+ process-resources
+
+ stop
+
+
+
+ org.liquibase${liquibase.plugin.artifactId}
@@ -28,7 +54,7 @@
com.mysql.jdbc.Driver${project.build.directory}/liquibase/${liquibase.cieldata.filename}
-
+ openmrstesttrue
@@ -74,6 +100,12 @@
${ciel.dictionary.openmrs.version}-${ciel.dictionary.version}zip
+
+ mysql
+ mysql-connector-java
+ 5.1.28
+ compile
+
diff --git a/pom-step-03.xml b/pom-step-03.xml
index 4cf3f0e..9eb24f7 100644
--- a/pom-step-03.xml
+++ b/pom-step-03.xml
@@ -35,6 +35,32 @@
+
+ ch.vorburger.mariaDB4j
+ mariaDB4j-maven-plugin
+
+ 33326
+ ${project.build.directory}/emptydatabase
+ ${project.build.directory}/emptydatabase/data
+
+
+
+
+ start-empty-database
+ initialize
+
+ start
+
+
+
+ stop-empty-database
+ process-resources
+
+ stop
+
+
+
+ org.liquibase${liquibase.plugin.artifactId}
@@ -43,9 +69,9 @@
empty-db-update-to-latestgenerate-resources
- com.mysql.jdbc.Driver
+ com.mysql.cj.jdbc.Driverliquibase-update-to-latest.xml
-
+ openmrstesttrue
@@ -69,9 +95,9 @@
empty-db-followupgenerate-resources
- com.mysql.jdbc.Driver
+ com.mysql.cj.jdbc.Driver${liquibase.emptydb.followup.filename}
-
+ openmrstesttrue
diff --git a/pom-step-04.xml b/pom-step-04.xml
index d85dbd3..5141d64 100644
--- a/pom-step-04.xml
+++ b/pom-step-04.xml
@@ -18,6 +18,32 @@
+
+ ch.vorburger.mariaDB4j
+ mariaDB4j-maven-plugin
+
+ 33328
+ ${project.build.directory}/demodatabase
+ ${project.build.directory}/demodatabase/data
+
+
+
+
+ start-demo-database
+ initialize
+
+ start
+
+
+
+ stop-demo-database
+ process-resources
+
+ stop
+
+
+
+ maven-antrun-plugin1.8
@@ -45,7 +71,7 @@
com.mysql.jdbc.Driver${liquibase.demodata.filename}
-
+ openmrstesttrue
@@ -85,6 +111,12 @@
identity-insert1.2.1
+
+ mysql
+ mysql-connector-java
+ 5.1.28
+ compile
+
diff --git a/pom-step-05.xml b/pom-step-05.xml
index c923560..9f2f2bb 100644
--- a/pom-step-05.xml
+++ b/pom-step-05.xml
@@ -35,6 +35,32 @@
+
+ ch.vorburger.mariaDB4j
+ mariaDB4j-maven-plugin
+
+ 33328
+ ${project.build.directory}/demodatabase
+ ${project.build.directory}/demodatabase/data
+
+
+
+
+ start-demo-database
+ initialize
+
+ start
+
+
+
+ stop-demo-database
+ process-resources
+
+ stop
+
+
+
+ org.liquibase${liquibase.plugin.artifactId}
@@ -43,9 +69,9 @@
demo-db-update-to-latestgenerate-resources
- com.mysql.jdbc.Driver
+ com.mysql.cj.jdbc.Driverliquibase-update-to-latest-from-1.9.x.xml
-
+ openmrstesttrue
@@ -69,9 +95,9 @@
demo-db-followupgenerate-resources
- com.mysql.jdbc.Driver
+ com.mysql.cj.jdbc.Driver${liquibase.demodata.followup.filename}
-
+ openmrstesttrue
@@ -93,25 +119,6 @@
-
- org.codehaus.mojo
- exec-maven-plugin
-
-
- prepare-package
-
- java
-
-
- org.openmrs.standalone.StopEmbeddedMySQL
-
- ${project.build.directory}/emptydatabase
- ${project.build.directory}/demodatabase
-
-
-
-
- org.apache.maven.pluginsmaven-dependency-plugin
@@ -205,6 +212,11 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M3
+
diff --git a/pom.xml b/pom.xml
index 6af697c..7c0a604 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,9 @@
+ 17
+ 17
+
2.6.020221104
@@ -35,7 +38,10 @@
2.4.0-SNAPSHOTUTF-8
- 7.0.50
+ 7.0.109
+ 5.7.0
+ 3.12.4
+ 3.0.1
@@ -60,21 +66,45 @@
mysqlmysql-connector-java
- 5.1.28
+ 8.0.33compile
- mysql
- mysql-connector-mxj-fixed
- 5.0.12
- compile
+ ch.vorburger.mariaDB4j
+ mariaDB4j
+ ${mariadb4jVersion}
- mysql
- mysql-connector-mxj-db-files-fixed
- 5.0.12-20170418
- compile
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junitVersion}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junitVersion}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockitoVersion}
+ test
+
+ org.mockito
+ mockito-core
+ ${mockitoVersion}
+ test
+
+
+ org.mockito
+ mockito-inline
+ ${mockitoVersion}
+ test
+
+
@@ -109,8 +139,6 @@
maven-compiler-plugintrue
-
- 1.6
@@ -124,7 +152,7 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 2.3.2
+ 3.13.0org.apache.maven.plugins
@@ -224,6 +252,19 @@
+
+ ch.vorburger.mariaDB4j
+ mariaDB4j-maven-plugin
+ ${mariadb4jVersion}
+
+ openmrs
+
+ --character-set-server=utf8
+ --collation-server=utf8_general_ci
+ --max_allowed_packet=32M
+
+
+
diff --git a/readme.txt b/readme.txt
index 1795f81..28d5246 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,11 +1,11 @@
...............QUICK SUMMARY FOR BUILDING THE STANDALONE.....................
-* Increase the maven memory: e.g. export MAVEN_OPTS="-Xms1012m -Xmx2024m -XX:PermSize=556m -XX:MaxPermSize=1012m"
+* Increase the maven memory: e.g. export MAVEN_OPTS="-Xms1012m -Xmx2024m"
* mvn clean
* mvn package -Dopenmrs.version=1.9.0
* If you are building standalone for OpenMRS 1.8.x you need to append the above command with -P1.8.x
and put in the main directory the Demo-1.8.0.sql file from https://wiki.openmrs.org/display/RES/Demo+Data
-* If running a second time, ALWAYS check to make sure mysql processes on port 3326 and 3328 are stopped.
+* If running a second time, ALWAYS check to make sure MariaDB processes on port 3326 and 3328 are stopped.
If you DON'T do that, then the "mvn clean" will not really clean.
A good command to use is: "pkill -f standalone" (kills anything with "standalone" in the path)
@@ -82,7 +82,7 @@ NOTE: Using Maven Package will generate the executable jar file in the target fo
7- For the section: "Do you currently have a database user other than root that has read/write access to the openmrs database?",
Choose Yes, and then enter a "openmrs" and "test" as the user name and password. This account will be created by the embedded database engine.
- The reason to use 'test' is that when the application starts, it checks for the mysql password and if it is test, it is replaced with a randomly
+ The reason to use 'test' is that when the application starts, it checks for the MariaDB password and if it is test, it is replaced with a randomly
generated 12 character password which is written back to the runtime properties file.
8- Click "Continue" to go to the next wizard screen, and feel free to fill what you want on this screen.
@@ -140,55 +140,34 @@ splashscreen-loading.png This is the splash screen displayed on startup. It c
............... DATABASE CONNECTION STRING.......................
-jdbc:mysql:mxj://localhost:3316/openmrs?autoReconnect=true&sessionVariables=storage_engine=InnoDB&useUnicode=true&characterEncoding=UTF-8&server.initialize-user=true&createDatabaseIfNotExist=true&server.basedir=database&server.datadir=database/data&server.collation-server=utf8_general_ci&server.character-set-server=utf8
+jdbc:mysql://127.0.0.1:3316/openmrs?autoReconnect=true&sessionVariables=storage_engine=InnoDB&useUnicode=true&characterEncoding=UTF-8
-The above default database connection string has all in the openmrs mysql default database connection string plus a
-few additional parameters as explained below:
-
-mxj This is required for the MySQL Connector/MXJ utility which we use for embedding mysql
- More information about it can be found at: http://dev.mysql.com/doc/refman/5.1/en/connector-mxj.html
-
-server.initialize-user The value of true tells the database engine to create the user account that will be specified
- in the openmrs web database setup. This is the account referred to as
- connection.username & connection.password in the runtime properties file.
-
-createDatabaseIfNotExist The value of true tells the database engine to create the database if it does not exist.
-
-server.basedir This is the directory where the mysql database server will be installed. The default value
- is a database folder in the current directory where the executable jar file is located.
-
-server.datadir This is the dirrectory where mysql stores the database. The default value is the data folder
- under the database folder in the current directory where the executable jar file is located.
-
-server.collation-server This sets the collation of the database server. If you do not set it to this value, you will
- get problems running the openmrs liquibase files. This is because the default value is swedish
- collation yet openmrs uses utf8
-
-server.character-set-server This is the character set used by the database server.
+The above default database connection string has all in the openmrs mysql default database connection string used for a MariaDB
+connection
NOTE: When creating a new database using the openmrs database setup wizard, remember to replace the default connection string
with the one above in the "Database Connection:" text field.
- The embedded mysql database engine is a fully functional database engine that you can connect too using any database
+ The embedded MariaDB4j database engine is a fully functional database engine that you can connect too using any database
GUI query tools like Navicat, EMS MySQL Manager, etc
.......................APPLICATION USER INTERFACE.....................
Tomcat Port This is the port at which to run tomcat.
-MySQL Port This is the port at which to run mysql
+MySQL Port This is the port at which to run MariaDB
-File -> Quit This menu item stops tomcat and mysql and then closes the application.
+File -> Quit This menu item stops tomcat and MariaDB and then closes the application.
File -> Launch Browser This menu item opens the openmrs login page for the current web application context.
File -> Clear Output This clears the output log in the user interface text area. But does not clear the log file
written on the file system.
-Start This button runs tomcat, which will automatically start the mysql database engine if it
- was not already running. For the embedded mysql, the first connection automatically starts
- the mysql engine.
+Start This button runs tomcat, which will automatically start the MariaDB database engine if it
+ was not already running. For the embedded MariaDB4j, the first connection automatically starts
+ the MariaDB engine.
-Stop This button stops tomcat and then also stops the mysql database engine, without closing the application.
+Stop This button stops tomcat and then also stops the MariaDB database engine, without closing the application.
NOTE: Minimizing or Maximizing the application window does not have any effect on the server. The window close icon will stop
@@ -202,7 +181,7 @@ NOTE: Minimizing or Maximizing the application window does not have any effect o
Running from command line requires the -commandline switch.
e.g. java -jar standalone-0.0.1-SNAPSHOT.jar -commandline
--mysqlport: Use to override the mysql port in the runtime properties file.
+-mysqlport: Use to override the database port in the runtime properties file.
-tomcatport: Use to override the tomcat port in the runtime properties file.
start Use to start the server.
stop Use to stop the server.
@@ -251,9 +230,5 @@ SUMMARY: Using a single package for all (most) platforms approximately tripples
-MySQL MXJ documentation can be found at:
-http://dev.mysql.com/doc/refman/5.1/en/connector-mxj.html
-
-Details on how to add or remove platform specific databases can be found at:
-http://dev.mysql.com/doc/refman/5.1/en/connector-mxj-usagenotes-packaging.html
-http://blog.teamlazerbeez.com/2011/10/03/embedded-mysql-on-java-with-connectormxj-and-64-bit-linux/
+MariaDB4j documentation can be found at:
+https://github.com/MariaDB4j/MariaDB4j
diff --git a/src/main/config/README.txt b/src/main/config/README.txt
index 8f84c17..cc45d6d 100644
--- a/src/main/config/README.txt
+++ b/src/main/config/README.txt
@@ -86,17 +86,17 @@ GUI MODE OPTIONS
================
Tomcat Port This is the port at which to run tomcat.
-MySQL Port This is the port at which to run mysql
-File → Quit This menu item stops tomcat and mysql and then closes the application.
+MySQL Port This is the port at which to run MariaDB
+File → Quit This menu item stops tomcat and MariaDB and then closes the application.
File → Launch Browser This menu item opens the openmrs login page for the current web application context.
File → Clear Output This clears the output log in the user interface text area. But does not clear the log file written on the file system.
-Start This button runs tomcat, which will automatically start the mysql database engine if it was not already running. For the embedded mysql, the first connection automatically starts the mysql engine.
-Stop This button stops tomcat and then also stops the mysql database engine, without closing the application.
+Start This button runs tomcat, which will automatically start the MariaDB database engine if it was not already running. For the embedded MariaDB4j, the first connection automatically starts the MariaDB engine.
+Stop This button stops tomcat and then also stops the MariaDB database engine, without closing the application.
COMMAND LINE OPTIONS
====================
--mysqlport Use to override the mysql port in the runtime properties file.
+-mysqlport Use to override the MariaDB port in the runtime properties file.
-tomcatport Use to override the tomcat port in the runtime properties file.
-start Use to start the server.
-stop Use to stop the server.
diff --git a/src/main/config/openmrs-standalone-runtime.properties b/src/main/config/openmrs-standalone-runtime.properties
index b84d834..79ae54f 100644
--- a/src/main/config/openmrs-standalone-runtime.properties
+++ b/src/main/config/openmrs-standalone-runtime.properties
@@ -4,12 +4,12 @@
module.allow_web_admin=true
# this connection url is copied several times in pom.xml, with the directory changed from database to emptydatabase and 3316 changed to 3326.
# If you change the property here, make sure to change it there too.
-connection.url=jdbc:mysql:mxj://127.0.0.1:3316/openmrs?autoReconnect=true&sessionVariables=storage_engine=InnoDB&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&server.initialize-user=true&createDatabaseIfNotExist=true&server.basedir=database&server.datadir=database/data&server.collation-server=utf8_general_ci&server.character-set-server=utf8&server.max_allowed_packet=96M
+connection.url=jdbc:mysql://127.0.0.1:3316/openmrs?autoReconnect=true&sessionVariables=storage_engine=InnoDB&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
connection.username=openmrs
auto_update_database=false
connection.password=test
tomcatport=8081
application_data_directory=appdata
reset_connection_password=true
-vm_arguments=-Xmx512m -Xms512m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:NewSize=128m
+vm_arguments=-Xmx512m -Xms512m -XX:NewSize=128m
diff --git a/src/main/java/org/openmrs/standalone/ApplicationController.java b/src/main/java/org/openmrs/standalone/ApplicationController.java
index 6e3da6d..a27ea70 100644
--- a/src/main/java/org/openmrs/standalone/ApplicationController.java
+++ b/src/main/java/org/openmrs/standalone/ApplicationController.java
@@ -13,6 +13,8 @@
*/
package org.openmrs.standalone;
+import static org.openmrs.standalone.MariaDbController.stopMariaDB;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -25,6 +27,8 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import ch.vorburger.exec.ManagedProcessException;
+
/**
* Manages the application workflow.
*/
@@ -230,7 +234,13 @@ private void init(boolean commandLineMode, boolean nonInteractive, DatabaseMode
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
- stopServer();
+ try {
+ stopMariaDB();
+ } catch (ManagedProcessException e) {
+ System.out.println("Failed to stop MariaDB: " + e.getMessage());
+ e.printStackTrace();
+ }
+ stopServer();
}
});
@@ -243,17 +253,17 @@ public void run() {
if (applyDatabaseChange == DatabaseMode.USE_INITIALIZATION_WIZARD) {
deleteActiveDatabase();
StandaloneUtil.resetConnectionPassword();
- StandaloneUtil.startupDatabaseToCreateDefaultUser();
+ StandaloneUtil.startupDatabaseToCreateDefaultUser(mySqlPort);
} else if (applyDatabaseChange == DatabaseMode.EMPTY_DATABASE) {
deleteActiveDatabase();
unzipDatabase(new File("emptydatabase.zip"));
StandaloneUtil.resetConnectionPassword();
- StandaloneUtil.startupDatabaseToCreateDefaultUser();
+ StandaloneUtil.startupDatabaseToCreateDefaultUser(mySqlPort);
} else if (applyDatabaseChange == DatabaseMode.DEMO_DATABASE) {
deleteActiveDatabase();
unzipDatabase(new File("demodatabase.zip"));
StandaloneUtil.resetConnectionPassword();
- StandaloneUtil.startupDatabaseToCreateDefaultUser();
+ StandaloneUtil.startupDatabaseToCreateDefaultUser(mySqlPort);
}
deleteNeedsConfigFile();
@@ -395,8 +405,9 @@ private String startServer() {
//some stuff in this directory.
deleteTomcatWorkDir();
- StandaloneUtil.setPortsAndMySqlPassword(userInterface.getMySqlPort(), userInterface.getTomcatPort() + "");
-
+ String mySqlPort = StandaloneUtil.setPortsAndMySqlPassword(userInterface.getMySqlPort(), userInterface.getTomcatPort() + "");
+ MariaDbController.startMariaDB(mySqlPort);
+
contextName = StandaloneUtil.getContextName();
tomcatManager = null;
tomcatManager = new TomcatManager(contextName, userInterface.getTomcatPort());
diff --git a/src/main/java/org/openmrs/standalone/Bootstrap.java b/src/main/java/org/openmrs/standalone/Bootstrap.java
index e6b07bc..b4540e0 100644
--- a/src/main/java/org/openmrs/standalone/Bootstrap.java
+++ b/src/main/java/org/openmrs/standalone/Bootstrap.java
@@ -24,6 +24,8 @@
import java.io.PrintWriter;
import java.util.Properties;
+import ch.vorburger.exec.ManagedProcessException;
+
/**
* The only reason for existence of this class is to enable us increase tomcat memory by passing the
* JVM options as advised at http://wiki.openmrs.org/display/docs/Out+Of+Memory+Errors. Since we
@@ -95,8 +97,10 @@ private void launch(String args, boolean showSplashScreen) {
try {
Properties properties = OpenmrsUtil.getRuntimeProperties(StandaloneUtil.getContextName());
- String vm_arguments = properties.getProperty("vm_arguments", "-Xmx512m -Xms512m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:NewSize=128m");
-
+ String debugArguments = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005";
+ String vm_arguments = properties.getProperty("vm_arguments", "-Xmx512m -Xms512m -XX:NewSize=128m");
+ vm_arguments = debugArguments + " " + vm_arguments;
+
// Spin up a separate java process calling a non-default Main class in our Jar.
process = Runtime.getRuntime().exec(
"java " + (showSplashScreen ? "-splash:splashscreen-loading.png" : "")
@@ -152,8 +156,13 @@ public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
- StandaloneUtil.stopMySqlServer();
- }
+ try {
+ MariaDbController.stopMariaDB();
+ } catch (ManagedProcessException e) {
+ System.out.println("Failed to stop MariaDB: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
});
new Bootstrap().launch(commandLineArguments, showSplashScreen);
diff --git a/src/main/java/org/openmrs/standalone/MainFrame.java b/src/main/java/org/openmrs/standalone/MainFrame.java
index b730bc9..2522e9d 100644
--- a/src/main/java/org/openmrs/standalone/MainFrame.java
+++ b/src/main/java/org/openmrs/standalone/MainFrame.java
@@ -31,12 +31,9 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowStateListener;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Method;
-import java.net.URL;
import java.util.Arrays;
import java.util.List;
diff --git a/src/main/java/org/openmrs/standalone/MariaDbController.java b/src/main/java/org/openmrs/standalone/MariaDbController.java
new file mode 100644
index 0000000..aaa96b6
--- /dev/null
+++ b/src/main/java/org/openmrs/standalone/MariaDbController.java
@@ -0,0 +1,81 @@
+package org.openmrs.standalone;
+
+import java.nio.file.Paths;
+import java.util.Properties;
+
+import ch.vorburger.exec.ManagedProcessException;
+import ch.vorburger.mariadb4j.DB;
+import ch.vorburger.mariadb4j.DBConfigurationBuilder;
+import org.apache.commons.lang3.RandomStringUtils;
+
+public class MariaDbController {
+
+ public static final String DATABASE_NAME = "openmrs";
+ private static final String MARIA_DB_BASE_DIR = "database";
+ private static final String MARIA_DB_DATA_DIR = Paths.get(MARIA_DB_BASE_DIR, "data").toString();
+
+ private static DB mariaDB;
+ private static DBConfigurationBuilder mariaDBConfig;
+ private static String rootPassword;
+
+ public static String KEY_MARIADB_BASE_DIR = "mariadb.basedir";
+ public static String KEY_MARIADB_DATA_DIR = "mariadb.datadir";
+
+ public static void startMariaDB(String port) throws Exception {
+ startMariaDB(Integer.parseInt(port));
+ }
+
+ public static void startMariaDB(int port) throws Exception {
+ mariaDBConfig = DBConfigurationBuilder.newBuilder();
+ mariaDBConfig.setPort(port);
+ mariaDBConfig.setSecurityDisabled(false);
+
+ Properties properties = OpenmrsUtil.getRuntimeProperties(StandaloneUtil.getContextName());
+
+ String baseDir = safeResolveProperty(properties, KEY_MARIADB_BASE_DIR, MARIA_DB_BASE_DIR);
+ String dataDir = safeResolveProperty(properties, KEY_MARIADB_DATA_DIR, MARIA_DB_DATA_DIR);
+
+ mariaDBConfig.setBaseDir(Paths.get(baseDir).toAbsolutePath().toString());
+ mariaDBConfig.setDataDir(Paths.get(dataDir).toAbsolutePath().toString());
+
+ mariaDBConfig.addArg("--max_allowed_packet=96M");
+ mariaDBConfig.addArg("--collation-server=utf8_general_ci");
+ mariaDBConfig.addArg("--character-set-server=utf8");
+
+ mariaDB = DB.newEmbeddedDB(mariaDBConfig.build());
+
+ mariaDB.start();
+
+ // Starting with MariaDB 10.4, the root user has an invalid password.
+ // We will therefore modify the root user password to a secure random string (a security best practice).
+ // Using the UID of the user that owns the data directory, we can execute this initial bootstrapping command:
+ // Note that on Windows MariaDB apparently does not implement this, still uses empty string password for the
+ // root user, so we can just use the root user.
+ if (rootPassword != null) {
+ rootPassword = RandomStringUtils.random(69, 97, 122, true, true);
+ mariaDB.run("SET PASSWORD FOR 'root'@'localhost' = PASSWORD('" + rootPassword + "');",
+ mariaDBConfig.isWindows() ? "root" : System.getProperty("user.name"), "");
+ }
+
+ mariaDB.createDB(DATABASE_NAME, "root", MariaDbController.getRootPassword());
+ }
+
+ private static String safeResolveProperty(Properties properties, String key, String defaultValue) {
+ if (properties == null || !properties.containsKey(key)) {
+ return defaultValue;
+ }
+ return properties.getProperty(key, defaultValue);
+ }
+
+ public static void stopMariaDB() throws ManagedProcessException {
+ if (mariaDB != null) {
+ mariaDB.stop();
+ } else {
+ System.out.println("MariaDB has already been stopped");
+ }
+ }
+
+ public static String getRootPassword() {
+ return rootPassword;
+ }
+}
diff --git a/src/main/java/org/openmrs/standalone/StandaloneUtil.java b/src/main/java/org/openmrs/standalone/StandaloneUtil.java
index 9561ab0..13e9ee8 100644
--- a/src/main/java/org/openmrs/standalone/StandaloneUtil.java
+++ b/src/main/java/org/openmrs/standalone/StandaloneUtil.java
@@ -28,6 +28,8 @@
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
@@ -37,7 +39,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.mysql.management.driverlaunched.ServerLauncherSocketFactory;
+import ch.vorburger.exec.ManagedProcessException;
/**
* Utility routines used by the standalone application.
@@ -134,33 +136,10 @@ public static String setPortsAndMySqlPassword(String mySqlPort, String tomcatPor
String username = properties.getProperty(KEY_CONNECTION_USERNAME);
String resetConnectionPassword = properties.getProperty(KEY_RESET_CONNECTION_PASSWORD);
- //We change the mysql password only if it is test.
- //if (password != null && password.toLowerCase().equals("test")) {
-
- //Change the mysql password if instructed to.
- if ("true".equalsIgnoreCase(resetConnectionPassword)) {
- String newPassword = "";
- // intentionally left out these characters: ufsb$() to prevent certain words forming randomly
- String chars = "acdeghijklmnopqrtvwxyzACDEGHIJKLMNOPQRTVWXYZ0123456789.|~@^&";
- Random r = new Random();
- for (int x = 0; x < 12; x++) {
- newPassword += chars.charAt(r.nextInt(chars.length()));
- }
-
- if (setMysqlPassword(connectionString, username, password, newPassword)) {
- properties.put(KEY_CONNECTION_PASSWORD, newPassword);
-
- //Now remove the reset connection password property such that we do not change the password again.
- properties.remove(KEY_RESET_CONNECTION_PASSWORD);
-
- propertiesFileChanged = true;
- }
- }
-
String portToken = ":" + mySqlPort + "/";
- //in a string like this: jdbc:mysql:mxj://localhost:3306/openmrs?autoReconnect=true
- //look for something like this :3306/
+ //in a string like this: jdbc:mysql://localhost:3316/openmrs?autoReconnect=true
+ //look for something like this :3316/
String regex = ":[0-9]+/";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(connectionString);
@@ -183,7 +162,30 @@ public static String setPortsAndMySqlPassword(String mySqlPort, String tomcatPor
mySqlPort = mySqlPort.replace("/", "");
}
}
-
+
+ //We change the mysql password only if it is test.
+ //if (password != null && password.toLowerCase().equals("test")) {
+
+ //Change the mysql password if instructed to.
+ if ("true".equalsIgnoreCase(resetConnectionPassword)) {
+ String newPassword = "";
+ // intentionally left out these characters: ufsb$() to prevent certain words forming randomly
+ String chars = "acdeghijklmnopqrtvwxyzACDEGHIJKLMNOPQRTVWXYZ0123456789.|~@^&";
+ Random r = new Random();
+ for (int x = 0; x < 12; x++) {
+ newPassword += chars.charAt(r.nextInt(chars.length()));
+ }
+
+ if (setMysqlPassword(connectionString, mySqlPort, username, password, newPassword)) {
+ properties.put(KEY_CONNECTION_PASSWORD, newPassword);
+
+ //Now remove the reset connection password property such that we do not change the password again.
+ properties.remove(KEY_RESET_CONNECTION_PASSWORD);
+
+ propertiesFileChanged = true;
+ }
+ }
+
if (tomcatPort != null) {
if (!tomcatPort.equals(properties.get(KEY_TOMCAT_PORT))) {
properties.put(KEY_TOMCAT_PORT, tomcatPort);
@@ -302,46 +304,42 @@ public static String getContextName() {
return CONTEXT_NAME;
}
-
- private static boolean setMysqlPassword(String url, String username, String oldPassword, String newPassword) {
-
- Connection connection = null;
+
+ private static boolean setMysqlPassword(String url, String mysqlPort, String username, String oldPassword, String newPassword) {
+
try {
- Class.forName("com.mysql.jdbc.Driver").newInstance();
-
- String sql = "update mysql.user set password=PASSWORD('" + newPassword + "') where User='" + username + "';";
- connection = DriverManager.getConnection(url, username, oldPassword);
- Statement statement = connection.createStatement();
- statement.executeUpdate(sql);
-
- StandaloneUtil.stopMySqlServer();
-
- return true;
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- finally {
- try {
- if (connection != null) {
- connection.close();
- }
- }
- catch (Exception ex) {
+ Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
+
+ MariaDbController.startMariaDB(mysqlPort);
+
+ String sql = "SET PASSWORD FOR '" + username + "'@localhost = PASSWORD(?);";
+
+ try (Connection connection = DriverManager.getConnection(url, "root", MariaDbController.getRootPassword());
+ PreparedStatement statement = connection.prepareStatement(sql)) {
+
+ statement.setString(1, newPassword);
+
+ statement.executeUpdate();
+
+ return true;
+
+ } catch (SQLException ex) {
ex.printStackTrace();
+ return false;
}
- }
-
- return false;
- }
-
- public static void stopMySqlServer() {
- try {
- ServerLauncherSocketFactory.shutdown(new File("database"), new File("database/data"));
- }
- catch (Exception exception) {
- System.out.println("Cannot Stop MySQL" + exception.getMessage());
- }
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return false;
+
+ } finally {
+ try {
+ MariaDbController.stopMariaDB();
+ } catch (ManagedProcessException e) {
+ System.out.println("Failed to stop MariaDB: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
}
/**
@@ -403,29 +401,38 @@ private static void updateRuntimeProperties(Map newProps) {
/**
- * Starts and stops MySQL, so that mxj can create the default user
+ * Starts and stops MySQL, so that MariaDB can create the default user
* @throws Exception
*/
- public static void startupDatabaseToCreateDefaultUser() throws Exception {
- try {
- Class.forName("com.mysql.jdbc.Driver");
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException("cannot find mysql driver class");
- }
- Properties props = OpenmrsUtil.getRuntimeProperties(getContextName());
- String url = props.getProperty("connection.url");
- if (!url.contains("server.initialize-user=true"))
- throw new RuntimeException("connection.url in runtime properties must contain server.initialize-user=true");
+ public static void startupDatabaseToCreateDefaultUser(String mysqlPort) throws Exception {
+ try {
+ Class.forName("com.mysql.cj.jdbc.Driver");
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException("cannot find mysql driver class", ex);
+ }
+ Properties props = OpenmrsUtil.getRuntimeProperties(getContextName());
+ String url = props.getProperty("connection.url");
System.out.println("Working directory is " + new File(".").getAbsolutePath());
- System.out.println("Opening MySQL connection to create openmrs/test users");
- Connection conn = DriverManager.getConnection(url, "openmrs", "test");
- conn.close();
- System.out.println("closed MySQL connection");
- stopMySqlServer();
- }
-
-
+ System.out.println("Opening MariaDB connection to create openmrs/test users");
+
+ MariaDbController.startMariaDB(mysqlPort);
+
+ try (Connection conn = DriverManager.getConnection(url, "root", MariaDbController.getRootPassword());
+ Statement stmt = conn.createStatement()) {
+
+ String createUserSQL = "CREATE USER IF NOT EXISTS 'openmrs'@'localhost' IDENTIFIED BY 'test';";
+ stmt.executeUpdate(createUserSQL);
+
+ String grantPrivilegesSQL = "GRANT ALL PRIVILEGES ON openmrs.* TO 'openmrs'@'localhost' WITH GRANT OPTION;";
+ stmt.executeUpdate(grantPrivilegesSQL);
+
+ } finally {
+ MariaDbController.stopMariaDB();
+ }
+ }
+
+
/**
* Sets the MySQL and Tomcat ports in the run time properties file.
*
@@ -446,8 +453,8 @@ public static String setRuntimePropertiesFileMysqlAndTomcatPorts(String mySqlPor
String connectionString = properties.getProperty(KEY_CONNECTION_URL);
String portToken = ":" + mySqlPort + "/";
- //in a string like this: jdbc:mysql:mxj://localhost:3306/openmrs?autoReconnect=true
- //look for something like this :3306/
+ //in a string like this: jdbc:mysql://localhost:3316/openmrs?autoReconnect=true
+ //look for something like this :3316/
String regex = ":[0-9]+/";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(connectionString);
diff --git a/src/main/java/org/openmrs/standalone/StopEmbeddedMySQL.java b/src/main/java/org/openmrs/standalone/StopEmbeddedMySQL.java
deleted file mode 100644
index 118a6a1..0000000
--- a/src/main/java/org/openmrs/standalone/StopEmbeddedMySQL.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * The contents of this file are subject to the OpenMRS Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://license.openmrs.org
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * Copyright (C) OpenMRS, LLC. All Rights Reserved.
- */
-package org.openmrs.standalone;
-
-import java.io.File;
-
-import com.mysql.management.driverlaunched.ServerLauncherSocketFactory;
-
-/**
- * It is used to stop embedded database.
- */
-public class StopEmbeddedMySQL {
-
- public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- throw new IllegalArgumentException("Must be called with at least one argument pointing to a database directory!");
- }
-
- for (int i = 0; i < args.length; i++) {
- ServerLauncherSocketFactory.shutdown(new File(args[i]), null);
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openmrs/standalone/TomcatManager.java b/src/main/java/org/openmrs/standalone/TomcatManager.java
index 7793a64..5a18429 100644
--- a/src/main/java/org/openmrs/standalone/TomcatManager.java
+++ b/src/main/java/org/openmrs/standalone/TomcatManager.java
@@ -22,6 +22,7 @@
import java.security.AccessControlException;
import java.util.Random;
+import ch.vorburger.exec.ManagedProcessException;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
@@ -119,10 +120,15 @@ public boolean stop() {
return false;
}
- //stop mysql.
- if(stopMySql)
- StandaloneUtil.stopMySqlServer();
-
+ if(stopMySql) {
+ try {
+ MariaDbController.stopMariaDB();
+ } catch (ManagedProcessException e) {
+ System.out.println("Failed to stop MariaDB: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
return true;
}
diff --git a/src/test/java/org/openmrs/standalone/MariaDbControllerTest.java b/src/test/java/org/openmrs/standalone/MariaDbControllerTest.java
new file mode 100644
index 0000000..ce88642
--- /dev/null
+++ b/src/test/java/org/openmrs/standalone/MariaDbControllerTest.java
@@ -0,0 +1,110 @@
+package org.openmrs.standalone;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+public class MariaDbControllerTest {
+
+ private static final int MARIADB_PORT = 33126;
+ private static final String JDBC_URL = "jdbc:mysql://127.0.0.1:" + MARIADB_PORT + "/" + MariaDbController.DATABASE_NAME;
+ private static final String ROOT_USER = "root";
+
+ private static final String MARIADB_BASEDIR_NAME = "mariadb-base-dir";
+
+ private Properties properties;
+ private Path tempBaseDir;
+ private final String dataDirName = "data";
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ properties = new Properties();
+
+ tempBaseDir = Paths.get("target", MARIADB_BASEDIR_NAME);
+ Files.createDirectories(tempBaseDir);
+
+ String dataDir = Paths.get(tempBaseDir.toString(), dataDirName).toString();
+
+ properties.setProperty(MariaDbController.KEY_MARIADB_BASE_DIR, tempBaseDir.toString());
+ properties.setProperty(MariaDbController.KEY_MARIADB_DATA_DIR, dataDir);
+ }
+
+ @AfterEach
+ public void tearDown() throws IOException {
+ if (Files.exists(tempBaseDir)) {
+ FileUtils.deleteDirectory(tempBaseDir.toFile());
+ }
+
+ if (Files.exists(tempBaseDir)) {
+ fail("Failed to delete temp base directory");
+ }
+ }
+
+ @Test
+ public void shouldStartAndStopMariaDB() throws Exception {
+ try (MockedStatic ignored = Mockito.mockStatic(OpenmrsUtil.class)) {
+ when(OpenmrsUtil.getRuntimeProperties(anyString())).thenReturn(properties);
+ when(OpenmrsUtil.getRuntimeProperties(Mockito.nullable(String.class))).thenReturn(properties);
+
+ MariaDbController.startMariaDB(MARIADB_PORT);
+
+ validateMariaDBRunning();
+
+ MariaDbController.stopMariaDB();
+
+ validateMariaDBStopped();
+ }
+ }
+
+ @Test
+ void shouldIgnoreStopMariaDBWhenNotStartedAndNotThrow() {
+ try (MockedStatic ignored = Mockito.mockStatic(OpenmrsUtil.class)) {
+ when(OpenmrsUtil.getRuntimeProperties(anyString())).thenReturn(properties);
+ when(OpenmrsUtil.getRuntimeProperties(Mockito.nullable(String.class))).thenReturn(properties);
+
+ validateMariaDBStopped();
+ try {
+ MariaDbController.stopMariaDB();
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ }
+
+ private void validateMariaDBRunning() {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL, ROOT_USER, MariaDbController.getRootPassword())) {
+ assertNotNull(conn, "Connection to MariaDB should not be null");
+ assertFalse(conn.isClosed(), "Connection to MariaDB should be open");
+ } catch (SQLException e) {
+ fail("MariaDB should start and accept connections. Exception: " + e.getMessage());
+ }
+ }
+
+ private void validateMariaDBStopped() {
+ SQLException exception = assertThrows(SQLException.class, () -> {
+ try (Connection ignored = DriverManager.getConnection(JDBC_URL, ROOT_USER, MariaDbController.getRootPassword())) {
+ // Attempt to connect
+ }
+ });
+ assertNotNull(exception.getMessage(), "Expected a SQLException when MariaDB is stopped");
+ }
+}
diff --git a/src/test/java/org/openmrs/standalone/StandaloneUtilTest.java b/src/test/java/org/openmrs/standalone/StandaloneUtilTest.java
new file mode 100644
index 0000000..f669731
--- /dev/null
+++ b/src/test/java/org/openmrs/standalone/StandaloneUtilTest.java
@@ -0,0 +1,189 @@
+package org.openmrs.standalone;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+class StandaloneUtilTest {
+
+
+ private static final String KEY_CONNECTION_PASSWORD = "connection.password";
+ private static final String KEY_RESET_CONNECTION_PASSWORD = "reset_connection_password";
+ private static final String KEY_CONNECTION_URL = "connection.url";
+ private static final String KEY_CONNECTION_USERNAME = "connection.username";
+ private static final String TEST_PASSWORD = "test";
+
+ private static final String USERNAME = "openmrs";
+ private static final String MARIADB_PORT = "33126";
+ private static final String DEFAULT_URL = "jdbc:mysql://127.0.0.1:" + MARIADB_PORT + "/" + MariaDbController.DATABASE_NAME;
+
+ private static final String MARIADB_BASEDIR_NAME = "mariadb-base-dir";
+ private static final String DATA_DIR_NAME = "data";
+
+ private Properties properties;
+ private Path tempBaseDir;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ properties = new Properties();
+ properties.setProperty(KEY_CONNECTION_USERNAME, USERNAME);
+ properties.setProperty(KEY_CONNECTION_PASSWORD, TEST_PASSWORD);
+ properties.setProperty(KEY_CONNECTION_URL, DEFAULT_URL);
+ properties.setProperty(KEY_RESET_CONNECTION_PASSWORD, "false");
+
+ tempBaseDir = Paths.get("target", MARIADB_BASEDIR_NAME);
+ Files.createDirectories(tempBaseDir);
+
+ String dataDir = Paths.get(tempBaseDir.toString(), DATA_DIR_NAME).toString();
+
+ properties.setProperty(MariaDbController.KEY_MARIADB_BASE_DIR, tempBaseDir.toString());
+ properties.setProperty(MariaDbController.KEY_MARIADB_DATA_DIR, dataDir);
+ }
+
+ @AfterEach
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(tempBaseDir.toFile());
+
+ if (Files.exists(tempBaseDir)) {
+ fail("Failed to delete temp base directory");
+ }
+ }
+
+ @Test
+ public void shouldCreateDefaultUser() throws Exception {
+ try (MockedStatic mockUtil = Mockito.mockStatic(OpenmrsUtil.class)) {
+ when(OpenmrsUtil.getRuntimeProperties(anyString())).thenReturn(properties);
+ when(OpenmrsUtil.getRuntimeProperties(Mockito.nullable(String.class))).thenReturn(properties);
+
+ StandaloneUtil.startupDatabaseToCreateDefaultUser(MARIADB_PORT);
+
+ MariaDbController.startMariaDB(MARIADB_PORT);
+ try (Connection connection = DriverManager.getConnection(DEFAULT_URL, "root", MariaDbController.getRootPassword())) {
+
+ assertNotNull(connection, "Connection to MariaDB with 'root' user should not be null");
+ assertFalse(connection.isClosed(), "Connection to MariaDB should be open");
+
+ try (Statement stmt = connection.createStatement()) {
+ ResultSet resultSet = stmt.executeQuery(
+ "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '" + USERNAME + "')"
+ );
+ if (resultSet.next()) {
+ assertTrue(resultSet.getInt(1) == 1, "'openmrs' user should be created");
+ } else {
+ fail("'openmrs' user does not exist in the database");
+ }
+
+ // Verify that the 'openmrs' user has the required privileges
+ resultSet = stmt.executeQuery(
+ "SHOW GRANTS FOR 'openmrs'@'localhost';"
+ );
+ boolean privilegesCorrect = false;
+ while (resultSet.next()) {
+ String grant = resultSet.getString(1);
+ if (grant.contains("GRANT ALL PRIVILEGES ON `openmrs`.* TO 'openmrs'@'localhost'")) {
+ privilegesCorrect = true;
+ break;
+ }
+ }
+ assertTrue(privilegesCorrect, "'openmrs' user should have the correct privileges");
+ }
+ } catch (
+ SQLException e) {
+ fail("Could not connect to MariaDB with 'root' user or verify user creation: " + e.getMessage());
+ } finally {
+ MariaDbController.stopMariaDB();
+ }
+ }
+ }
+
+ @Test
+ public void shouldKeepTestPasswordWhenResetFlagIsFalse() throws Exception {
+ assertEquals("false", properties.getProperty(KEY_RESET_CONNECTION_PASSWORD));
+ String resultPort;
+ try (MockedStatic mockUtil = Mockito.mockStatic(OpenmrsUtil.class)) {
+ when(OpenmrsUtil.getRuntimeProperties(anyString())).thenReturn(properties);
+ when(OpenmrsUtil.getRuntimeProperties(Mockito.nullable(String.class))).thenReturn(properties);
+
+ StandaloneUtil.startupDatabaseToCreateDefaultUser(MARIADB_PORT);
+ resultPort = StandaloneUtil.setPortsAndMySqlPassword(null, null);
+
+
+ assertEquals(MARIADB_PORT, resultPort);
+
+ MariaDbController.startMariaDB(resultPort);
+ try (Connection connection = DriverManager.getConnection(
+ DEFAULT_URL, USERNAME, TEST_PASSWORD)) {
+
+ assertNotNull(connection, "Connection to MariaDB with '" + USERNAME + "' user should not be null");
+ assertFalse(connection.isClosed(), "Connection to MariaDB should be open");
+
+ } catch (SQLException e) {
+ fail("Could not connect to MariaDB with user '" + USERNAME + "' and password 'test'");
+ } finally {
+ MariaDbController.stopMariaDB();
+ }
+ }
+ }
+
+ @Test
+ public void shouldChangePasswordWhenResetFlagIsTrue() throws Exception {
+ properties.setProperty(KEY_RESET_CONNECTION_PASSWORD, "true");
+ assertEquals("true", properties.getProperty(KEY_RESET_CONNECTION_PASSWORD));
+ Path tempDirectory = Files.createTempDirectory("openmrsTest");
+ String resultPort;
+ try (MockedStatic mockUtil = Mockito.mockStatic(OpenmrsUtil.class)) {
+ Path propertiesFile = tempDirectory.resolve("runtime.properties");
+
+ when(OpenmrsUtil.getRuntimeProperties(anyString())).thenReturn(properties);
+ when(OpenmrsUtil.getRuntimeProperties(Mockito.nullable(String.class))).thenReturn(properties);
+ when(OpenmrsUtil.getRuntimePropertiesPathName())
+ .thenReturn(tempDirectory.resolve(propertiesFile.getFileName()).toString());
+
+ StandaloneUtil.startupDatabaseToCreateDefaultUser(MARIADB_PORT);
+ resultPort = StandaloneUtil.setPortsAndMySqlPassword(null, null);
+
+ Files.deleteIfExists(propertiesFile);
+ Files.deleteIfExists(tempDirectory);
+
+ assertEquals(MARIADB_PORT, resultPort);
+
+ MariaDbController.startMariaDB(resultPort);
+ String newPassword = properties.getProperty(KEY_CONNECTION_PASSWORD);
+ assertNotEquals(TEST_PASSWORD, newPassword);
+ try (Connection connection = DriverManager.getConnection(
+ DEFAULT_URL, USERNAME, newPassword)) {
+
+ assertNotNull(connection, "Connection to MariaDB with 'openmrs' user should not be null");
+ assertFalse(connection.isClosed(), "Connection to MariaDB should be open");
+
+ } catch (SQLException e) {
+ fail("Could not connect to MariaDB with user 'openmrs' and password '" + newPassword + "'");
+ } finally {
+ MariaDbController.stopMariaDB();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/stop-mysql.sh b/stop-mysql.sh
index 9a68e59..4f6d47b 100644
--- a/stop-mysql.sh
+++ b/stop-mysql.sh
@@ -1,9 +1,9 @@
#!/bin/bash
-stopMysql() {
+stopMariaDB() {
fuser -k 33326/tcp
fuser -k 33328/tcp
exit 0
}
-stopMysql
+stopMariaDB