This is an automated email from the ASF dual-hosted git repository. adamsaghy pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 59409550a77bc7bd8e37d12049faad7983104947 Author: Adam Saghy <[email protected]> AuthorDate: Mon Jul 21 14:53:25 2025 +0200 FINERACT-2181: Money helper exception handling --- .../service/tenant/JdbcTenantDetailsService.java | 2 +- .../organisation/monetary/domain/MoneyHelper.java | 7 +-- .../service/MoneyHelperInitializationService.java | 25 ++------ .../MoneyHelperStartupInitializationService.java | 70 +++++++--------------- 4 files changed, 30 insertions(+), 74 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/tenant/JdbcTenantDetailsService.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/tenant/JdbcTenantDetailsService.java index 3cc6167ed6..e248b301ae 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/tenant/JdbcTenantDetailsService.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/tenant/JdbcTenantDetailsService.java @@ -35,7 +35,7 @@ import org.springframework.stereotype.Service; * A JDBC implementation of {@link TenantDetailsService} for loading a tenants details by a * <code>tenantIdentifier</code>. */ -@Service +@Service("tenantDetailsService") public class JdbcTenantDetailsService implements TenantDetailsService { private final JdbcTemplate jdbcTemplate; diff --git a/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java b/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java index f605f8e8de..10e55688db 100644 --- a/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java +++ b/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java @@ -33,7 +33,6 @@ import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; public final class MoneyHelper { public static final int PRECISION = 19; - private static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_EVEN; private static final ConcurrentHashMap<String, RoundingMode> roundingModeCache = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String, MathContext> mathContextCache = new ConcurrentHashMap<>(); @@ -62,7 +61,7 @@ public final class MoneyHelper { // Clear math context cache to force recreation with new rounding mode mathContextCache.remove(tenantIdentifier); - log.info("Initialized rounding mode for tenant {}: {}", tenantIdentifier, roundingMode.name()); + log.info("Initialized rounding mode for tenant `{}`: {}", tenantIdentifier, roundingMode.name()); } /** @@ -77,9 +76,7 @@ public final class MoneyHelper { RoundingMode roundingMode = roundingModeCache.get(tenantId); if (roundingMode == null) { - // For integration tests and development, use default if not initialized - log.warn("Rounding mode not initialized for tenant: {}. Using default: {}", tenantId, DEFAULT_ROUNDING_MODE); - return DEFAULT_ROUNDING_MODE; + throw new IllegalStateException("Rounding mode is not initialized for tenant: " + tenantId); } return roundingMode; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java index 617ef4a28d..04eac2f3dc 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperInitializationService.java @@ -18,7 +18,6 @@ */ package org.apache.fineract.infrastructure.configuration.service; -import java.math.RoundingMode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants; @@ -66,9 +65,6 @@ public class MoneyHelperInitializationService { // Initialize MoneyHelper for this tenant MoneyHelper.initializeTenantRoundingMode(tenantIdentifier, roundingModeValue); - - log.info("MoneyHelper initialized for tenant '{}' with rounding mode: {}", tenantIdentifier, roundingModeValue); - } catch (Exception e) { log.error("Failed to initialize MoneyHelper for tenant '{}'", tenantIdentifier, e); throw new RuntimeException("Failed to initialize MoneyHelper for tenant: " + tenantIdentifier, e); @@ -90,26 +86,13 @@ public class MoneyHelperInitializationService { } /** - * Get the rounding mode from configuration with fallback to default. This method safely handles cases where - * configuration might not be available. + * Get the rounding mode from configuration with fallback to default. * * @return the rounding mode value */ private int getRoundingModeFromConfiguration() { - try { - GlobalConfigurationProperty roundingModeProperty = globalConfigurationRepository - .findOneByNameWithNotFoundDetection(GlobalConfigurationConstants.ROUNDING_MODE); - - if (roundingModeProperty != null && roundingModeProperty.getValue() != null) { - return roundingModeProperty.getValue().intValue(); - } - } catch (Exception e) { - log.warn("Failed to read rounding mode from configuration: {}", e.getMessage()); - } - - // Default to HALF_UP if configuration is not available - int defaultRoundingMode = RoundingMode.HALF_UP.ordinal(); - log.info("Using default rounding mode: {} (HALF_UP)", defaultRoundingMode); - return defaultRoundingMode; + GlobalConfigurationProperty roundingModeProperty = globalConfigurationRepository + .findOneByNameWithNotFoundDetection(GlobalConfigurationConstants.ROUNDING_MODE); + return roundingModeProperty.getValue().intValue(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java index 7215d9616d..bdef68fa6a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/MoneyHelperStartupInitializationService.java @@ -23,9 +23,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.core.annotation.Order; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Service; /** @@ -35,7 +34,8 @@ import org.springframework.stereotype.Service; @Service @Slf4j @RequiredArgsConstructor -public class MoneyHelperStartupInitializationService { +@DependsOn({ "tenantDetailsService", "moneyHelperInitializationService", "tenantDatabaseUpgradeService" }) +public class MoneyHelperStartupInitializationService implements InitializingBean { private final TenantDetailsService tenantDetailsService; private final MoneyHelperInitializationService moneyHelperInitializationService; @@ -43,54 +43,30 @@ public class MoneyHelperStartupInitializationService { /** * Initialize MoneyHelper for all tenants after the application is ready. This method runs after * ApplicationReadyEvent to ensure all database migrations and tenant configurations are complete. + * + * If it fails (for any reason), it will fail the application startup! + * */ - @EventListener(ApplicationReadyEvent.class) - @Order(1000) // Run after other startup processes - public void initializeMoneyHelperForAllTenants() { + @Override + public void afterPropertiesSet() throws Exception { log.info("Starting MoneyHelper initialization for all tenants..."); - try { - List<FineractPlatformTenant> tenants = tenantDetailsService.findAllTenants(); - - if (tenants.isEmpty()) { - log.warn("No tenants found during MoneyHelper initialization"); - return; - } - - int successCount = 0; - int failureCount = 0; - - for (FineractPlatformTenant tenant : tenants) { - try { - String tenantIdentifier = tenant.getTenantIdentifier(); - - // Check if already initialized (in case of restart scenarios) - if (moneyHelperInitializationService.isTenantInitialized(tenantIdentifier)) { - log.debug("MoneyHelper already initialized for tenant: {}", tenantIdentifier); - successCount++; - continue; - } - - // Initialize MoneyHelper for this tenant - moneyHelperInitializationService.initializeTenantRoundingMode(tenant); - successCount++; - - } catch (Exception e) { - failureCount++; - log.error("Failed to initialize MoneyHelper for tenant '{}'", tenant.getTenantIdentifier(), e); - } - } - - log.info("MoneyHelper initialization completed - Success: {}, Failures: {}, Total: {}", successCount, failureCount, - tenants.size()); + List<FineractPlatformTenant> tenants = tenantDetailsService.findAllTenants(); + if (tenants.isEmpty()) { + log.warn("No tenants found during MoneyHelper initialization"); + return; + } - if (failureCount > 0) { - log.warn("Some tenants failed MoneyHelper initialization. " - + "These tenants may experience issues with rounding mode configuration."); + for (FineractPlatformTenant tenant : tenants) { + String tenantIdentifier = tenant.getTenantIdentifier(); + // Check if already initialized (in case of restart scenarios) + if (moneyHelperInitializationService.isTenantInitialized(tenantIdentifier)) { + log.debug("MoneyHelper already initialized for tenant: {}", tenantIdentifier); + continue; } - - } catch (Exception e) { - log.error("Critical error during MoneyHelper initialization for all tenants", e); + // Initialize MoneyHelper for this tenant + moneyHelperInitializationService.initializeTenantRoundingMode(tenant); } + log.info("MoneyHelper initialization completed"); } }
