Skip to content

Commit

Permalink
Add mybatis runtime feature (#565)
Browse files Browse the repository at this point in the history
* add mybatis runtime feature

* remove run_migration task from ci

* update configs module

* remove unused variables

* remove data migration scripts

* update server core version

* update configs module
  • Loading branch information
bennsimon authored Jun 15, 2022
1 parent 08c5000 commit d186eff
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 6 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ jobs:

- name: Show running services
run: sudo netstat -tuplen # listing all the port for debug purpose.

- name: Configure migrations
run: chmod +x configs/assets/migrations/run_mybatis_migrations.sh && sudo ./configs/assets/migrations/run_mybatis_migrations.sh


- name: Create multimedia dir
run: sudo mkdir -p /opt/multimedia/patient_images && id

Expand Down
16 changes: 15 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<artifactId>opensrp-server-core</artifactId>
<packaging>jar</packaging>
<version>2.13.5-SNAPSHOT</version>
<version>2.14.0-SNAPSHOT</version>
<name>opensrp-server-core</name>
<description>OpenSRP Server Core module</description>
<url>https://github.com/OpenSRP/opensrp-server-core</url>
Expand Down Expand Up @@ -327,6 +327,12 @@
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-migrations -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-migrations</artifactId>
<version>3.3.10</version>
</dependency>

<!-- Test dependencies -->
<dependency>
Expand Down Expand Up @@ -398,6 +404,14 @@
<directory>src/main/java/org/opensrp/repository/postgres/mapper/custom/xml</directory>
<targetPath>org/opensrp/repository/postgres/mapper/custom/xml</targetPath>
</resource>
<resource>
<directory>configs/assets/migrations/environments</directory>
<targetPath>mybatis/environments</targetPath>
</resource>
<resource>
<directory>configs/assets/migrations/scripts</directory>
<targetPath>mybatis/scripts</targetPath>
</resource>
</resources>
<plugins>
<plugin>
Expand Down
72 changes: 72 additions & 0 deletions src/main/java/org/opensrp/migrations/MybatisMigration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.opensrp.migrations;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.ibatis.migration.DataSourceConnectionProvider;
import org.apache.ibatis.migration.FileMigrationLoader;
import org.apache.ibatis.migration.operations.UpOperation;
import org.apache.ibatis.migration.options.DatabaseOperationOption;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

@Component
public class MybatisMigration {

private static Logger logger = LogManager.getLogger(MybatisMigration.class.getName());

@Autowired
private DataSource dataSource;

private static final String CONFIG_FILE = "mybatis/environments/deployment.properties";

private static final String SCRIPTS_FOLDER = "mybatis/scripts";

@PostConstruct
public void initializeMybatisMigration() {
logger.info("Running migrations.");
Resource resource = new ClassPathResource(CONFIG_FILE);
try {
Properties props = PropertiesLoaderUtils.loadProperties(resource);
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();

JSONObject dbOperationOptionObject = new JSONObject(gson.toJson(new DatabaseOperationOption()));
for(String key : dbOperationOptionObject.keySet()){
if(props.containsKey(key)){
dbOperationOptionObject.put(key, props.getProperty(key));
}
}

DatabaseOperationOption databaseOperationOption = gson.fromJson(dbOperationOptionObject.toString(), DatabaseOperationOption.class);

runMigrationOperation(props, databaseOperationOption);

logger.info("Migration done.");
}
catch (IOException e) {
logger.error(e);
}
}

protected void runMigrationOperation(Properties props, DatabaseOperationOption databaseOperationOption) throws IOException {
new UpOperation().operate(
new DataSourceConnectionProvider(dataSource),
new FileMigrationLoader(new ClassPathResource(SCRIPTS_FOLDER).getFile(), StandardCharsets.UTF_8.toString(),
props), databaseOperationOption, System.out);
}

}
47 changes: 47 additions & 0 deletions src/test/java/org/opensrp/migrations/MybatisMigrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.opensrp.migrations;

import org.apache.ibatis.migration.options.DatabaseOperationOption;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import java.io.IOException;
import java.util.Properties;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

@RunWith(MockitoJUnitRunner.class)
public class MybatisMigrationTest {

private MybatisMigration mybatisMigration;

@Before
public void setUp() {
mybatisMigration = Mockito.spy(new MybatisMigration());
}

@Test
public void testInitializeMybatisMigrationShouldInvokeRunMigrationOperation() throws IOException {
Mockito.doNothing().when(mybatisMigration).runMigrationOperation(Mockito.any(Properties.class), Mockito.any(
DatabaseOperationOption.class));

mybatisMigration.initializeMybatisMigration();

ArgumentCaptor<Properties> propertiesArgumentCaptor = ArgumentCaptor.forClass(Properties.class);
ArgumentCaptor<DatabaseOperationOption> databaseOperationOptionArgumentCaptor = ArgumentCaptor.forClass(
DatabaseOperationOption.class);

Mockito.verify(mybatisMigration).runMigrationOperation(propertiesArgumentCaptor.capture(),
databaseOperationOptionArgumentCaptor.capture());

assertNotNull(databaseOperationOptionArgumentCaptor.getValue());
assertNotNull(propertiesArgumentCaptor.getValue());

// Has to be set to false
assertFalse(databaseOperationOptionArgumentCaptor.getValue().isAutoCommit());
}
}
2 changes: 2 additions & 0 deletions src/test/resources/test-applicationContext-opensrp.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
<context:component-scan base-package="org.opensrp.config"/>
<context:component-scan base-package="org.opensrp.queue"/>
<context:component-scan base-package="org.opensrp.validator"/>
<context:component-scan base-package="org.opensrp.migrations"/>
<context:component-scan base-package="org.opensrp.service">

<!--These classes are excluded to enable the context load. This is because
EventsListener has EventsRouter as a dependency, problem is that IHandlerMapper
in EventsRouter is an interface that has its implementation in opensrp-register
Expand Down

0 comments on commit d186eff

Please sign in to comment.