FINERACT-1724: Ability to run Fineract in Liquibase only mode for scaled environments

This commit is contained in:
Arnold Galovics
2023-02-17 16:31:16 +01:00
committed by Arnold Gálovics
parent f927dd4ff9
commit 6c86e15eb7
45 changed files with 288 additions and 71 deletions
@@ -22,8 +22,8 @@ import static org.mockito.Mockito.mock;
import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.group.domain.GroupRepository; import org.apache.fineract.portfolio.group.domain.GroupRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
@@ -21,8 +21,8 @@ package com.acme.fineract.portfolio.note.starter;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.group.domain.GroupRepository; import org.apache.fineract.portfolio.group.domain.GroupRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
@@ -48,4 +48,9 @@
|FINERACT_DEFAULT_TENANTDB_DESCRIPTION |FINERACT_DEFAULT_TENANTDB_DESCRIPTION
|Default Demo Tenant |Default Demo Tenant
|TBD |TBD
|spring.liquibase.enabled
|FINERACT_LIQUIBASE_ENABLED
|true
|TBD
|=== |===
@@ -1,3 +1,11 @@
= Kubernetes = Kubernetes
TBD In a scaled Kubernetes environment where multiple Fineract instances are deployed, doing the database migrations properly is essential.
Fineract provides a way to run only the Liquibase migrations instead of starting up the whole application server so that you can easily do the migrations before actually upgrading a Fineract instance.
The `FINERACT_LIQUIBASE_ENABLED` flag controls whether Liquibase is enabled or not. For regular read/write/batch manager/batch worker instances this should be disabled.
There's a special Spring profile that should be enabled for running Liquibase only. In can be done via `SPRING_PROFILES_ACTIVE` environment variable. The profile name is `liquibase-only`. At the end of the migration process, the application will exit.
For the instance running the Liquibase migrations, the profile should be activated.
@@ -19,10 +19,12 @@
package org.apache.fineract; package org.apache.fineract;
import java.io.IOException; import java.io.IOException;
import org.apache.fineract.infrastructure.core.boot.AbstractApplicationConfiguration; import org.apache.fineract.infrastructure.core.boot.FineractLiquibaseOnlyApplicationConfiguration;
import org.apache.fineract.infrastructure.core.boot.FineractWebApplicationConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Import;
/** /**
* Fineract main() application which launches Fineract in an embedded Tomcat HTTP (using Spring Boot). * Fineract main() application which launches Fineract in an embedded Tomcat HTTP (using Spring Boot).
@@ -39,11 +41,12 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
public class ServerApplication extends SpringBootServletInitializer { public class ServerApplication extends SpringBootServletInitializer {
private static class Configuration extends AbstractApplicationConfiguration {} @Import({ FineractWebApplicationConfiguration.class, FineractLiquibaseOnlyApplicationConfiguration.class })
private static class Configuration {}
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Configuration.class); return configureApplication(builder);
} }
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) { private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
@@ -52,6 +55,5 @@ public class ServerApplication extends SpringBootServletInitializer {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
configureApplication(new SpringApplicationBuilder(ServerApplication.class)).run(args); configureApplication(new SpringApplicationBuilder(ServerApplication.class)).run(args);
// ApplicationExitUtil.waitForKeyPressToCleanlyExit(ctx);
} }
} }
@@ -19,7 +19,7 @@
package org.apache.fineract.accounting.glaccount.jobs.updatetrialbalancedetails; package org.apache.fineract.accounting.glaccount.jobs.updatetrialbalancedetails;
import org.apache.fineract.accounting.glaccount.domain.TrialBalanceRepositoryWrapper; import org.apache.fineract.accounting.glaccount.domain.TrialBalanceRepositoryWrapper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.jobs.service.JobName; import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.springframework.batch.core.Job; import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step; import org.springframework.batch.core.Step;
@@ -27,8 +27,8 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.glaccount.domain.TrialBalance; import org.apache.fineract.accounting.glaccount.domain.TrialBalance;
import org.apache.fineract.accounting.glaccount.domain.TrialBalanceRepositoryWrapper; import org.apache.fineract.accounting.glaccount.domain.TrialBalanceRepositoryWrapper;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -33,10 +33,10 @@ import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException; import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.documentmanagement.command.DocumentCommand; import org.apache.fineract.infrastructure.documentmanagement.command.DocumentCommand;
import org.apache.fineract.infrastructure.documentmanagement.domain.Document; import org.apache.fineract.infrastructure.documentmanagement.domain.Document;
import org.apache.fineract.infrastructure.documentmanagement.service.DocumentWritePlatformService; import org.apache.fineract.infrastructure.documentmanagement.service.DocumentWritePlatformService;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -0,0 +1,45 @@
/**
* 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.boot;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.condition.FineractLiquibaseOnlyApplicationCondition;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.config.HikariCpConfig;
import org.apache.fineract.infrastructure.core.config.JdbcConfig;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Import;
@Conditional(FineractLiquibaseOnlyApplicationCondition.class)
@Slf4j
@EnableConfigurationProperties({ FineractProperties.class, LiquibaseProperties.class })
@Import({ HikariCpConfig.class, JdbcConfig.class })
@ComponentScan(basePackages = { "org.apache.fineract.infrastructure.core.service.migration",
"org.apache.fineract.infrastructure.core.service.database", "org.apache.fineract.infrastructure.core.service.tenant" })
public class FineractLiquibaseOnlyApplicationConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
log.warn("Fineract is running in Liquibase only mode");
}
}
@@ -0,0 +1,26 @@
/**
* 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.boot;
public final class FineractProfiles {
public static final String LIQUIBASE_ONLY = "liquibase-only";
private FineractProfiles() {}
}
@@ -18,7 +18,10 @@
*/ */
package org.apache.fineract.infrastructure.core.boot; package org.apache.fineract.infrastructure.core.boot;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.condition.FineractWebApplicationCondition;
import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@@ -29,6 +32,7 @@ import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -47,6 +51,13 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableConfigurationProperties({ FineractProperties.class, LiquibaseProperties.class }) @EnableConfigurationProperties({ FineractProperties.class, LiquibaseProperties.class })
@ComponentScan(basePackages = "org.apache.fineract.**") @ComponentScan(basePackages = "org.apache.fineract.**")
@IntegrationComponentScan(basePackages = "org.apache.fineract.**") @IntegrationComponentScan(basePackages = "org.apache.fineract.**")
public abstract class AbstractApplicationConfiguration { @Conditional(FineractWebApplicationCondition.class)
@Slf4j
// The class needs to be abstract for some reason, otherwise the tests start to fail...
public abstract class FineractWebApplicationConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
log.warn("Fineract is running in web application mode");
}
} }
@@ -0,0 +1,30 @@
/**
* 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.condition;
import java.util.List;
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
public class FineractLiquibaseOnlyApplicationCondition extends ProfileCondition {
@Override
protected boolean matches(List<String> activeProfiles) {
return activeProfiles.contains(FineractProfiles.LIQUIBASE_ONLY);
}
}
@@ -0,0 +1,30 @@
/**
* 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.condition;
import java.util.List;
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
public class FineractWebApplicationCondition extends ProfileCondition {
@Override
protected boolean matches(List<String> activeProfiles) {
return !activeProfiles.contains(FineractProfiles.LIQUIBASE_ONLY);
}
}
@@ -0,0 +1,36 @@
/**
* 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.condition;
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public abstract class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String[] activeProfiles = context.getEnvironment().getActiveProfiles();
return matches(Arrays.asList(activeProfiles));
}
protected abstract boolean matches(List<String> activeProfiles);
}
@@ -21,7 +21,6 @@ package org.apache.fineract.infrastructure.core.config;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -41,7 +40,7 @@ public class HikariCpConfig {
} }
@Bean(destroyMethod = "close") @Bean(destroyMethod = "close")
public DataSource hikariTenantDataSource(HikariConfig hikariConfig) { public HikariDataSource hikariTenantDataSource(HikariConfig hikariConfig) {
return new HikariDataSource(hikariConfig); return new HikariDataSource(hikariConfig);
} }
} }
@@ -18,7 +18,7 @@
*/ */
package org.apache.fineract.infrastructure.core.config; package org.apache.fineract.infrastructure.core.config;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
@@ -27,8 +27,8 @@ import java.util.Set;
import org.apache.fineract.infrastructure.core.auditing.JpaAuditingHandlerRegistrar; import org.apache.fineract.infrastructure.core.auditing.JpaAuditingHandlerRegistrar;
import org.apache.fineract.infrastructure.core.domain.AuditorAwareImpl; import org.apache.fineract.infrastructure.core.domain.AuditorAwareImpl;
import org.apache.fineract.infrastructure.core.persistence.DatabaseSelectingPersistenceUnitPostProcessor; import org.apache.fineract.infrastructure.core.persistence.DatabaseSelectingPersistenceUnitPostProcessor;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver; import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.eclipse.persistence.config.PersistenceUnitProperties; import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer; import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer;
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.core.service; package org.apache.fineract.infrastructure.core.service.database;
import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection.toJdbcUrl; import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection.toJdbcUrl;
import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection.toProtocol; import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection.toProtocol;
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.core.service; package org.apache.fineract.infrastructure.core.service.database;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.core.service; package org.apache.fineract.infrastructure.core.service.database;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.core.service; package org.apache.fineract.infrastructure.core.service.database;
import javax.sql.DataSource; import javax.sql.DataSource;
@@ -16,8 +16,9 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.core.service; package org.apache.fineract.infrastructure.core.service.database;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.core.service; package org.apache.fineract.infrastructure.core.service.database;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -22,7 +22,6 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import javax.sql.DataSource; import javax.sql.DataSource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService; import org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@@ -42,8 +41,6 @@ public class TenantDatabaseStateVerifier {
private final LiquibaseProperties liquibaseProperties; private final LiquibaseProperties liquibaseProperties;
private final DatabaseIndependentQueryService dbQueryService; private final DatabaseIndependentQueryService dbQueryService;
private final FineractProperties fineractProperties;
public boolean isFirstLiquibaseMigration(DataSource dataSource) { public boolean isFirstLiquibaseMigration(DataSource dataSource) {
boolean databaseChangelogTableExists = dbQueryService.isTablePresent(dataSource, "DATABASECHANGELOG"); boolean databaseChangelogTableExists = dbQueryService.isTablePresent(dataSource, "DATABASECHANGELOG");
return !databaseChangelogTableExists; return !databaseChangelogTableExists;
@@ -20,18 +20,21 @@ package org.apache.fineract.infrastructure.core.service.migration;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import javax.sql.DataSource; import javax.sql.DataSource;
import liquibase.exception.LiquibaseException; import liquibase.exception.LiquibaseException;
import liquibase.integration.spring.SpringLiquibase; import liquibase.integration.spring.SpringLiquibase;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService; import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
@@ -39,6 +42,7 @@ import org.springframework.stereotype.Service;
*/ */
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor
public class TenantDatabaseUpgradeService implements InitializingBean { public class TenantDatabaseUpgradeService implements InitializingBean {
private static final String TENANT_STORE_DB_CONTEXT = "tenant_store_db"; private static final String TENANT_STORE_DB_CONTEXT = "tenant_store_db";
@@ -47,33 +51,24 @@ public class TenantDatabaseUpgradeService implements InitializingBean {
private static final String CUSTOM_CHANGELOG_CONTEXT = "custom_changelog"; private static final String CUSTOM_CHANGELOG_CONTEXT = "custom_changelog";
private final TenantDetailsService tenantDetailsService; private final TenantDetailsService tenantDetailsService;
@Qualifier("hikariTenantDataSource")
private final DataSource tenantDataSource; private final DataSource tenantDataSource;
private final FineractProperties fineractProperties; private final FineractProperties fineractProperties;
private final TenantDatabaseStateVerifier databaseStateVerifier; private final TenantDatabaseStateVerifier databaseStateVerifier;
private final ExtendedSpringLiquibaseFactory liquibaseFactory; private final ExtendedSpringLiquibaseFactory liquibaseFactory;
private final TenantDataSourceFactory tenantDataSourceFactory; private final TenantDataSourceFactory tenantDataSourceFactory;
private final Environment environment;
@Autowired
public TenantDatabaseUpgradeService(final TenantDetailsService detailsService,
@Qualifier("hikariTenantDataSource") final DataSource tenantDataSource, final FineractProperties fineractProperties,
TenantDatabaseStateVerifier databaseStateVerifier, ExtendedSpringLiquibaseFactory liquibaseFactory,
TenantDataSourceFactory tenantDataSourceFactory) {
this.tenantDetailsService = detailsService;
this.tenantDataSource = tenantDataSource;
this.fineractProperties = fineractProperties;
this.databaseStateVerifier = databaseStateVerifier;
this.liquibaseFactory = liquibaseFactory;
this.tenantDataSourceFactory = tenantDataSourceFactory;
}
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
if (databaseStateVerifier.isLiquibaseDisabled() || !fineractProperties.getMode().isWriteEnabled()) { if (notLiquibaseOnlyMode()) {
log.warn("Liquibase is disabled. Not upgrading any database."); if (databaseStateVerifier.isLiquibaseDisabled() || !fineractProperties.getMode().isWriteEnabled()) {
if (!fineractProperties.getMode().isWriteEnabled()) { log.warn("Liquibase is disabled. Not upgrading any database.");
log.warn("Liquibase is disabled because the current instance is configured as a non-write Fineract instance"); if (!fineractProperties.getMode().isWriteEnabled()) {
log.warn("Liquibase is disabled because the current instance is configured as a non-write Fineract instance");
}
return;
} }
return;
} }
try { try {
upgradeTenantStore(); upgradeTenantStore();
@@ -83,6 +78,11 @@ public class TenantDatabaseUpgradeService implements InitializingBean {
} }
} }
private boolean notLiquibaseOnlyMode() {
List<String> activeProfiles = Arrays.asList(environment.getActiveProfiles());
return !activeProfiles.contains(FineractProfiles.LIQUIBASE_ONLY);
}
private void upgradeTenantStore() throws LiquibaseException { private void upgradeTenantStore() throws LiquibaseException {
log.warn("Upgrading tenant store DB at {}:{}", fineractProperties.getTenant().getHost(), fineractProperties.getTenant().getPort()); log.warn("Upgrading tenant store DB at {}:{}", fineractProperties.getTenant().getHost(), fineractProperties.getTenant().getPort());
logTenantStoreDetails(); logTenantStoreDetails();
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.security.service; package org.apache.fineract.infrastructure.core.service.tenant;
import java.util.List; import java.util.List;
import javax.sql.DataSource; import javax.sql.DataSource;
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.security.service; package org.apache.fineract.infrastructure.core.service.tenant;
import java.util.List; import java.util.List;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
@@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.security.service; package org.apache.fineract.infrastructure.core.service.tenant;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@@ -44,7 +44,7 @@ public final class TenantMapper implements RowMapper<FineractPlatformTenant> {
+ " from tenants t left join tenant_server_connections ts "; + " from tenants t left join tenant_server_connections ts ";
private final StringBuilder sqlBuilder = new StringBuilder(TENANT_SERVER_CONNECTION_BUILDER); private final StringBuilder sqlBuilder = new StringBuilder(TENANT_SERVER_CONNECTION_BUILDER);
TenantMapper(boolean isReport) { public TenantMapper(boolean isReport) {
this.isReport = isReport; this.isReport = isReport;
} }
@@ -28,9 +28,9 @@ import java.util.List;
import javax.sql.DataSource; import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService; import org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService;
import org.apache.fineract.infrastructure.core.service.database.IndexDetail; import org.apache.fineract.infrastructure.core.service.database.IndexDetail;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData; import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData; import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnValueData; import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnValueData;
@@ -29,11 +29,11 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
import org.apache.fineract.infrastructure.event.external.exception.ExternalEventConfigurationNotFoundException; import org.apache.fineract.infrastructure.event.external.exception.ExternalEventConfigurationNotFoundException;
import org.apache.fineract.infrastructure.event.external.service.validation.ExternalEventSourceService; import org.apache.fineract.infrastructure.event.external.service.validation.ExternalEventSourceService;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -19,7 +19,7 @@
package org.apache.fineract.infrastructure.jobs; package org.apache.fineract.infrastructure.jobs;
import org.apache.fineract.infrastructure.core.persistence.ExtendedJpaTransactionManager; import org.apache.fineract.infrastructure.core.persistence.ExtendedJpaTransactionManager;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer; import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
@@ -29,9 +29,9 @@ import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.ActionContext; import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.jobs.domain.ScheduledJobDetail; import org.apache.fineract.infrastructure.jobs.domain.ScheduledJobDetail;
import org.apache.fineract.infrastructure.jobs.domain.SchedulerDetail; import org.apache.fineract.infrastructure.jobs.domain.SchedulerDetail;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -27,7 +27,7 @@ import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadP
import org.apache.fineract.infrastructure.core.domain.ActionContext; import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService; import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobKey; import org.quartz.JobKey;
import org.quartz.Trigger; import org.quartz.Trigger;
@@ -27,10 +27,10 @@ import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadP
import org.apache.fineract.infrastructure.core.domain.ActionContext; import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.event.external.service.JdbcTemplateFactory; import org.apache.fineract.infrastructure.event.external.service.JdbcTemplateFactory;
import org.apache.fineract.infrastructure.jobs.domain.JobExecutionRepository; import org.apache.fineract.infrastructure.jobs.domain.JobExecutionRepository;
import org.apache.fineract.infrastructure.jobs.service.jobname.JobNameProvider; import org.apache.fineract.infrastructure.jobs.service.jobname.JobNameProvider;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService;
import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
@@ -18,9 +18,9 @@
*/ */
package org.apache.fineract.infrastructure.jobs.service.updatenpa; package org.apache.fineract.infrastructure.jobs.service.updatenpa;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver; import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.jobs.service.JobName; import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.batch.core.Job; import org.springframework.batch.core.Job;
@@ -21,10 +21,10 @@ package org.apache.fineract.infrastructure.jobs.service.updatenpa;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver; import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.useradministration.domain.AppUser; import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepContribution;
@@ -20,6 +20,7 @@ package org.apache.fineract.infrastructure.security.service;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.tenant.TenantMapper;
import org.apache.fineract.infrastructure.security.exception.InvalidTenantIdentifierException; import org.apache.fineract.infrastructure.security.exception.InvalidTenantIdentifierException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@@ -18,7 +18,7 @@
*/ */
package org.apache.fineract.portfolio.savings.jobs.generaterdschedule; package org.apache.fineract.portfolio.savings.jobs.generaterdschedule;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.infrastructure.jobs.service.JobName; import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService; import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService;
import org.springframework.batch.core.Job; import org.springframework.batch.core.Job;
@@ -26,7 +26,7 @@ import java.util.Map;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
import org.apache.fineract.portfolio.savings.DepositAccountUtils; import org.apache.fineract.portfolio.savings.DepositAccountUtils;
import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService; import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService;
import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepContribution;
@@ -0,0 +1,20 @@
#
# 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.
#
spring.main.web-application-type=none
@@ -159,7 +159,7 @@ spring.datasource.hikari.dataSourceProperties['dumpQueriesOnException']=${FINERA
spring.jpa.open-in-view=false spring.jpa.open-in-view=false
# Liquibase configuration # Liquibase configuration
spring.liquibase.enabled=true spring.liquibase.enabled=${FINERACT_LIQUIBASE_ENABLED:true}
spring.liquibase.changeLog=classpath:/db/changelog/db.changelog-master.xml spring.liquibase.changeLog=classpath:/db/changelog/db.changelog-master.xml
spring.liquibase.parameters.fineract.tenant.identifier=${fineract.tenant.identifier} spring.liquibase.parameters.fineract.tenant.identifier=${fineract.tenant.identifier}
@@ -30,9 +30,9 @@ import org.apache.fineract.infrastructure.core.service.migration.ExtendedSpringL
import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory; import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier; import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseUpgradeService; import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseUpgradeService;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.jobs.ScheduledJobRunnerConfig; import org.apache.fineract.infrastructure.jobs.ScheduledJobRunnerConfig;
import org.apache.fineract.infrastructure.jobs.service.JobRegisterService; import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@@ -59,6 +59,7 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -138,8 +139,8 @@ public class TestConfiguration {
@Bean @Bean
public TenantDatabaseStateVerifier tenantDatabaseStateVerifier(DatabaseIndependentQueryService databaseIndependentQueryService, public TenantDatabaseStateVerifier tenantDatabaseStateVerifier(DatabaseIndependentQueryService databaseIndependentQueryService,
LiquibaseProperties liquibaseProperties, FineractProperties fineractProperties) { LiquibaseProperties liquibaseProperties) {
return new TenantDatabaseStateVerifier(liquibaseProperties, databaseIndependentQueryService, fineractProperties); return new TenantDatabaseStateVerifier(liquibaseProperties, databaseIndependentQueryService);
} }
/** /**
@@ -150,9 +151,9 @@ public class TestConfiguration {
public TenantDatabaseUpgradeService tenantDatabaseUpgradeService(TenantDetailsService tenantDetailsService, public TenantDatabaseUpgradeService tenantDatabaseUpgradeService(TenantDetailsService tenantDetailsService,
HikariDataSource tenantDataSource, TenantDatabaseStateVerifier tenantDatabaseStateVerifier, HikariDataSource tenantDataSource, TenantDatabaseStateVerifier tenantDatabaseStateVerifier,
ExtendedSpringLiquibaseFactory liquibaseFactory, TenantDataSourceFactory tenantDataSourceFactory, ExtendedSpringLiquibaseFactory liquibaseFactory, TenantDataSourceFactory tenantDataSourceFactory,
FineractProperties fineractProperties) { FineractProperties fineractProperties, Environment environment) {
return new TenantDatabaseUpgradeService(tenantDetailsService, tenantDataSource, fineractProperties, tenantDatabaseStateVerifier, return new TenantDatabaseUpgradeService(tenantDetailsService, tenantDataSource, fineractProperties, tenantDatabaseStateVerifier,
liquibaseFactory, tenantDataSourceFactory); liquibaseFactory, tenantDataSourceFactory, environment);
} }
/** /**
@@ -37,8 +37,8 @@ import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection;
import org.apache.fineract.infrastructure.core.service.DataSourcePerTenantServiceFactory; import org.apache.fineract.infrastructure.core.service.database.DataSourcePerTenantServiceFactory;
import org.apache.fineract.infrastructure.core.service.HikariDataSourceFactory; import org.apache.fineract.infrastructure.core.service.database.HikariDataSourceFactory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -39,8 +39,10 @@ import org.apache.fineract.infrastructure.core.service.migration.SchemaUpgradeNe
import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory; import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier; import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseUpgradeService; import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseUpgradeService;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService; import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.mock.env.MockEnvironment;
public class LiquibaseStepDefinitions implements En { public class LiquibaseStepDefinitions implements En {
@@ -61,6 +63,7 @@ public class LiquibaseStepDefinitions implements En {
private List<FineractPlatformTenant> allTenants; private List<FineractPlatformTenant> allTenants;
private SchemaUpgradeNeededException executionException; private SchemaUpgradeNeededException executionException;
private DataSource defaultTenantDataSource; private DataSource defaultTenantDataSource;
private Environment environment;
public LiquibaseStepDefinitions() { public LiquibaseStepDefinitions() {
Given("Liquibase is disabled with a default tenant", () -> { Given("Liquibase is disabled with a default tenant", () -> {
@@ -148,6 +151,7 @@ public class LiquibaseStepDefinitions implements En {
tenantDataSourceFactory = mock(TenantDataSourceFactory.class); tenantDataSourceFactory = mock(TenantDataSourceFactory.class);
tenantDetailsService = mock(TenantDetailsService.class); tenantDetailsService = mock(TenantDetailsService.class);
databaseStateVerifier = mock(TenantDatabaseStateVerifier.class); databaseStateVerifier = mock(TenantDatabaseStateVerifier.class);
environment = new MockEnvironment();
liquibaseFactory = mock(ExtendedSpringLiquibaseFactory.class); liquibaseFactory = mock(ExtendedSpringLiquibaseFactory.class);
@@ -176,6 +180,6 @@ public class LiquibaseStepDefinitions implements En {
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "custom_changelog")).willReturn(customChangeLogLiquibase); given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "custom_changelog")).willReturn(customChangeLogLiquibase);
tenantDatabaseUpgradeService = new TenantDatabaseUpgradeService(tenantDetailsService, tenantStoreDataSource, fineractProperties, tenantDatabaseUpgradeService = new TenantDatabaseUpgradeService(tenantDetailsService, tenantStoreDataSource, fineractProperties,
databaseStateVerifier, liquibaseFactory, tenantDataSourceFactory); databaseStateVerifier, liquibaseFactory, tenantDataSourceFactory, environment);
} }
} }
@@ -31,9 +31,9 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.event.external.exception.ExternalEventConfigurationNotFoundException; import org.apache.fineract.infrastructure.event.external.exception.ExternalEventConfigurationNotFoundException;
import org.apache.fineract.infrastructure.event.external.service.validation.ExternalEventSourceService; import org.apache.fineract.infrastructure.event.external.service.validation.ExternalEventSourceService;
import org.apache.fineract.infrastructure.security.service.TenantDetailsService;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;