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
The following commit(s) were added to refs/heads/develop by this push:
new 5079203d57 FINERACT-2389: Fix for rounding mode not being initialized
whenever a new tenant is added to the system without a restart
5079203d57 is described below
commit 5079203d57b7ab14368f7e19b286098439ff78c8
Author: Arnold Galovics <[email protected]>
AuthorDate: Thu Nov 6 11:30:56 2025 +0100
FINERACT-2389: Fix for rounding mode not being initialized whenever a new
tenant is added to the system without a restart
---
.../domain/GlobalConfigurationProperty.java | 0
.../domain/GlobalConfigurationRepository.java | 0
.../GlobalConfigurationRepositoryWrapper.java | 0
...obalConfigurationPropertyNotFoundException.java | 0
.../service/MoneyHelperInitializationService.java | 15 ++++++++++++---
.../MoneyHelperStartupInitializationService.java | 0
.../TomcatJdbcDataSourcePerTenantService.java | 22 ++++++++++++++++++++++
7 files changed, 34 insertions(+), 3 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
similarity index 100%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepository.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepository.java
similarity index 100%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepository.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepository.java
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepositoryWrapper.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepositoryWrapper.java
similarity index 100%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepositoryWrapper.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationRepositoryWrapper.java
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/exception/GlobalConfigurationPropertyNotFoundException.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/exception/GlobalConfigurationPropertyNotFoundException.java
similarity index 100%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/exception/GlobalConfigurationPropertyNotFoundException.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/exception/GlobalConfigurationPropertyNotFoundException.java
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java
similarity index 87%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java
index 04eac2f3dc..34fea1c7d0 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java
+++
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java
@@ -26,6 +26,8 @@ import
org.apache.fineract.infrastructure.configuration.domain.GlobalConfigurati
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
/**
@@ -40,7 +42,10 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor
public class MoneyHelperInitializationService {
- private final GlobalConfigurationRepositoryWrapper
globalConfigurationRepository;
+ // TODO: this is preventing the circular dependency...
+ @Lazy
+ @Autowired
+ private GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
/**
* Initialize MoneyHelper for a specific tenant. This method should be
called during tenant setup and whenever
@@ -56,6 +61,7 @@ public class MoneyHelperInitializationService {
String tenantIdentifier = tenant.getTenantIdentifier();
+ FineractPlatformTenant originalTenant =
ThreadLocalContextUtil.getTenant();
try {
// Set tenant context to read configuration
ThreadLocalContextUtil.setTenant(tenant);
@@ -69,8 +75,7 @@ public class MoneyHelperInitializationService {
log.error("Failed to initialize MoneyHelper for tenant '{}'",
tenantIdentifier, e);
throw new RuntimeException("Failed to initialize MoneyHelper for
tenant: " + tenantIdentifier, e);
} finally {
- // Clear tenant context
- ThreadLocalContextUtil.clearTenant();
+ ThreadLocalContextUtil.setTenant(originalTenant);
}
}
@@ -85,6 +90,10 @@ public class MoneyHelperInitializationService {
return MoneyHelper.isTenantInitialized(tenantIdentifier);
}
+ public boolean isTenantInitialized(FineractPlatformTenant tenant) {
+ return isTenantInitialized(tenant.getTenantIdentifier());
+ }
+
/**
* Get the rounding mode from configuration with fallback to default.
*
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java
similarity index 100%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java
diff --git
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/TomcatJdbcDataSourcePerTenantService.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/TomcatJdbcDataSourcePerTenantService.java
index e3b792e1b1..a6c1889dd8 100644
---
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/TomcatJdbcDataSourcePerTenantService.java
+++
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/TomcatJdbcDataSourcePerTenantService.java
@@ -18,14 +18,17 @@
*/
package org.apache.fineract.infrastructure.core.service.database;
+import com.google.common.collect.Sets;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import
org.apache.fineract.infrastructure.configuration.service.MoneyHelperInitializationService;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import
org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@@ -53,6 +56,9 @@ public class TomcatJdbcDataSourcePerTenantService implements
RoutingDataSourceSe
private final DataSourcePerTenantServiceFactory
dataSourcePerTenantServiceFactory;
+ private final MoneyHelperInitializationService
moneyHelperInitializationService;
+ private final Set<Long> tenantMoneyInitializingSet =
Sets.newConcurrentHashSet();
+
@Override
public DataSource retrieveDataSource() {
// default to tenant database datasource
@@ -66,7 +72,23 @@ public class TomcatJdbcDataSourcePerTenantService implements
RoutingDataSourceSe
// appropriate datasource for that tenant.
actualDataSource =
TENANT_TO_DATA_SOURCE_MAP.computeIfAbsent(tenantConnectionKey,
(key) ->
dataSourcePerTenantServiceFactory.createNewDataSourceFor(tenant,
tenantConnection));
+ }
+ // TODO: This is definitely not the optimal place to initialize the
rounding modes
+ // Preferably nothing should use a statically referenced context and
the initialization
+ // should happen within the rounding mode retrieval
+ if (tenant != null) {
+ Long connectionId = tenant.getConnection().getConnectionId();
+ if (!tenantMoneyInitializingSet.contains(connectionId) &&
!moneyHelperInitializationService.isTenantInitialized(tenant)) {
+ // Double check to prevent visibility and race-condition issues
+ synchronized (tenantMoneyInitializingSet) {
+ if (!tenantMoneyInitializingSet.contains(connectionId)) {
+ tenantMoneyInitializingSet.add(connectionId);
+
moneyHelperInitializationService.initializeTenantRoundingMode(tenant);
+ tenantMoneyInitializingSet.remove(connectionId);
+ }
+ }
+ }
}
return actualDataSource;