This is an automated email from the ASF dual-hosted git repository. arnold pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract.git
commit e9df96e3878e111f749d4f51fef9091939eca532 Author: Arnold Galovics <[email protected]> AuthorDate: Mon Jun 13 11:42:23 2022 +0200 Readonly connection support --- build.gradle | 12 -- fineract-provider/build.gradle | 2 - .../AdHocScheduledJobRunnerServiceImpl.java | 2 +- .../service/DataSourcePerTenantServiceFactory.java | 33 +-- .../core/service/HikariDataSourceFactory.java | 31 +++ .../TomcatJdbcDataSourcePerTenantService.java | 2 +- .../tenant/parts/0014_remove_unused_jobs.xml | 5 - .../DataSourcePerTenantServiceFactoryTest.java | 233 +++++++++++++++++++++ .../TomcatJdbcDataSourcePerTenantServiceTest.java | 147 ------------- .../core/db/DatabaseConnectionProperties.java | 111 ---------- 10 files changed, 287 insertions(+), 291 deletions(-) diff --git a/build.gradle b/build.gradle index 3bba809a2..c654d88df 100644 --- a/build.gradle +++ b/build.gradle @@ -539,18 +539,6 @@ configure(project.fineractJavaProjects) { excludeTestsMatching project.property('excludeTests') } } - - // Database type used in the Test - systemProperty 'dbType', 'mariadb' - if (project.hasProperty('dbType')) { - if ('postgresql'.equalsIgnoreCase(dbType)) { - systemProperty 'dbType', 'postgresql' - } else if ('mysql'.equalsIgnoreCase(dbType)) { - systemProperty 'dbType', 'mysql' - } else { - throw new GradleException('Provided dbType is not supported') - } - } } testlogger { diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle index 544f6ef23..2172b7a32 100644 --- a/fineract-provider/build.gradle +++ b/fineract-provider/build.gradle @@ -223,7 +223,6 @@ bootRun { dependencies { implementation 'org.mariadb.jdbc:mariadb-java-client:2.7.5' implementation 'org.postgresql:postgresql:42.3.5' - implementation 'mysql:mysql-connector-java:8.0.29' } } @@ -289,7 +288,6 @@ jib { dependencies { implementation 'org.mariadb.jdbc:mariadb-java-client:2.7.5' implementation 'org.postgresql:postgresql:42.3.5' - implementation 'mysql:mysql-connector-java:8.0.29' } pluginExtensions { diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java index f2a81e238..e5f62bcc3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java @@ -82,7 +82,7 @@ public class AdHocScheduledJobRunnerServiceImpl implements AdHocScheduledJobRunn run = Math.toIntExact(ChronoUnit.YEARS.between(start, end)) >= 1; break; case CUSTOM: - next = start.plusDays((long) adhoc.getReportRunEvery()); + next = start.plusDays((int) (long) adhoc.getReportRunEvery()); run = Math.toIntExact(ChronoUnit.DAYS.between(start, end)) >= adhoc.getReportRunEvery(); break; default: diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DataSourcePerTenantServiceFactory.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DataSourcePerTenantServiceFactory.java index 676ec48a6..2380f7d52 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DataSourcePerTenantServiceFactory.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DataSourcePerTenantServiceFactory.java @@ -22,13 +22,12 @@ import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTen import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection.toProtocol; import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; import javax.sql.DataSource; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection; import org.apache.fineract.infrastructure.security.constants.TenantConstants; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -40,14 +39,24 @@ import org.springframework.stereotype.Component; */ @Component @Slf4j -@RequiredArgsConstructor public class DataSourcePerTenantServiceFactory { private final HikariConfig hikariConfig; private final FineractProperties fineractProperties; private final ApplicationContext context; + private final DataSource tenantDataSource; + private final HikariDataSourceFactory hikariDataSourceFactory; - public DataSource createNewDataSourceFor(final DataSource tenantDataSource, final FineractPlatformTenantConnection tenantConnection) { + public DataSourcePerTenantServiceFactory(@Qualifier("hikariTenantDataSource") DataSource tenantDataSource, HikariConfig hikariConfig, + FineractProperties fineractProperties, ApplicationContext context, HikariDataSourceFactory hikariDataSourceFactory) { + this.hikariConfig = hikariConfig; + this.fineractProperties = fineractProperties; + this.context = context; + this.tenantDataSource = tenantDataSource; + this.hikariDataSourceFactory = hikariDataSourceFactory; + } + + public DataSource createNewDataSourceFor(final FineractPlatformTenantConnection tenantConnection) { String protocol = toProtocol(tenantDataSource); // Default properties for Writing String schemaServer = tenantConnection.getSchemaServer(); @@ -57,7 +66,7 @@ public class DataSourcePerTenantServiceFactory { String schemaPassword = tenantConnection.getSchemaPassword(); String schemaConnectionParameters = tenantConnection.getSchemaConnectionParameters(); // Properties to ReadOnly case - if (this.fineractProperties.getMode().isReadOnlyMode()) { + if (fineractProperties.getMode().isReadOnlyMode()) { schemaServer = getPropertyValue(tenantConnection.getReadOnlySchemaServer(), TenantConstants.PROPERTY_RO_SCHEMA_SERVER_NAME, schemaServer); schemaPort = getPropertyValue(tenantConnection.getReadOnlySchemaServerPort(), TenantConstants.PROPERTY_RO_SCHEMA_SERVER_PORT, @@ -75,16 +84,16 @@ public class DataSourcePerTenantServiceFactory { log.debug("{}", jdbcUrl); HikariConfig config = new HikariConfig(); - config.setReadOnly(this.fineractProperties.getMode().isReadOnlyMode()); - config.setDriverClassName(hikariConfig.getDriverClassName()); - config.setPoolName(schemaName + "_pool"); + config.setReadOnly(fineractProperties.getMode().isReadOnlyMode()); config.setJdbcUrl(jdbcUrl); + config.setPoolName(schemaName + "_pool"); config.setUsername(schemaUsername); config.setPassword(schemaPassword); config.setMinimumIdle(tenantConnection.getInitialSize()); config.setMaximumPoolSize(tenantConnection.getMaxActive()); - config.setConnectionTestQuery(hikariConfig.getConnectionTestQuery()); config.setValidationTimeout(tenantConnection.getValidationInterval()); + config.setDriverClassName(hikariConfig.getDriverClassName()); + config.setConnectionTestQuery(hikariConfig.getConnectionTestQuery()); config.setAutoCommit(hikariConfig.isAutoCommit()); // https://github.com/brettwooldridge/HikariCP/wiki/MBean-(JMX)-Monitoring-and-Management @@ -96,7 +105,7 @@ public class DataSourcePerTenantServiceFactory { // for the all Tenants DB --> config.setDataSourceProperties(hikariConfig.getDataSourceProperties()); - return new HikariDataSource(config); + return hikariDataSourceFactory.create(config); } private String getPropertyValue(final String baseValue, final String propertyName, final String defaultValue) { @@ -104,10 +113,10 @@ public class DataSourcePerTenantServiceFactory { if (null != baseValue) { return baseValue; } - if (this.context == null) { + if (context == null) { return defaultValue; } - return this.context.getEnvironment().getProperty(propertyName, defaultValue); + return context.getEnvironment().getProperty(propertyName, defaultValue); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/HikariDataSourceFactory.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/HikariDataSourceFactory.java new file mode 100644 index 000000000..dc43d2541 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/HikariDataSourceFactory.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.core.service; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.stereotype.Component; + +@Component +public class HikariDataSourceFactory { + + public HikariDataSource create(HikariConfig config) { + return new HikariDataSource(config); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TomcatJdbcDataSourcePerTenantService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TomcatJdbcDataSourcePerTenantService.java index 26a708d2f..a16ef739d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TomcatJdbcDataSourcePerTenantService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TomcatJdbcDataSourcePerTenantService.java @@ -64,7 +64,7 @@ public class TomcatJdbcDataSourcePerTenantService implements RoutingDataSourceSe if (possibleDS != null) { tenantDataSource = possibleDS; } else { - tenantDataSource = dataSourcePerTenantServiceFactory.createNewDataSourceFor(this.tenantDataSource, tenantConnection); + tenantDataSource = dataSourcePerTenantServiceFactory.createNewDataSourceFor(tenantConnection); this.tenantToDataSourceMap.put(tenantConnection.getConnectionId(), tenantDataSource); } } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0014_remove_unused_jobs.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0014_remove_unused_jobs.xml index 0f7d536ee..8359f9d64 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0014_remove_unused_jobs.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0014_remove_unused_jobs.xml @@ -25,11 +25,6 @@ <dropForeignKeyConstraint baseTableName="job_run_history" constraintName="scheduledjobsFK"/> </changeSet> <changeSet author="fineract" id="1"> - <validCheckSum>8:18ed72e1958f7db9c1a0c983ac823ab3</validCheckSum> <!-- checksum withsout delete from history --> - <validCheckSum>8:b4a83f9764270372a384616acf066d7c</validCheckSum> <!-- checksum with delete from history --> - <sql> - DELETE FROM job_run_history WHERE job_id IN (SELECT id FROM job WHERE name IN ('Update loan Summary', 'Update Loan Paid In Advance')) - </sql> <delete tableName="job"> <where>name='Update loan Summary'</where> </delete> diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java new file mode 100644 index 000000000..036ccddfa --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java @@ -0,0 +1,233 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.core; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Properties; +import javax.sql.DataSource; +import org.apache.fineract.infrastructure.core.config.FineractProperties; +import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; +import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection; +import org.apache.fineract.infrastructure.core.service.DataSourcePerTenantServiceFactory; +import org.apache.fineract.infrastructure.core.service.HikariDataSourceFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +public class DataSourcePerTenantServiceFactoryTest { + + public static final String MASTER_DB_SERVER = "localhost"; + public static final String MASTER_DB_SERVER_PORT = "3306"; + public static final String MASTER_DB_SCHEMA_NAME = "fineract_tenants"; + public static final String MASTER_DB_USERNAME = "root"; + public static final String MASTER_DB_PASSWORD = "password"; + public static final String MASTER_DB_CONN_PARAMS = "something"; + public static final String MASTER_DB_JDBC_URL = "jdbc:mariadb://" + MASTER_DB_SERVER + ":" + MASTER_DB_SERVER_PORT + "/" + + MASTER_DB_SCHEMA_NAME + "?" + MASTER_DB_CONN_PARAMS; + + public static final String READONLY_DB_SERVER = "localhost-readonly"; + public static final String READONLY_DB_SERVER_PORT = "3306-readonly"; + public static final String READONLY_DB_SCHEMA_NAME = "fineract_tenants-readonly"; + public static final String READONLY_DB_USERNAME = "root-readonly"; + public static final String READONLY_DB_PASSWORD = "password-readonly"; + public static final String READONLY_DB_CONN_PARAMS = "something-readonly"; + public static final String READONLY_DB_JDBC_URL = "jdbc:mariadb://" + READONLY_DB_SERVER + ":" + READONLY_DB_SERVER_PORT + "/" + + READONLY_DB_SCHEMA_NAME + "?" + READONLY_DB_CONN_PARAMS; + + public static final int MASTER_DB_INITIAL_SIZE = 1; + public static final int MASTER_DB_MAX_ACTIVE = 5; + public static final long MASTER_DB_VALIDATION_INTERVAL = 500L; + public static final long MASTER_DB_INIT_FAIL_TIMEOUT = 0L; + + public static final String MASTER_DB_DRIVER_CLASS_NAME = "org.mariadb.jdbc.Driver"; + public static final String MASTER_DB_CONN_TEST_QUERY = "SELECT 1"; + public static final boolean MASTER_DB_AUTO_COMMIT_ENABLED = true; + + @Mock + private FineractProperties fineractProperties; + + @Mock + private HikariConfig tenantHikariConfig; + + @Mock + private FineractPlatformTenant defaultTenant; + + @Mock + private FineractPlatformTenantConnection tenantConnection; + + @Mock + private DataSource tenantDataSource; + + @Mock + private HikariDataSourceFactory hikariDataSourceFactory; + + @Captor + private ArgumentCaptor<HikariConfig> hikariConfigCaptor; + + @InjectMocks + private DataSourcePerTenantServiceFactory underTest; + + @BeforeEach + void setUp() throws SQLException { + Connection connection = mock(Connection.class); + given(tenantDataSource.getConnection()).willReturn(connection); + + DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class); + given(connection.getMetaData()).willReturn(databaseMetaData); + + given(databaseMetaData.getURL()).willReturn("jdbc:mariadb://localhost:3306/fineract_tenants"); + + given(tenantConnection.getSchemaServer()).willReturn(MASTER_DB_SERVER); + given(tenantConnection.getSchemaServerPort()).willReturn(MASTER_DB_SERVER_PORT); + given(tenantConnection.getSchemaName()).willReturn(MASTER_DB_SCHEMA_NAME); + given(tenantConnection.getSchemaUsername()).willReturn(MASTER_DB_USERNAME); + given(tenantConnection.getSchemaPassword()).willReturn(MASTER_DB_PASSWORD); + given(tenantConnection.getSchemaConnectionParameters()).willReturn(MASTER_DB_CONN_PARAMS); + + given(tenantConnection.getReadOnlySchemaServer()).willReturn(READONLY_DB_SERVER); + given(tenantConnection.getReadOnlySchemaServerPort()).willReturn(READONLY_DB_SERVER_PORT); + given(tenantConnection.getReadOnlySchemaName()).willReturn(READONLY_DB_SCHEMA_NAME); + given(tenantConnection.getReadOnlySchemaUsername()).willReturn(READONLY_DB_USERNAME); + given(tenantConnection.getReadOnlySchemaPassword()).willReturn(READONLY_DB_PASSWORD); + given(tenantConnection.getReadOnlySchemaConnectionParameters()).willReturn(READONLY_DB_CONN_PARAMS); + + given(defaultTenant.getConnection()).willReturn(tenantConnection); + given(tenantConnection.getInitialSize()).willReturn(MASTER_DB_INITIAL_SIZE); + given(tenantConnection.getMaxActive()).willReturn(MASTER_DB_MAX_ACTIVE); + given(tenantConnection.getValidationInterval()).willReturn(MASTER_DB_VALIDATION_INTERVAL); + + given(tenantHikariConfig.getInitializationFailTimeout()).willReturn(MASTER_DB_INIT_FAIL_TIMEOUT); + given(tenantHikariConfig.getDriverClassName()).willReturn(MASTER_DB_DRIVER_CLASS_NAME); + given(tenantHikariConfig.getConnectionTestQuery()).willReturn(MASTER_DB_CONN_TEST_QUERY); + given(tenantHikariConfig.getDataSourceProperties()).willReturn(mock(Properties.class)); + given(tenantHikariConfig.isAutoCommit()).willReturn(MASTER_DB_AUTO_COMMIT_ENABLED); + + given(hikariDataSourceFactory.create(any())).willReturn(mock(HikariDataSource.class)); + } + + @Test + void testCreateNewDataSourceFor_ShouldUseNormalConfiguration_WhenInAllMode() { + // given + FineractProperties.FineractModeProperties modeProperties = createModeProps(MASTER_DB_AUTO_COMMIT_ENABLED, + MASTER_DB_AUTO_COMMIT_ENABLED, MASTER_DB_AUTO_COMMIT_ENABLED); + given(fineractProperties.getMode()).willReturn(modeProperties); + + // when + DataSource dataSource = underTest.createNewDataSourceFor(defaultTenant.getConnection()); + + // then + assertNotNull(dataSource); + verify(hikariDataSourceFactory).create(hikariConfigCaptor.capture()); + HikariConfig hikariConfig = hikariConfigCaptor.getValue(); + assertFalse(hikariConfig.isReadOnly()); + assertEquals(MASTER_DB_JDBC_URL, hikariConfig.getJdbcUrl()); + assertEquals(MASTER_DB_SCHEMA_NAME + "_pool", hikariConfig.getPoolName()); + assertEquals(MASTER_DB_USERNAME, hikariConfig.getUsername()); + assertEquals(MASTER_DB_PASSWORD, hikariConfig.getPassword()); + assertEquals(MASTER_DB_INITIAL_SIZE, hikariConfig.getMinimumIdle()); + assertEquals(MASTER_DB_MAX_ACTIVE, hikariConfig.getMaximumPoolSize()); + assertEquals(MASTER_DB_VALIDATION_INTERVAL, hikariConfig.getValidationTimeout()); + assertEquals(MASTER_DB_DRIVER_CLASS_NAME, hikariConfig.getDriverClassName()); + assertEquals(MASTER_DB_CONN_TEST_QUERY, hikariConfig.getConnectionTestQuery()); + assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, hikariConfig.isAutoCommit()); + } + + @Test + void testCreateNewDataSourceFor_ShouldUseReadOnlyConfiguration_WhenInReadOnlyMode() { + // given + FineractProperties.FineractModeProperties modeProperties = createModeProps(true, false, false); + given(fineractProperties.getMode()).willReturn(modeProperties); + + // when + DataSource dataSource = underTest.createNewDataSourceFor(defaultTenant.getConnection()); + + // then + assertNotNull(dataSource); + verify(hikariDataSourceFactory).create(hikariConfigCaptor.capture()); + HikariConfig hikariConfig = hikariConfigCaptor.getValue(); + assertTrue(hikariConfig.isReadOnly()); + assertEquals(READONLY_DB_JDBC_URL, hikariConfig.getJdbcUrl()); + assertEquals(READONLY_DB_SCHEMA_NAME + "_pool", hikariConfig.getPoolName()); + assertEquals(READONLY_DB_USERNAME, hikariConfig.getUsername()); + assertEquals(READONLY_DB_PASSWORD, hikariConfig.getPassword()); + assertEquals(MASTER_DB_INITIAL_SIZE, hikariConfig.getMinimumIdle()); + assertEquals(MASTER_DB_MAX_ACTIVE, hikariConfig.getMaximumPoolSize()); + assertEquals(MASTER_DB_VALIDATION_INTERVAL, hikariConfig.getValidationTimeout()); + assertEquals(MASTER_DB_DRIVER_CLASS_NAME, hikariConfig.getDriverClassName()); + assertEquals(MASTER_DB_CONN_TEST_QUERY, hikariConfig.getConnectionTestQuery()); + assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, hikariConfig.isAutoCommit()); + } + + @Test + void testCreateNewDataSourceFor_ShouldUseNormalConfiguration_WhenInBatchOnlyMode() { + // given + FineractProperties.FineractModeProperties modeProperties = createModeProps(false, false, true); + given(fineractProperties.getMode()).willReturn(modeProperties); + + // when + DataSource dataSource = underTest.createNewDataSourceFor(defaultTenant.getConnection()); + + // then + assertNotNull(dataSource); + verify(hikariDataSourceFactory).create(hikariConfigCaptor.capture()); + HikariConfig hikariConfig = hikariConfigCaptor.getValue(); + assertFalse(hikariConfig.isReadOnly()); + assertEquals(MASTER_DB_JDBC_URL, hikariConfig.getJdbcUrl()); + assertEquals(MASTER_DB_SCHEMA_NAME + "_pool", hikariConfig.getPoolName()); + assertEquals(MASTER_DB_USERNAME, hikariConfig.getUsername()); + assertEquals(MASTER_DB_PASSWORD, hikariConfig.getPassword()); + assertEquals(MASTER_DB_INITIAL_SIZE, hikariConfig.getMinimumIdle()); + assertEquals(MASTER_DB_MAX_ACTIVE, hikariConfig.getMaximumPoolSize()); + assertEquals(MASTER_DB_VALIDATION_INTERVAL, hikariConfig.getValidationTimeout()); + assertEquals(MASTER_DB_DRIVER_CLASS_NAME, hikariConfig.getDriverClassName()); + assertEquals(MASTER_DB_CONN_TEST_QUERY, hikariConfig.getConnectionTestQuery()); + assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, hikariConfig.isAutoCommit()); + } + + private FineractProperties.FineractModeProperties createModeProps(boolean readEnabled, boolean writeEnabled, boolean batchEnabled) { + FineractProperties.FineractModeProperties modeProperties = new FineractProperties.FineractModeProperties(); + modeProperties.setReadEnabled(readEnabled); + modeProperties.setWriteEnabled(writeEnabled); + modeProperties.setBatchEnabled(batchEnabled); + return modeProperties; + } + +} diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/TomcatJdbcDataSourcePerTenantServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/TomcatJdbcDataSourcePerTenantServiceTest.java deleted file mode 100644 index 7257301fa..000000000 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/TomcatJdbcDataSourcePerTenantServiceTest.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.infrastructure.core; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.SQLException; -import java.util.Properties; -import javax.sql.DataSource; -import org.apache.fineract.infrastructure.core.config.FineractProperties; -import org.apache.fineract.infrastructure.core.db.DatabaseConnectionProperties; -import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; -import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection; -import org.apache.fineract.infrastructure.core.service.DataSourcePerTenantServiceFactory; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; -import org.springframework.test.context.TestPropertySource; - -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) -@TestPropertySource("classpath:application-test.properties") -public class TomcatJdbcDataSourcePerTenantServiceTest { - - @Mock - private FineractProperties fineractProperties; - - @Mock - private HikariConfig hikariConfig; - - @Mock - private Connection connection; - - @Mock - private FineractPlatformTenant defaultTenant; - - @Mock - private FineractPlatformTenantConnection tenantConnection; - - @InjectMocks - private DataSourcePerTenantServiceFactory underTest; - - private DataSource dataSource; - private DataSource tenantDataSource; - private DatabaseConnectionProperties databaseConnectionProperties; - - @BeforeEach - void setUp() throws SQLException { - this.databaseConnectionProperties = DatabaseConnectionProperties.instance(System.getProperty("dbType")); - - tenantDataSource = mock(HikariDataSource.class); - given(tenantDataSource.getConnection()).willReturn(connection); - given(connection.getMetaData()).willReturn(mock(DatabaseMetaData.class)); - given(connection.getMetaData().getURL()).willReturn(databaseConnectionProperties.getJdbcUrl()); - - given(tenantConnection.getSchemaServer()).willReturn(databaseConnectionProperties.getSchemaServer()); - given(tenantConnection.getSchemaServerPort()).willReturn(databaseConnectionProperties.getSchemaPort()); - given(tenantConnection.getSchemaUsername()).willReturn(databaseConnectionProperties.getSchemaUsername()); - given(tenantConnection.getSchemaPassword()).willReturn(databaseConnectionProperties.getSchemaPassword()); - given(tenantConnection.getSchemaName()).willReturn(databaseConnectionProperties.getSchemaName()); - - given(defaultTenant.getConnection()).willReturn(tenantConnection); - given(defaultTenant.getConnection().getMaxActive()).willReturn(5); - given(defaultTenant.getConnection().getValidationInterval()).willReturn(500L); - - given(hikariConfig.getInitializationFailTimeout()).willReturn(0L); - given(hikariConfig.getDriverClassName()).willReturn(databaseConnectionProperties.getDriverClassName()); - given(hikariConfig.getConnectionTestQuery()).willReturn(databaseConnectionProperties.getConnectionTestQuery()); - given(hikariConfig.getDataSourceProperties()).willReturn(mock(Properties.class)); - given(hikariConfig.isAutoCommit()).willReturn(true); - } - - @Test - void testRetrieveDataSource_ShouldCreateDataSource_WhenFineractIsInAllMode() { - // given - FineractProperties.FineractModeProperties modeProperties = createModeProps(true, true, true); - given(fineractProperties.getMode()).willReturn(modeProperties); - - // when - dataSource = underTest.createNewDataSourceFor(tenantDataSource, defaultTenant.getConnection()); - - // then - assertNotNull(dataSource); - } - - @Test - void testRetrieveDataSource_ShouldCreateDataSource_WhenFineractIsInReadOnlyMode() { - // given - FineractProperties.FineractModeProperties modeProperties = createModeProps(true, false, false); - given(fineractProperties.getMode()).willReturn(modeProperties); - - // when - dataSource = underTest.createNewDataSourceFor(tenantDataSource, defaultTenant.getConnection()); - - // then - assertNotNull(dataSource); - } - - @Test - void testRetrieveDataSource_ShouldCreateDataSource_WhenFineractIsInBatchMode() { - // given - FineractProperties.FineractModeProperties modeProperties = createModeProps(false, false, true); - given(fineractProperties.getMode()).willReturn(modeProperties); - - // when - dataSource = underTest.createNewDataSourceFor(tenantDataSource, defaultTenant.getConnection()); - - // then - assertNotNull(dataSource); - } - - private FineractProperties.FineractModeProperties createModeProps(boolean readEnabled, boolean writeEnabled, boolean batchEnabled) { - FineractProperties.FineractModeProperties modeProperties = new FineractProperties.FineractModeProperties(); - modeProperties.setReadEnabled(readEnabled); - modeProperties.setWriteEnabled(writeEnabled); - modeProperties.setBatchEnabled(batchEnabled); - return modeProperties; - } - -} diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/db/DatabaseConnectionProperties.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/db/DatabaseConnectionProperties.java deleted file mode 100644 index d962239ef..000000000 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/db/DatabaseConnectionProperties.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.fineract.infrastructure.core.db; - -public class DatabaseConnectionProperties { - - private String driverClassName; - private String jdbcUrl; - private String connectionTestQuery; - - private String schemaServer; - private String schemaName; - private String schemaPort; - private String schemaUsername; - private String schemaPassword; - - protected DatabaseConnectionProperties(final String driverClassName, final String jdbcUrl, final String schemaPort, - final String schemaPassword) { - this.driverClassName = driverClassName; - this.jdbcUrl = jdbcUrl; - this.schemaPort = schemaPort; - this.schemaPassword = schemaPassword; - - this.schemaServer = "localhost"; - this.schemaUsername = "root"; - this.schemaName = "fineract_tenants"; - this.connectionTestQuery = "SELECT 1"; - } - - public static DatabaseConnectionProperties instance(final String dbType) { - return new DatabaseConnectionProperties(getDbDriverClassName(dbType), buildJdbcUrl(dbType), getDbPort(dbType), - getDbPassword(dbType)); - } - - private static String getDbDriverClassName(final String dbType) { - if (dbType.equals("mariadb")) { - return "org.mariadb.jdbc.Driver"; - } else if (dbType.equals("mysql")) { - return "com.mysql.cj.jdbc.Driver"; - } else { - return "org.postgresql.Driver"; - } - } - - private static String buildJdbcUrl(final String dbType) { - return "jdbc:" + dbType + "://localhost:" + getDbPort(dbType) + "/fineract_tenants"; - } - - private static String getDbPort(final String dbType) { - if (dbType.equals("postgresql")) { - return "5432"; - } - return "3306"; - } - - private static String getDbPassword(final String dbType) { - if (dbType.equals("postgresql")) { - return "postgres"; - } - return "mysql"; - } - - public String getDriverClassName() { - return driverClassName; - } - - public String getJdbcUrl() { - return jdbcUrl; - } - - public String getConnectionTestQuery() { - return connectionTestQuery; - } - - public String getSchemaServer() { - return schemaServer; - } - - public String getSchemaName() { - return schemaName; - } - - public String getSchemaPort() { - return schemaPort; - } - - public String getSchemaUsername() { - return schemaUsername; - } - - public String getSchemaPassword() { - return schemaPassword; - } -}
