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");
     }
 }

Reply via email to