Skip to content

Commit 5079203

Browse files
committed
FINERACT-2389: Fix for rounding mode not being initialized whenever a new tenant is added to the system without a restart
1 parent 63c220e commit 5079203

7 files changed

Lines changed: 34 additions & 3 deletions

File tree

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java renamed to fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java

File renamed without changes.

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepository.java renamed to fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepository.java

File renamed without changes.

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepositoryWrapper.java renamed to fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepositoryWrapper.java

File renamed without changes.

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/exception/GlobalConfigurationPropertyNotFoundException.java renamed to fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/exception/GlobalConfigurationPropertyNotFoundException.java

File renamed without changes.

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java renamed to fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
2727
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
2828
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
29+
import org.springframework.beans.factory.annotation.Autowired;
30+
import org.springframework.context.annotation.Lazy;
2931
import org.springframework.stereotype.Service;
3032

3133
/**
@@ -40,7 +42,10 @@
4042
@RequiredArgsConstructor
4143
public class MoneyHelperInitializationService {
4244

43-
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
45+
// TODO: this is preventing the circular dependency...
46+
@Lazy
47+
@Autowired
48+
private GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
4449

4550
/**
4651
* Initialize MoneyHelper for a specific tenant. This method should be called during tenant setup and whenever
@@ -56,6 +61,7 @@ public void initializeTenantRoundingMode(FineractPlatformTenant tenant) {
5661

5762
String tenantIdentifier = tenant.getTenantIdentifier();
5863

64+
FineractPlatformTenant originalTenant = ThreadLocalContextUtil.getTenant();
5965
try {
6066
// Set tenant context to read configuration
6167
ThreadLocalContextUtil.setTenant(tenant);
@@ -69,8 +75,7 @@ public void initializeTenantRoundingMode(FineractPlatformTenant tenant) {
6975
log.error("Failed to initialize MoneyHelper for tenant '{}'", tenantIdentifier, e);
7076
throw new RuntimeException("Failed to initialize MoneyHelper for tenant: " + tenantIdentifier, e);
7177
} finally {
72-
// Clear tenant context
73-
ThreadLocalContextUtil.clearTenant();
78+
ThreadLocalContextUtil.setTenant(originalTenant);
7479
}
7580
}
7681

@@ -85,6 +90,10 @@ public boolean isTenantInitialized(String tenantIdentifier) {
8590
return MoneyHelper.isTenantInitialized(tenantIdentifier);
8691
}
8792

93+
public boolean isTenantInitialized(FineractPlatformTenant tenant) {
94+
return isTenantInitialized(tenant.getTenantIdentifier());
95+
}
96+
8897
/**
8998
* Get the rounding mode from configuration with fallback to default.
9099
*

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java renamed to fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java

File renamed without changes.

fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/TomcatJdbcDataSourcePerTenantService.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@
1818
*/
1919
package org.apache.fineract.infrastructure.core.service.database;
2020

21+
import com.google.common.collect.Sets;
2122
import java.sql.Connection;
2223
import java.sql.SQLException;
2324
import java.util.List;
2425
import java.util.Map;
26+
import java.util.Set;
2527
import java.util.concurrent.ConcurrentHashMap;
2628
import javax.sql.DataSource;
2729
import lombok.RequiredArgsConstructor;
2830
import lombok.extern.slf4j.Slf4j;
31+
import org.apache.fineract.infrastructure.configuration.service.MoneyHelperInitializationService;
2932
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
3033
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection;
3134
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@@ -53,6 +56,9 @@ public class TomcatJdbcDataSourcePerTenantService implements RoutingDataSourceSe
5356

5457
private final DataSourcePerTenantServiceFactory dataSourcePerTenantServiceFactory;
5558

59+
private final MoneyHelperInitializationService moneyHelperInitializationService;
60+
private final Set<Long> tenantMoneyInitializingSet = Sets.newConcurrentHashSet();
61+
5662
@Override
5763
public DataSource retrieveDataSource() {
5864
// default to tenant database datasource
@@ -66,7 +72,23 @@ public DataSource retrieveDataSource() {
6672
// appropriate datasource for that tenant.
6773
actualDataSource = TENANT_TO_DATA_SOURCE_MAP.computeIfAbsent(tenantConnectionKey,
6874
(key) -> dataSourcePerTenantServiceFactory.createNewDataSourceFor(tenant, tenantConnection));
75+
}
6976

77+
// TODO: This is definitely not the optimal place to initialize the rounding modes
78+
// Preferably nothing should use a statically referenced context and the initialization
79+
// should happen within the rounding mode retrieval
80+
if (tenant != null) {
81+
Long connectionId = tenant.getConnection().getConnectionId();
82+
if (!tenantMoneyInitializingSet.contains(connectionId) && !moneyHelperInitializationService.isTenantInitialized(tenant)) {
83+
// Double check to prevent visibility and race-condition issues
84+
synchronized (tenantMoneyInitializingSet) {
85+
if (!tenantMoneyInitializingSet.contains(connectionId)) {
86+
tenantMoneyInitializingSet.add(connectionId);
87+
moneyHelperInitializationService.initializeTenantRoundingMode(tenant);
88+
tenantMoneyInitializingSet.remove(connectionId);
89+
}
90+
}
91+
}
7092
}
7193

7294
return actualDataSource;

0 commit comments

Comments
 (0)