This is an automated email from the ASF dual-hosted git repository.

vorburger 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 1b1e80b  Log errors from cron jobs individually and with cause 
(FINERACT-858)
1b1e80b is described below

commit 1b1e80b6b1e084d30c19fa339fe7342366c43c76
Author: Michael Vorburger <[email protected]>
AuthorDate: Mon Mar 9 00:29:18 2020 +0100

    Log errors from cron jobs individually and with cause (FINERACT-858)
    
    instead of current huge JobExecutionException message (without cause)
---
 .../AccrualAccountingWritePlatformServiceImpl.java |   8 +-
 .../exception/MultiException.java}                 |  32 ++--
 .../infrastructure/jobs/annotation/CronTarget.java |   2 -
 .../jobs/exception/JobExecutionException.java      |   8 +-
 .../infrastructure/jobs/service/JobName.java       |  42 +++---
 ...tandingInstructionWritePlatformServiceImpl.java |  45 +++---
 .../domain/LoanAccountDomainServiceJpa.java        |  40 ++---
 .../service/LoanAccrualPlatformService.java        |   5 +-
 .../service/LoanAccrualPlatformServiceImpl.java    |  53 ++++---
 .../loanaccount/service/LoanSchedularService.java  |   4 -
 .../service/LoanSchedularServiceImpl.java          | 155 ++++++++------------
 .../LoanWritePlatformServiceJpaRepositoryImpl.java | 162 ++++++++++-----------
 .../service/RecalculateInterestPoster.java         |  78 +++-------
 ...countWritePlatformServiceJpaRepositoryImpl.java |  37 ++---
 .../service/SavingsSchedularServiceImpl.java       |  40 +++--
 .../service/ScheduledJobRunnerServiceImpl.java     | 119 +++++++--------
 16 files changed, 373 insertions(+), 457 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
index 7f42124..a745840 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
@@ -29,6 +29,7 @@ import 
org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import 
org.apache.fineract.portfolio.loanaccount.service.LoanAccrualPlatformService;
 import org.joda.time.LocalDate;
@@ -52,12 +53,13 @@ public class AccrualAccountingWritePlatformServiceImpl 
implements AccrualAccount
     public CommandProcessingResult executeLoansPeriodicAccrual(JsonCommand 
command) {
         
this.accountingDataValidator.validateLoanPeriodicAccrualData(command.json());
         LocalDate tilldate = 
command.localDateValueOfParameterNamed(accrueTillParamName);
-        String errorlog = 
this.loanAccrualPlatformService.addPeriodicAccruals(tilldate);
-        if (errorlog.length() > 0) {
+        try {
+            this.loanAccrualPlatformService.addPeriodicAccruals(tilldate);
+        } catch (MultiException e) {
             final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
             final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors)
                     .resource(PERIODIC_ACCRUAL_ACCOUNTING_RESOURCE_NAME);
-            
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(PERIODIC_ACCRUAL_ACCOUNTING_EXECUTION_ERROR_CODE,
 errorlog);
+            
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(PERIODIC_ACCRUAL_ACCOUNTING_EXECUTION_ERROR_CODE,
 e.getMessage());
             throw new PlatformApiDataValidationException(dataValidationErrors);
         }
         return CommandProcessingResult.empty();
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/exception/MultiException.java
similarity index 50%
copy from 
fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
copy to 
fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/exception/MultiException.java
index 1d5596d..79ba28b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/exception/MultiException.java
@@ -16,22 +16,30 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.infrastructure.jobs.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.apache.fineract.infrastructure.jobs.service.JobName;
+package org.apache.fineract.infrastructure.core.exception;
 
 /**
- * Annotation that marks a method to be picked while scheduling a cron jobs.
+ * Exception with multiple root causes.
+ *
+ * Intended to be used in places where N operations are performed in a loop 
over something,
+ * each of which could fail, but where we don't want to fail immediately but 
continue, and
+ * then fail at end.
  *
+ * <p>The failures MUST each be logged within the loop, as they occur; this 
exception is
+ * only thrown to propagate the failure, but will not contain and re-log the 
details.
+ *
+ * @author Michael Vorburger.ch <[email protected]>
  */
+public class MultiException extends Exception {
+
+    private final int n;
 
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface CronTarget {
+    public MultiException(int n) {
+        super(n + "x failures occured here (details have been previously 
logged");
+        this.n = n;
+    }
 
-    JobName jobName();
+    public int getCausesSize() {
+        return n;
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
index 1d5596d..16aba6e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
@@ -26,9 +26,7 @@ import 
org.apache.fineract.infrastructure.jobs.service.JobName;
 
 /**
  * Annotation that marks a method to be picked while scheduling a cron jobs.
- *
  */
-
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface CronTarget {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
index 3ebc87b..c66b9d6 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
@@ -18,9 +18,11 @@
  */
 package org.apache.fineract.infrastructure.jobs.exception;
 
-public class JobExecutionException extends Exception {
+import org.apache.fineract.infrastructure.core.exception.MultiException;
 
-    public JobExecutionException(final String msg) {
-        super(msg);
+public class JobExecutionException extends MultiException {
+
+    public JobExecutionException(int n) {
+        super(n);
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
index 999e296..cebba45 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
@@ -20,27 +20,27 @@ package org.apache.fineract.infrastructure.jobs.service;
 
 public enum JobName {
 
-    UPDATE_LOAN_SUMMARY("Update loan Summary"), //
-    UPDATE_LOAN_ARREARS_AGEING("Update Loan Arrears Ageing"), //
-    UPDATE_LOAN_PAID_IN_ADVANCE("Update Loan Paid In Advance"), //
-    APPLY_ANNUAL_FEE_FOR_SAVINGS("Apply Annual Fee For Savings"), //
-    APPLY_HOLIDAYS_TO_LOANS("Apply Holidays To Loans"), //
-    POST_INTEREST_FOR_SAVINGS("Post Interest For Savings"), //
-    TRANSFER_FEE_CHARGE_FOR_LOANS("Transfer Fee For Loans From Savings"), //
-    ACCOUNTING_RUNNING_BALANCE_UPDATE("Update Accounting Running Balances"), //
-    PAY_DUE_SAVINGS_CHARGES("Pay Due Savings Charges"), //
-    APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue 
loans"), //
-    EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction"), //
-    ADD_ACCRUAL_ENTRIES("Add Accrual Transactions"), //
-    UPDATE_NPA("Update Non Performing Assets"), //
-    UPDATE_DEPOSITS_ACCOUNT_MATURITY_DETAILS("Update Deposit Accounts Maturity 
details"), //
-    TRANSFER_INTEREST_TO_SAVINGS("Transfer Interest To Savings"), //
-    ADD_PERIODIC_ACCRUAL_ENTRIES("Add Periodic Accrual Transactions"), //
-    RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"), //
-    GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"), //
-    GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
-    POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"), //
-    UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"), //
+    UPDATE_LOAN_SUMMARY("Update loan Summary"),
+    UPDATE_LOAN_ARREARS_AGEING("Update Loan Arrears Ageing"),
+    UPDATE_LOAN_PAID_IN_ADVANCE("Update Loan Paid In Advance"),
+    APPLY_ANNUAL_FEE_FOR_SAVINGS("Apply Annual Fee For Savings"),
+    APPLY_HOLIDAYS_TO_LOANS("Apply Holidays To Loans"),
+    POST_INTEREST_FOR_SAVINGS("Post Interest For Savings"),
+    TRANSFER_FEE_CHARGE_FOR_LOANS("Transfer Fee For Loans From Savings"),
+    ACCOUNTING_RUNNING_BALANCE_UPDATE("Update Accounting Running Balances"),
+    PAY_DUE_SAVINGS_CHARGES("Pay Due Savings Charges"),
+    APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans"),
+    EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction"),
+    ADD_ACCRUAL_ENTRIES("Add Accrual Transactions"),
+    UPDATE_NPA("Update Non Performing Assets"),
+    UPDATE_DEPOSITS_ACCOUNT_MATURITY_DETAILS("Update Deposit Accounts Maturity 
details"),
+    TRANSFER_INTEREST_TO_SAVINGS("Transfer Interest To Savings"),
+    ADD_PERIODIC_ACCRUAL_ENTRIES("Add Periodic Accrual Transactions"),
+    RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"),
+    GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"),
+    GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"),
+    POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"),
+    UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"),
     
ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS("Add 
Accrual Transactions For Loans With Income Posted As Transactions"),
     EXECUTE_REPORT_MAILING_JOBS("Execute Report Mailing Jobs"),
     UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE("Update SMS Outbound with 
Campaign Message"),
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
index 657e26d..dac87a2 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
@@ -167,10 +167,10 @@ public class StandingInstructionWritePlatformServiceImpl 
implements StandingInst
         AccountTransferStandingInstruction standingInstructionsForUpdate = 
this.standingInstructionRepository.findById(id)
                 .orElseThrow(() -> new 
StandingInstructionNotFoundException(id));
         final Map<String, Object> actualChanges = 
standingInstructionsForUpdate.update(command);
-        return new CommandProcessingResultBuilder() //
-                .withCommandId(command.commandId()) //
-                .withEntityId(id) //
-                .with(actualChanges) //
+        return new CommandProcessingResultBuilder()
+                .withCommandId(command.commandId())
+                .withEntityId(id)
+                .with(actualChanges)
                 .build();
     }
 
@@ -182,9 +182,9 @@ public class StandingInstructionWritePlatformServiceImpl 
implements StandingInst
 
         final Map<String, Object> actualChanges = new HashMap<>();
         actualChanges.put(statusParamName, 
StandingInstructionStatus.DELETED.getValue());
-        return new CommandProcessingResultBuilder() //
-                .withEntityId(id) //
-                .with(actualChanges) //
+        return new CommandProcessingResultBuilder()
+                .withEntityId(id)
+                .with(actualChanges)
                 .build();
     }
 
@@ -237,8 +237,8 @@ public class StandingInstructionWritePlatformServiceImpl 
implements StandingInst
                 final boolean isExceptionForBalanceCheck = false;
                 AccountTransferDTO accountTransferDTO = new 
AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
                         data.toAccountType(), data.fromAccount().accountId(), 
data.toAccount().accountId(), data.name()
-                                + " Standing instruction trasfer ", null, 
null, null, null, data.toTransferType(), null, null, data
-                                .transferType().getValue(), null, null, null, 
null, null, fromSavingsAccount,
+                        + " Standing instruction trasfer ", null, null, null, 
null, data.toTransferType(), null, null, data
+                        .transferType().getValue(), null, null, null, null, 
null, fromSavingsAccount,
                         isRegularTransaction, isExceptionForBalanceCheck);
                 final boolean transferCompleted = transferAmount(sb, 
accountTransferDTO, data.getId());
 
@@ -249,14 +249,13 @@ public class StandingInstructionWritePlatformServiceImpl 
implements StandingInst
 
             }
         }
-        if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); 
}
-
+        if (sb.length() > 0) {
+            logger.error("executeStandingInstructions (transferAmount) 
encountered failure/s: {}", sb.toString());
+            // This is a bit of a hack (related to 
https://issues.apache.org/jira/browse/FINERACT-858) and could be improved..
+            throw new JobExecutionException(123456789);
+        }
     }
 
-    /**
-     * @param sb
-     * @param accountTransferDTO
-     */
     private boolean transferAmount(final StringBuilder sb, final 
AccountTransferDTO accountTransferDTO, final Long instructionId) {
         boolean transferCompleted = true;
         StringBuffer errorLog = new StringBuffer();
@@ -266,23 +265,23 @@ public class StandingInstructionWritePlatformServiceImpl 
implements StandingInst
             
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
         } catch (final PlatformApiDataValidationException e) {
             sb.append("Validation exception while trasfering funds for 
standing Instruction id").append(instructionId).append(" from ")
-                    .append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
-                    .append("--------");
+            .append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
+            .append("--------");
             errorLog.append("Validation exception while trasfering funds " + 
e.getDefaultUserMessage());
         } catch (final InsufficientAccountBalanceException e) {
             sb.append("InsufficientAccountBalance Exception while trasfering 
funds for standing Instruction id").append(instructionId)
-                    .append(" from 
").append(accountTransferDTO.getFromAccountId()).append(" to ")
-                    
.append(accountTransferDTO.getToAccountId()).append("--------");
+            .append(" from 
").append(accountTransferDTO.getFromAccountId()).append(" to ")
+            .append(accountTransferDTO.getToAccountId()).append("--------");
             errorLog.append("InsufficientAccountBalance Exception ");
         } catch (final AbstractPlatformServiceUnavailableException e) {
             sb.append("Platform exception while trasfering funds for standing 
Instruction id").append(instructionId).append(" from ")
-                    .append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
-                    .append("--------");
+            .append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
+            .append("--------");
             errorLog.append("Platform exception while trasfering funds " + 
e.getDefaultUserMessage());
         } catch (Exception e) {
             sb.append("Exception while trasfering funds for standing 
Instruction id").append(instructionId).append(" from ")
-                    .append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
-                    .append("--------");
+            .append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
+            .append("--------");
             errorLog.append("Exception while trasfering funds " + 
e.getMessage());
 
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index af4eb32..f288b6d 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -35,6 +35,7 @@ import 
org.apache.fineract.infrastructure.core.data.ApiParameterError;
 import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
 import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
 import 
org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -227,10 +228,10 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         // disable all active standing orders linked to this loan if status 
changes to closed
         disableStandingInstructionsLinkedToClosedLoan(loan);
 
-        builderResult.withEntityId(newRepaymentTransaction.getId()) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()); //
+        builderResult.withEntityId(newRepaymentTransaction.getId())
+        .withOfficeId(loan.getOfficeId())
+        .withClientId(loan.getClientId())
+        .withGroupId(loan.getGroupId());
 
         return newRepaymentTransaction;
     }
@@ -244,7 +245,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
             if 
(realCause.getMessage().toLowerCase().contains("external_id_unique")) {
                 
baseDataValidator.reset().parameter("externalId").value(newRepaymentTransaction.getExternalId())
-                        .failWithCode("value.must.be.unique");
+                .failWithCode("value.must.be.unique");
             }
             if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException("validation.msg.validation.errors.exist",
                     "Validation errors exist.", dataValidationErrors); }
@@ -412,10 +413,10 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds, isAccountTransfer);
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_REFUND,
                 constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, 
newRefundTransaction));
-        builderResult.withEntityId(newRefundTransaction.getId()) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()); //
+        builderResult.withEntityId(newRefundTransaction.getId())
+        .withOfficeId(loan.getOfficeId())
+        .withClientId(loan.getClientId())
+        .withGroupId(loan.getGroupId());
 
         return newRefundTransaction;
     }
@@ -509,10 +510,11 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         }
 
         if (!loanScheduleAccrualDatas.isEmpty()) {
-            String error = 
this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill, 
loanScheduleAccrualDatas);
-            if (error.length() > 0) {
+            try {
+                
this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill, 
loanScheduleAccrualDatas);
+            } catch (MultiException e) {
                 String globalisationMessageCode = 
"error.msg.accrual.exception";
-                throw new 
GeneralPlatformDomainRuleException(globalisationMessageCode, error, error);
+                throw new 
GeneralPlatformDomainRuleException(globalisationMessageCode, e.getMessage());
             }
         }
     }
@@ -543,10 +545,10 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             LoanScheduleAccrualData accrualData = new 
LoanScheduleAccrualData(loanId, officeId, installment.getInstallmentNumber(),
                     accrualStartDate, repaymentFrequency, repayEvery, 
installment.getDueDate(), installment.getFromDate(),
                     installment.getId(), loanProductId, 
installment.getInterestCharged(currency).getAmount(), installment
-                            .getFeeChargesCharged(currency).getAmount(), 
installment.getPenaltyChargesCharged(currency).getAmount(),
+                    .getFeeChargesCharged(currency).getAmount(), 
installment.getPenaltyChargesCharged(currency).getAmount(),
                     installment.getInterestAccrued(currency).getAmount(), 
installment.getFeeAccrued(currency).getAmount(), installment
-                            .getPenaltyAccrued(currency).getAmount(), 
currencyData, interestCalculatedFrom, installment
-                            .getInterestWaived(currency).getAmount());
+                    .getPenaltyAccrued(currency).getAmount(), currencyData, 
interestCalculatedFrom, installment
+                    .getInterestWaived(currency).getAmount());
             loanScheduleAccrualDatas.add(accrualData);
 
         }
@@ -604,10 +606,10 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_REFUND,
                 constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, 
newRefundTransaction));
 
-        builderResult.withEntityId(newRefundTransaction.getId()) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()); //
+        builderResult.withEntityId(newRefundTransaction.getId())
+        .withOfficeId(loan.getOfficeId())
+        .withClientId(loan.getClientId())
+        .withGroupId(loan.getGroupId());
 
         return newRefundTransaction;
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
index d3311f0..edcbf94 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
@@ -19,15 +19,16 @@
 package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.util.Collection;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
 import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
 import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleAccrualData;
 import org.joda.time.LocalDate;
 
 public interface LoanAccrualPlatformService {
 
-    String addPeriodicAccruals(LocalDate tilldate);
+    void addPeriodicAccruals(LocalDate tilldate) throws MultiException;
 
-    String addPeriodicAccruals(LocalDate tilldate, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas);
+    void addPeriodicAccruals(LocalDate tilldate, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws 
MultiException;
 
     void addAccrualAccounting() throws JobExecutionException;
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
index af990ca..284b692 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
@@ -22,17 +22,22 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
 import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
 import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
 import org.apache.fineract.infrastructure.jobs.service.JobName;
 import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleAccrualData;
 import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
 public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformService {
 
+    private final static Logger LOG = 
LoggerFactory.getLogger(LoanAccrualPlatformServiceImpl.class);
+
     private final LoanReadPlatformService loanReadPlatformService;
     private final LoanAccrualWritePlatformService 
loanAccrualWritePlatformService;
 
@@ -47,7 +52,6 @@ public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformServic
     @CronTarget(jobName = JobName.ADD_ACCRUAL_ENTRIES)
     public void addAccrualAccounting() throws JobExecutionException {
         Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = 
this.loanReadPlatformService.retriveScheduleAccrualData();
-        StringBuilder sb = new StringBuilder();
         Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new 
HashMap<>();
         for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDatas) {
             if (loanDataMap.containsKey(accrualData.getLoanId())) {
@@ -59,37 +63,36 @@ public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformServic
             }
         }
 
+        int errors = 0;
         for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : 
loanDataMap.entrySet()) {
             try {
                 
this.loanAccrualWritePlatformService.addAccrualAccounting(mapEntry.getKey(), 
mapEntry.getValue());
             } catch (Exception e) {
-                Throwable realCause = e;
-                if (e.getCause() != null) {
-                    realCause = e.getCause();
-                }
-                sb.append("failed to add accural transaction for loan " + 
mapEntry.getKey() + " with message " + realCause.getMessage());
+                LOG.error("Failed to add accural transaction for loan {}", 
mapEntry.getKey(), e);
+                ++errors;
             }
         }
-
-        if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); 
}
+        if (errors > 0) { throw new JobExecutionException(errors); }
     }
 
     @Override
     @CronTarget(jobName = JobName.ADD_PERIODIC_ACCRUAL_ENTRIES)
     public void addPeriodicAccruals() throws JobExecutionException {
-        String errors = addPeriodicAccruals(LocalDate.now());
-        if (errors.length() > 0) { throw new JobExecutionException(errors); }
+        try {
+            addPeriodicAccruals(LocalDate.now());
+        } catch (MultiException e) {
+            throw new JobExecutionException(e.getCausesSize());
+        }
     }
 
     @Override
-    public String addPeriodicAccruals(final LocalDate tilldate) {
+    public void addPeriodicAccruals(final LocalDate tilldate) throws 
MultiException {
         Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = 
this.loanReadPlatformService.retrivePeriodicAccrualData(tilldate);
-        return addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
+        addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
     }
 
     @Override
-    public String addPeriodicAccruals(final LocalDate tilldate, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) {
-        StringBuilder sb = new StringBuilder();
+    public void addPeriodicAccruals(final LocalDate tilldate, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws 
MultiException {
         Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new 
HashMap<>();
         for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDatas) {
             if (loanDataMap.containsKey(accrualData.getLoanId())) {
@@ -101,19 +104,16 @@ public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformServic
             }
         }
 
+        int errors = 0;
         for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : 
loanDataMap.entrySet()) {
             try {
                 
this.loanAccrualWritePlatformService.addPeriodicAccruals(tilldate, 
mapEntry.getKey(), mapEntry.getValue());
             } catch (Exception e) {
-                Throwable realCause = e;
-                if (e.getCause() != null) {
-                    realCause = e.getCause();
-                }
-                sb.append("failed to add accural transaction for loan " + 
mapEntry.getKey() + " with message " + realCause.getMessage());
+                LOG.error("Failed to add accural transaction for loan {}", 
mapEntry.getKey(), e);
+                ++errors;
             }
         }
-
-        return sb.toString();
+        if (errors > 0) { throw new MultiException(errors); }
     }
 
     @Override
@@ -121,19 +121,16 @@ public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformServic
     public void addPeriodicAccrualsForLoansWithIncomePostedAsTransactions() 
throws JobExecutionException {
         Collection<Long> loanIds = 
this.loanReadPlatformService.retrieveLoanIdsWithPendingIncomePostingTransactions();
         if(loanIds != null && loanIds.size() > 0){
-            StringBuilder sb = new StringBuilder();
+            int errors = 0;
             for (Long loanId : loanIds) {
                 try {
                     
this.loanAccrualWritePlatformService.addIncomeAndAccrualTransactions(loanId);
                 } catch (Exception e) {
-                    Throwable realCause = e;
-                    if (e.getCause() != null) {
-                        realCause = e.getCause();
-                    }
-                    sb.append("failed to add income and accrual transaction 
for loan " + loanId + " with message " + realCause.getMessage());
+                    LOG.error("Failed to add income and accrual transaction 
for loan {}", loanId, e);
+                    ++errors;
                 }
             }
-            if (sb.length() > 0) { throw new 
JobExecutionException(sb.toString()); }
+            if (errors > 0) { throw new JobExecutionException(errors); }
         }
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
index 25b1728..b6bfa29 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
@@ -20,7 +20,6 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.util.Map;
 import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
-import org.apache.fineract.organisation.office.data.OfficeData;
 
 
 public interface LoanSchedularService {
@@ -29,8 +28,5 @@ public interface LoanSchedularService {
 
     void recalculateInterest() throws JobExecutionException;
 
-    void recalculateInterest(final OfficeData office, final int 
threadPoolSize, final int batchSize);
-
     void recalculateInterest(@SuppressWarnings("unused") final Map<String, 
String> jobParameters);
-
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
index f56bded..b8d36f6 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
@@ -55,6 +55,7 @@ import org.springframework.util.CollectionUtils;
 public class LoanSchedularServiceImpl implements LoanSchedularService {
 
     private final static Logger logger = 
LoggerFactory.getLogger(LoanSchedularServiceImpl.class);
+
     private final ConfigurationDomainService configurationDomainService;
     private final LoanReadPlatformService loanReadPlatformService;
     private final LoanWritePlatformService loanWritePlatformService;
@@ -63,9 +64,9 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
 
     @Autowired
     public LoanSchedularServiceImpl(final ConfigurationDomainService 
configurationDomainService,
-                                    final LoanReadPlatformService 
loanReadPlatformService, final LoanWritePlatformService 
loanWritePlatformService,
-                                    final OfficeReadPlatformService 
officeReadPlatformService,
-                                    final ApplicationContext 
applicationContext) {
+            final LoanReadPlatformService loanReadPlatformService, final 
LoanWritePlatformService loanWritePlatformService,
+            final OfficeReadPlatformService officeReadPlatformService,
+            final ApplicationContext applicationContext) {
         this.configurationDomainService = configurationDomainService;
         this.loanReadPlatformService = loanReadPlatformService;
         this.loanWritePlatformService = loanWritePlatformService;
@@ -83,7 +84,6 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
                 
.retrieveAllLoansWithOverdueInstallments(penaltyWaitPeriodValue,backdatePenalties);
 
         if (!overdueLoanScheduledInstallments.isEmpty()) {
-            final StringBuilder sb = new StringBuilder();
             final Map<Long, Collection<OverdueLoanScheduleData>> 
overdueScheduleData = new HashMap<>();
             for (final OverdueLoanScheduleData overdueInstallment : 
overdueLoanScheduledInstallments) {
                 if 
(overdueScheduleData.containsKey(overdueInstallment.getLoanId())) {
@@ -95,6 +95,7 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
                 }
             }
 
+            int numberOfErrors = 0;
             for (final Long loanId : overdueScheduleData.keySet()) {
                 try {
                     
this.loanWritePlatformService.applyOverdueChargesForLoan(loanId, 
overdueScheduleData.get(loanId));
@@ -102,28 +103,18 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
                 } catch (final PlatformApiDataValidationException e) {
                     final List<ApiParameterError> errors = e.getErrors();
                     for (final ApiParameterError error : errors) {
-                        logger.error("Apply Charges due for overdue loans 
failed for account:" + loanId + " with message "
-                                + error.getDeveloperMessage());
-                        sb.append("Apply Charges due for overdue loans failed 
for account:").append(loanId).append(" with message ")
-                                .append(error.getDeveloperMessage());
+                        logger.error("Apply Charges due for overdue loans 
failed for account {} with message: {}", loanId, error.getDeveloperMessage(), 
e);
+                        ++numberOfErrors;
                     }
-                } catch (final AbstractPlatformDomainRuleException ex) {
-                    logger.error("Apply Charges due for overdue loans failed 
for account:" + loanId + " with message "
-                            + ex.getDefaultUserMessage());
-                    sb.append("Apply Charges due for overdue loans failed for 
account:").append(loanId).append(" with message ")
-                            .append(ex.getDefaultUserMessage());
+                } catch (final AbstractPlatformDomainRuleException e) {
+                    logger.error("Apply Charges due for overdue loans failed 
for account {} with message: {}", loanId, e.getDefaultUserMessage(), e);
+                    ++numberOfErrors;
                 } catch (Exception e) {
-                    Throwable realCause = e;
-                    if (e.getCause() != null) {
-                        realCause = e.getCause();
-                    }
-                    logger.error("Apply Charges due for overdue loans failed 
for account:" + loanId + " with message "
-                            + realCause.getMessage());
-                    sb.append("Apply Charges due for overdue loans failed for 
account:").append(loanId).append(" with message ")
-                            .append(realCause.getMessage());
+                    logger.error("Apply Charges due for overdue loans failed 
for account {}", loanId, e);
+                    ++numberOfErrors;
                 }
             }
-            if (sb.length() > 0) { throw new 
JobExecutionException(sb.toString()); }
+            if (numberOfErrors > 0) { throw new 
JobExecutionException(numberOfErrors); }
         }
     }
 
@@ -138,64 +129,44 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
                 .fetchLoansForInterestRecalculation();
         int i = 0;
         if (!loanIds.isEmpty()) {
-            final StringBuilder sb = new StringBuilder();
+            int errors = 0;
             for (Long loanId : loanIds) {
-                logger.info("Loan ID " + loanId);
+                logger.info("recalculateInterest: Loan ID = {}", loanId);
                 Integer numberOfRetries = 0;
                 while (numberOfRetries <= maxNumberOfRetries) {
                     try {
-                        this.loanWritePlatformService
-                                .recalculateInterest(loanId);
+                        
this.loanWritePlatformService.recalculateInterest(loanId);
                         numberOfRetries = maxNumberOfRetries + 1;
                     } catch (CannotAcquireLockException
                             | ObjectOptimisticLockingFailureException 
exception) {
-                        logger.info("Recalulate interest job has been retried  
"
-                                + numberOfRetries + " time(s)");
-                        /***
-                         * Fail if the transaction has been retired for
-                         * maxNumberOfRetries
-                         **/
+                        logger.info("Recalulate interest job has been retried 
{} time(s)", numberOfRetries);
+                        // Fail if the transaction has been retried for 
maxNumberOfRetries
                         if (numberOfRetries >= maxNumberOfRetries) {
-                            logger.warn("Recalulate interest job has been 
retried for the max allowed attempts of "
-                                    + numberOfRetries
-                                    + " and will be rolled back");
-                            sb.append("Recalulate interest job has been 
retried for the max allowed attempts of "
-                                    + numberOfRetries
-                                    + " and will be rolled back");
+                            logger.error("Recalulate interest job has been 
retried for the max allowed attempts of {} and will be rolled back", 
numberOfRetries);
+                            ++errors;
                             break;
                         }
-                        /***
-                         * Else sleep for a random time (between 1 to 10
-                         * seconds) and continue
-                         **/
+                        // Else sleep for a random time (between 1 to 10 
seconds) and continue
                         try {
                             Random random = new Random();
-                            int randomNum = random
-                                    .nextInt(maxIntervalBetweenRetries + 1);
+                            int randomNum = 
random.nextInt(maxIntervalBetweenRetries + 1);
                             Thread.sleep(1000 + (randomNum * 1000));
                             numberOfRetries = numberOfRetries + 1;
                         } catch (InterruptedException e) {
-                            sb.append("Interest recalculation for loans failed 
" + exception.getMessage()) ;
+                            logger.error("Interest recalculation for loans 
retry failed due to InterruptedException", e) ;
+                            ++errors;
                             break;
                         }
                     } catch (Exception e) {
-                        Throwable realCause = e;
-                        if (e.getCause() != null) {
-                            realCause = e.getCause();
-                        }
-                        logger.error("Interest recalculation for loans failed 
for account:"    + loanId + " with message "
-                                + realCause.getMessage());
-                        sb.append("Interest recalculation for loans failed for 
account:").append(loanId).append(" with message ")
-                                .append(realCause.getMessage());
+                        logger.error("Interest recalculation for loans failed 
for account {}", loanId, e);
                         numberOfRetries = maxNumberOfRetries + 1;
+                        ++errors;
                     }
                     i++;
                 }
-                logger.info("Loans count " + i);
-            }
-            if (sb.length() > 0) {
-                throw new JobExecutionException(sb.toString());
+                logger.info("recalculateInterest: Loans count {}", i);
             }
+            if (errors > 0) { throw new JobExecutionException(errors); }
         }
 
     }
@@ -203,64 +174,63 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
     @Override
     @CronTarget(jobName = JobName.RECALCULATE_INTEREST_FOR_LOAN)
     public void recalculateInterest(Map<String, String> jobParameters) {
-        //gets the officeId
+        // gets the officeId
         final String officeId = jobParameters.get("officeId");
-        logger.info(officeId);
-        Long officeIdLong=Long.valueOf(officeId);
-        //gets the Office object
+        logger.info("recalculateInterest: officeId={}", officeId);
+        Long officeIdLong = Long.valueOf(officeId);
+
+        // gets the Office object
         final OfficeData office = 
this.officeReadPlatformService.retrieveOffice(officeIdLong);
-        if(office == null)
+        if(office == null) {
             throw new OfficeNotFoundException(officeIdLong);
+        }
         final int 
threadPoolSize=Integer.parseInt(jobParameters.get("thread-pool-size"));
         final int batchSize=Integer.parseInt(jobParameters.get("batch-size"));
 
         recalculateInterest(office,threadPoolSize,batchSize);
     }
 
-    @Override
-    public void recalculateInterest(OfficeData office, int threadPoolSize, int 
batchSize) {
+    private void recalculateInterest(OfficeData office, int threadPoolSize, 
int batchSize) {
         final int pageSize = batchSize * threadPoolSize;
 
-        //initialise the executor service with fetched configurations
+        // initialise the executor service with fetched configurations
         final ExecutorService executorService = 
Executors.newFixedThreadPool(threadPoolSize);
 
         Long maxLoanIdInList = 0L;
         final String officeHierarchy = office.getHierarchy() + "%";
 
-        //Get the loanIds from service
+        // get the loanIds from service
         List<Long> loanIds = 
Collections.synchronizedList(this.loanReadPlatformService
                 .fetchLoansForInterestRecalculation(pageSize, maxLoanIdInList, 
officeHierarchy));
 
-
         // gets the loanIds data set iteratively and call addAccuruals for 
that paginated dataset
         do {
             int totalFilteredRecords = loanIds.size();
             logger.info("Starting accrual - total filtered records - " + 
totalFilteredRecords);
-            recalculateInterest(loanIds, threadPoolSize, batchSize,
-                    executorService);
+            recalculateInterest(loanIds, threadPoolSize, batchSize, 
executorService);
             maxLoanIdInList+= pageSize+1;
             loanIds = Collections.synchronizedList(this.loanReadPlatformService
                     .fetchLoansForInterestRecalculation(pageSize, 
maxLoanIdInList, officeHierarchy));
         } while (!CollectionUtils.isEmpty(loanIds));
 
-        //shutdown the executor when done
+        // shutdown the executor when done
         executorService.shutdownNow();
     }
 
     private void recalculateInterest(List<Long> loanIds,
-                                     int threadPoolSize, int batchSize, final 
ExecutorService executorService) {
-        //StringBuilder sb = new StringBuilder();
+            int threadPoolSize, int batchSize, final ExecutorService 
executorService) {
 
-        List<Callable<Object>> posters = new ArrayList<Callable<Object>>();
+        List<Callable<Void>> posters = new ArrayList<>();
         int fromIndex = 0;
         // get the size of current paginated dataset
         int size = loanIds.size();
-        //calculate the batch size
-        double toGetCeilValue = (double) (size / threadPoolSize);
+        // calculate the batch size
+        double toGetCeilValue = size / threadPoolSize;
         batchSize = (int) Math.ceil(toGetCeilValue);
 
-        if(batchSize == 0)
+        if(batchSize == 0) {
             return;
+        }
 
         int toIndex = (batchSize > size - 1)? size : batchSize ;
         while(toIndex < size && loanIds.get(toIndex - 
1).equals(loanIds.get(toIndex))) {
@@ -274,27 +244,30 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
             RecalculateInterestPoster poster = (RecalculateInterestPoster) 
this.applicationContext.getBean("recalculateInterestPoster");
             poster.setLoanIds(subList);
             poster.setLoanWritePlatformService(loanWritePlatformService);
-            posters.add(Executors.callable(poster));
-            if(lastBatch)
+            posters.add(poster);
+            if(lastBatch) {
                 break;
-            if(toIndex + batchSize > size - 1)
+            }
+            if(toIndex + batchSize > size - 1) {
                 lastBatch = true;
+            }
             fromIndex = fromIndex + (toIndex - fromIndex);
             toIndex = (toIndex + batchSize > size - 1)? size : toIndex + 
batchSize;
             while(toIndex < size && loanIds.get(toIndex - 
1).equals(loanIds.get(toIndex))) {
-                toIndex ++;
+                toIndex++;
             }
         }
 
         try {
-            List<Future<Object>> responses = 
executorService.invokeAll(posters);
+            List<Future<Void>> responses = executorService.invokeAll(posters);
             checkCompletion(responses);
         } catch (InterruptedException e1) {
             logger.error("Interrupted while recalculateInterest", e1);
         }
     }
-    //break the lists into sub lists
-    public <T> List<T> safeSubList(List<T> list, int fromIndex, int toIndex) {
+
+    // break the lists into sub lists
+    private <T> List<T> safeSubList(List<T> list, int fromIndex, int toIndex) {
         int size = list.size();
         if (fromIndex >= size || toIndex <= 0 || fromIndex >= toIndex) {
             return Collections.emptyList();
@@ -305,30 +278,28 @@ public class LoanSchedularServiceImpl implements 
LoanSchedularService {
 
         return list.subList(fromIndex, toIndex);
     }
-    //checks the execution of task by each thread in the executor service
-    private void checkCompletion(List<Future<Object>> responses) {
+
+    // checks the execution of task by each thread in the executor service
+    private void checkCompletion(List<Future<Void>> responses) {
         try {
-            for(Future f : responses) {
+            for(Future<Void> f : responses) {
                 f.get();
             }
             boolean allThreadsExecuted = false;
             int noOfThreadsExecuted = 0;
-            for (Future<Object> future : responses) {
+            for (Future<Void> future : responses) {
                 if (future.isDone()) {
                     noOfThreadsExecuted++;
                 }
             }
             allThreadsExecuted = noOfThreadsExecuted == responses.size();
-            if(!allThreadsExecuted)
+            if(!allThreadsExecuted) {
                 logger.error("All threads could not execute.");
+            }
         } catch (InterruptedException e1) {
             logger.error("Interrupted while posting IR entries", e1);
         }  catch (ExecutionException e2) {
             logger.error("Execution exception while posting IR entries", e2);
         }
     }
-
-
-
-
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index d8bf85c..94cb93b 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -194,7 +194,7 @@ import 
org.springframework.transaction.annotation.Transactional;
 @Service
 public class LoanWritePlatformServiceJpaRepositoryImpl implements 
LoanWritePlatformService {
 
-    private final static Logger logger = 
LoggerFactory.getLogger(LoanWritePlatformServiceJpaRepositoryImpl.class);
+    private final static Logger LOG = 
LoggerFactory.getLogger(LoanWritePlatformServiceJpaRepositoryImpl.class);
 
     private final PlatformSecurityContext context;
     private final LoanEventApiJsonValidator loanEventApiJsonValidator;
@@ -393,11 +393,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                     throw new GeneralPlatformDomainRuleException(
                             
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
                             "Disbursal date of this loan application 
"+loan.getDisbursementDate()
-                                    +" should be after last transaction date 
of loan to be closed "+ lastUserTransactionOnLoanToClose);
+                            +" should be after last transaction date of loan 
to be closed "+ lastUserTransactionOnLoanToClose);
                 }
 
                 BigDecimal loanOutstanding = 
this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(loanIdToClose,
-                            actualDisbursementDate).getAmount();
+                        actualDisbursementDate).getAmount();
                 final BigDecimal firstDisbursalAmount = 
loan.getFirstDisbursalAmount();
                 if(loanOutstanding.compareTo(firstDisbursalAmount) > 0){
                     throw new 
GeneralPlatformDomainRuleException("error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
@@ -621,9 +621,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final LocalDate nextPossibleRepaymentDate = null;
         final Date rescheduledRepaymentDate = null;
 
-        for (int i = 0; i < disbursalCommand.length; i++) {
-            final SingleDisbursalCommand singleLoanDisbursalCommand = 
disbursalCommand[i];
-
+        for (final SingleDisbursalCommand singleLoanDisbursalCommand : 
disbursalCommand) {
             final Loan loan = 
this.loanAssembler.assembleFrom(singleLoanDisbursalCommand.getLoanId());
             final LocalDate actualDisbursementDate = 
command.localDateValueOfParameterNamed("actualDisbursementDate");
 
@@ -896,7 +894,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                 constructEntityMap(BUSINESS_ENTITY.LOAN_ADJUSTED_TRANSACTION, 
transactionToAdjust));
         if 
(this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, 
PortfolioAccountType.LOAN)) { throw new PlatformServiceUnavailableException(
                 "error.msg.loan.transfer.transaction.update.not.allowed", 
"Loan transaction:" + transactionId
-                        + " update not allowed as it involves in account 
transfer", transactionId); }
+                + " update not allowed as it involves in account transfer", 
transactionId); }
         if (loan.isClosedWrittenOff()) { throw new 
PlatformServiceUnavailableException("error.msg.loan.written.off.update.not.allowed",
                 "Loan transaction:" + transactionId + " update not allowed as 
loan status is written off", transactionId); }
 
@@ -995,7 +993,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
 
         if (!transactionIds.isEmpty()) {
             this.accountTransfersWritePlatformService
-                    
.reverseTransfersWithFromAccountTransactions(transactionIds, 
PortfolioAccountType.LOAN);
+            .reverseTransfersWithFromAccountTransactions(transactionIds, 
PortfolioAccountType.LOAN);
             loan.updateLoanSummarAndStatus();
         }
 
@@ -1008,14 +1006,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         }
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_ADJUST_TRANSACTION,
 entityMap);
 
-        return new CommandProcessingResultBuilder() //
-                .withCommandId(command.commandId()) //
-                .withEntityId(transactionId) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()) //
-                .withLoanId(loanId) //
-                .with(changes) //
+        return new CommandProcessingResultBuilder()
+                .withCommandId(command.commandId())
+                .withEntityId(transactionId)
+                .withOfficeId(loan.getOfficeId())
+                .withClientId(loan.getClientId())
+                .withGroupId(loan.getGroupId())
+                .withLoanId(loanId)
+                .with(changes)
                 .build();
     }
 
@@ -1095,14 +1093,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         this.loanAccountDomainService.recalculateAccruals(loan);
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_WAIVE_INTEREST,
                 constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, 
waiveInterestTransaction));
-        return new CommandProcessingResultBuilder() //
-                .withCommandId(command.commandId()) //
-                .withEntityId(waiveInterestTransaction.getId()) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()) //
-                .withLoanId(loanId) //
-                .with(changes) //
+        return new CommandProcessingResultBuilder()
+                .withCommandId(command.commandId())
+                .withEntityId(waiveInterestTransaction.getId())
+                .withOfficeId(loan.getOfficeId())
+                .withClientId(loan.getClientId())
+                .withGroupId(loan.getGroupId())
+                .withLoanId(loanId)
+                .with(changes)
                 .build();
     }
 
@@ -1165,14 +1163,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         this.loanAccountDomainService.recalculateAccruals(loan);
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_WRITTEN_OFF,
                 constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, 
writeoff));
-        return new CommandProcessingResultBuilder() //
-                .withCommandId(command.commandId()) //
-                .withEntityId(writeoff.getId()) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()) //
-                .withLoanId(loanId) //
-                .with(changes) //
+        return new CommandProcessingResultBuilder()
+                .withCommandId(command.commandId())
+                .withEntityId(writeoff.getId())
+                .withOfficeId(loan.getOfficeId())
+                .withClientId(loan.getClientId())
+                .withGroupId(loan.getGroupId())
+                .withLoanId(loanId)
+                .with(changes)
                 .build();
     }
 
@@ -1237,24 +1235,24 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         CommandProcessingResult result = null;
         if (possibleClosingTransaction != null) {
 
-            result = new CommandProcessingResultBuilder() //
-                    .withCommandId(command.commandId()) //
-                    .withEntityId(possibleClosingTransaction.getId()) //
-                    .withOfficeId(loan.getOfficeId()) //
-                    .withClientId(loan.getClientId()) //
-                    .withGroupId(loan.getGroupId()) //
-                    .withLoanId(loanId) //
-                    .with(changes) //
+            result = new CommandProcessingResultBuilder()
+                    .withCommandId(command.commandId())
+                    .withEntityId(possibleClosingTransaction.getId())
+                    .withOfficeId(loan.getOfficeId())
+                    .withClientId(loan.getClientId())
+                    .withGroupId(loan.getGroupId())
+                    .withLoanId(loanId)
+                    .with(changes)
                     .build();
         } else {
-            result = new CommandProcessingResultBuilder() //
-                    .withCommandId(command.commandId()) //
-                    .withEntityId(loanId) //
-                    .withOfficeId(loan.getOfficeId()) //
-                    .withClientId(loan.getClientId()) //
-                    .withGroupId(loan.getGroupId()) //
-                    .withLoanId(loanId) //
-                    .with(changes) //
+            result = new CommandProcessingResultBuilder()
+                    .withCommandId(command.commandId())
+                    .withEntityId(loanId)
+                    .withOfficeId(loan.getOfficeId())
+                    .withClientId(loan.getClientId())
+                    .withGroupId(loan.getGroupId())
+                    .withLoanId(loanId)
+                    .with(changes)
                     .build();
         }
 
@@ -1332,14 +1330,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final Charge chargeDefinition = 
this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
 
         if (loan.isDisbursed() && chargeDefinition.isDisbursementCharge()) {
-            validateAddingNewChargeAllowed(loanDisburseDetails); // validates
-                                                                 // whether any
-                                                                 // pending
-                                                                 // 
disbursements
-                                                                 // are
-                                                                 // available 
to
-                                                                 // apply this
-                                                                 // charge
+            // validates whether any pending disbursements are available to 
apply this charge
+            validateAddingNewChargeAllowed(loanDisburseDetails);
         }
         final List<Long> existingTransactionIds = new 
ArrayList<>(loan.findExistingTransactionIds());
         final List<Long> existingReversedTransactionIds = new 
ArrayList<>(loan.findExistingReversedTransactionIds());
@@ -1410,13 +1402,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         }
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_ADD_CHARGE,
                 constructEntityMap(BUSINESS_ENTITY.LOAN_CHARGE, loanCharge));
-        return new CommandProcessingResultBuilder() //
-                .withCommandId(command.commandId()) //
-                .withEntityId(loanCharge.getId()) //
-                .withOfficeId(loan.getOfficeId()) //
-                .withClientId(loan.getClientId()) //
-                .withGroupId(loan.getGroupId()) //
-                .withLoanId(loanId) //
+        return new CommandProcessingResultBuilder()
+                .withCommandId(command.commandId())
+                .withEntityId(loanCharge.getId())
+                .withOfficeId(loan.getOfficeId())
+                .withClientId(loan.getClientId())
+                .withGroupId(loan.getGroupId())
+                .withLoanId(loanId)
                 .build();
     }
 
@@ -1782,7 +1774,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final Collection<LoanChargeData> chargeDatas = 
this.loanChargeReadPlatformService.retrieveLoanChargesForFeePayment(
                 ChargePaymentMode.ACCOUNT_TRANSFER.getValue(), 
LoanStatus.ACTIVE.getValue());
         final boolean isRegularTransaction = true;
-        final StringBuilder sb = new StringBuilder();
+        int errors = 0;
         if (chargeDatas != null) {
             for (final LoanChargeData chargeData : chargeDatas) {
                 if (chargeData.isInstallmentFee()) {
@@ -1803,7 +1795,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                                     null, 
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
                                     
installmentChargeData.getInstallmentNumber(), 
AccountTransferType.CHARGE_PAYMENT.getValue(), null,
                                     null, null, null, null, 
fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
-                            transferFeeCharge(sb, accountTransferDTO);
+                            if (!transferFeeCharge(accountTransferDTO)) {
+                                ++errors;
+                            }
                         }
                     }
                 } else if (chargeData.getDueDate() != null && 
!chargeData.getDueDate().isAfter(DateUtils.getLocalDateOfTenant())) {
@@ -1817,27 +1811,25 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                             LoanTransactionType.CHARGE_PAYMENT.getValue(), 
chargeData.getId(), null,
                             AccountTransferType.CHARGE_PAYMENT.getValue(), 
null, null, null, null, null, fromSavingsAccount,
                             isRegularTransaction, isExceptionForBalanceCheck);
-                    transferFeeCharge(sb, accountTransferDTO);
+                    if (!transferFeeCharge(accountTransferDTO)) {
+                        ++errors;
+                    }
                 }
             }
         }
-        if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); 
}
+        if (errors > 0) { throw new JobExecutionException(errors); }
     }
 
-    /**
-     * @param sb
-     * @param accountTransferDTO
-     */
-    private void transferFeeCharge(final StringBuilder sb, final 
AccountTransferDTO accountTransferDTO) {
+    private boolean transferFeeCharge(final AccountTransferDTO 
accountTransferDTO) {
         try {
             
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
+            return true;
         } catch (final PlatformApiDataValidationException e) {
-            sb.append("Validation exception while paying charge 
").append(accountTransferDTO.getChargeId()).append(" for loan id:")
-                    
.append(accountTransferDTO.getToAccountId()).append("--------");
+            LOG.error("Validation exception while paying charge {} for loan id 
{}", accountTransferDTO.getChargeId(), accountTransferDTO.getToAccountId(), e);
+            return false;
         } catch (final InsufficientAccountBalanceException e) {
-            sb.append("InsufficientAccountBalance Exception while paying 
charge ").append(accountTransferDTO.getChargeId())
-                    .append("for loan 
id:").append(accountTransferDTO.getToAccountId()).append("--------");
-
+            LOG.error("InsufficientAccountBalanceException while paying charge 
{} for loan id {}", accountTransferDTO.getChargeId(), 
accountTransferDTO.getToAccountId(), e);
+            return false;
         }
     }
 
@@ -2517,7 +2509,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
         if (!loan.isClosedWrittenOff()) { throw new 
PlatformServiceUnavailableException(
                 "error.msg.loan.status.not.written.off.update.not.allowed", 
"Loan :" + loanId
-                        + " update not allowed as loan status is not written 
off", loanId); }
+                + " update not allowed as loan status is not written off", 
loanId); }
         LocalDate recalculateFrom = null;
         LoanTransaction writeOffTransaction = loan.findWriteOffTransaction();
         
this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_UNDO_WRITTEN_OFF,
@@ -2883,7 +2875,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         BigDecimal overpaid = 
this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId).getPaidInAdvance();
 
         if (overpaid == null || overpaid.equals(new BigDecimal(0)) || 
transactionAmount.floatValue() > overpaid.floatValue()) {
-            if (overpaid == null) overpaid = BigDecimal.ZERO;
+            if (overpaid == null) {
+                overpaid = BigDecimal.ZERO;
+            }
             throw new 
InvalidPaidInAdvanceAmountException(overpaid.toPlainString());
         }
     }
@@ -3005,12 +2999,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     }
 
     private void syncExpectedDateWithActualDisbursementDate(final Loan loan, 
LocalDate actualDisbursementDate){
-           
if(!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)){
-               throw new DateMismatchException(actualDisbursementDate,
-                       loan.getExpectedDisbursedOnLocalDate());
-           }
+        
if(!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)){
+            throw new DateMismatchException(actualDisbursementDate,
+                    loan.getExpectedDisbursedOnLocalDate());
+        }
 
-       }
+    }
 
     private void validateTransactionsForTransfer(final Loan loan, final 
LocalDate transferDate) {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
index f3dfab8..b084c60 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.util.Collection;
 import java.util.Random;
+import java.util.concurrent.Callable;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
 import org.slf4j.Logger;
@@ -29,41 +30,25 @@ import org.springframework.dao.CannotAcquireLockException;
 import org.springframework.orm.ObjectOptimisticLockingFailureException;
 import org.springframework.stereotype.Component;
 
-
 @Component
-
 @Scope("prototype")
+public class RecalculateInterestPoster implements Callable<Void> {
 
-public class RecalculateInterestPoster implements Runnable {
-
-
-
-    private final static Logger logger = LoggerFactory.getLogger(" recalculate 
interest poster");
+    private final static Logger logger = 
LoggerFactory.getLogger(RecalculateInterestPoster.class);
 
     private Collection<Long> loanIds;
-
     private LoanWritePlatformService loanWritePlatformService;
 
-
     public void setLoanIds(final Collection<Long> loanIds) {
-
         this.loanIds = loanIds;
-
     }
 
-
-
     public void setLoanWritePlatformService(final LoanWritePlatformService 
loanWritePlatformService) {
-
         this.loanWritePlatformService = loanWritePlatformService;
-
     }
 
-
-
     @Override
-    public void run() {
-
+    public Void call() throws JobExecutionException {
         Integer maxNumberOfRetries = ThreadLocalContextUtil.getTenant()
                 .getConnection().getMaxRetriesOnDeadlock();
         Integer maxIntervalBetweenRetries = ThreadLocalContextUtil.getTenant()
@@ -71,72 +56,45 @@ public class RecalculateInterestPoster implements Runnable {
 
         int i = 0;
         if (!loanIds.isEmpty()) {
-            final StringBuilder sb = new StringBuilder();
+            int errors = 0;
             for (Long loanId : loanIds) {
                 logger.info("Loan ID " + loanId);
                 Integer numberOfRetries = 0;
                 while (numberOfRetries <= maxNumberOfRetries) {
                     try {
-                        this.loanWritePlatformService
-                                .recalculateInterest(loanId);
+                        
this.loanWritePlatformService.recalculateInterest(loanId);
                         numberOfRetries = maxNumberOfRetries + 1;
                     } catch (CannotAcquireLockException
                             | ObjectOptimisticLockingFailureException 
exception) {
-                        logger.info("Recalulate interest job has been retried  
"
-                                + numberOfRetries + " time(s)");
-                        /***
-                         * Fail if the transaction has been retired for
-                         * maxNumberOfRetries
-                         **/
+                        logger.info("Recalulate interest job has been retried 
time(s)", numberOfRetries);
+                        // Fail if the transaction has been retired for 
maxNumberOfRetries
                         if (numberOfRetries >= maxNumberOfRetries) {
-                            logger.warn("Recalulate interest job has been 
retried for the max allowed attempts of "
-                                    + numberOfRetries
-                                    + " and will be rolled back");
-                            sb.append("Recalulate interest job has been 
retried for the max allowed attempts of "
-                                    + numberOfRetries
-                                    + " and will be rolled back");
+                            logger.error("Recalulate interest job has been 
retried for the max allowed attempts of {} and will be rolled back", 
numberOfRetries);
+                            ++errors;
                             break;
                         }
-                        /***
-                         * Else sleep for a random time (between 1 to 10
-                         * seconds) and continue
-                         **/
+                        // Else sleep for a random time (between 1 to 10 
seconds) and continue
                         try {
                             Random random = new Random();
-                            int randomNum = random
-                                    .nextInt(maxIntervalBetweenRetries + 1);
+                            int randomNum = 
random.nextInt(maxIntervalBetweenRetries + 1);
                             Thread.sleep(1000 + (randomNum * 1000));
                             numberOfRetries = numberOfRetries + 1;
                         } catch (InterruptedException e) {
-                            sb.append("Interest recalculation for loans failed 
" + exception.getMessage()) ;
+                            logger.error("Interest recalculation for loans 
retry failed due to InterruptedException", e) ;
+                            ++errors;
                             break;
                         }
                     } catch (Exception e) {
-                        Throwable realCause = e;
-                        if (e.getCause() != null) {
-                            realCause = e.getCause();
-                        }
-                        logger.error("Interest recalculation for loans failed 
for account:"    + loanId + " with message " + realCause.getMessage(), e);
-                        sb.append("Interest recalculation for loans failed for 
account:").append(loanId).append(" with message ")
-                                .append(realCause.getMessage());
+                        logger.error("Interest recalculation for loans failed 
for account {}", loanId, e);
                         numberOfRetries = maxNumberOfRetries + 1;
+                        ++errors;
                     }
                     i++;
                 }
                 logger.info("Loans count " + i);
             }
-            if (sb.length() > 0) {
-                try {
-                    throw new JobExecutionException(sb.toString());
-                } catch (JobExecutionException e) {
-                    logger.info("JobExecutionException occured :", e);
-                }
-            }
+            if (errors > 0) { throw new JobExecutionException(errors); }
         }
-
-
+        return null;
     }
-
-
-
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
index 23841e2..d5c23eb 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -112,6 +112,8 @@ import 
org.apache.fineract.useradministration.domain.AppUser;
 import org.joda.time.LocalDate;
 import org.joda.time.format.DateTimeFormat;
 import org.joda.time.format.DateTimeFormatter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -119,6 +121,8 @@ import 
org.springframework.transaction.annotation.Transactional;
 @Service
 public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements 
DepositAccountWritePlatformService {
 
+    private final static Logger LOG = 
LoggerFactory.getLogger(DepositAccountWritePlatformServiceJpaRepositoryImpl.class);
+
     private final PlatformSecurityContext context;
     private final SavingsAccountRepositoryWrapper 
savingAccountRepositoryWrapper;
     private final SavingsAccountTransactionRepository 
savingsAccountTransactionRepository;
@@ -571,21 +575,20 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
     @Override
     @CronTarget(jobName = JobName.TRANSFER_INTEREST_TO_SAVINGS)
     public void transferInterestToSavings() throws JobExecutionException {
+        int errors = 0;
         Collection<AccountTransferDTO> accountTrasferData = 
this.depositAccountReadPlatformService.retrieveDataForInterestTransfer();
-        StringBuilder sb = new StringBuilder(200);
         for (AccountTransferDTO accountTransferDTO : accountTrasferData) {
             try {
                 
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
             } catch (final PlatformApiDataValidationException e) {
-                sb.append("Validation exception while trasfering Interest form 
").append(accountTransferDTO.getFromAccountId())
-                        .append(" to 
").append(accountTransferDTO.getToAccountId()).append("--------");
+                LOG.error("Validation exception while trasfering Interest from 
{} to {}", accountTransferDTO.getFromAccountId(), 
accountTransferDTO.getToAccountId(), e);
+                ++errors;
             } catch (final InsufficientAccountBalanceException e) {
-                sb.append("InsufficientAccountBalance Exception while 
trasfering Interest form ")
-                        
.append(accountTransferDTO.getFromAccountId()).append(" to 
").append(accountTransferDTO.getToAccountId())
-                        .append("--------");
+                LOG.error("InsufficientAccountBalanceException while 
trasfering Interest from {} to {} ", accountTransferDTO.getFromAccountId(), 
accountTransferDTO.getToAccountId(), e);
+                ++errors;
             }
         }
-        if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); 
}
+        if (errors > 0) { throw new JobExecutionException(errors); }
     }
 
     @Override
@@ -615,8 +618,8 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
 
         if (!allowAccountTransferModification
                 && 
this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, 
PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException(
-                
"error.msg.recurring.deposit.account.transfer.transaction.update.not.allowed", 
"Recurring deposit account transaction:"
-                        + transactionId + " update not allowed as it involves 
in account transfer", transactionId); }
+                        
"error.msg.recurring.deposit.account.transfer.transaction.update.not.allowed", 
"Recurring deposit account transaction:"
+                                + transactionId + " update not allowed as it 
involves in account transfer", transactionId); }
 
         final LocalDate today = DateUtils.getLocalDateOfTenant();
         final MathContext mc = MathContext.DECIMAL64;
@@ -689,12 +692,12 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
                 .findOneByIdAndSavingsAccountId(transactionId, savingsId);
         if (savingsAccountTransaction == null) { throw new 
SavingsAccountTransactionNotFoundException(savingsId, transactionId); }
 
-        if (!(savingsAccountTransaction.isDeposit() || 
savingsAccountTransaction.isWithdrawal()) || 
savingsAccountTransaction.isReversed()) { throw new 
TransactionUpdateNotAllowedException(
+        if ((!savingsAccountTransaction.isDeposit() && 
!savingsAccountTransaction.isWithdrawal()) || 
savingsAccountTransaction.isReversed()) { throw new 
TransactionUpdateNotAllowedException(
                 savingsId, transactionId); }
 
         if 
(this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, 
PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException(
                 
"error.msg.saving.account.transfer.transaction.update.not.allowed", "Deposit 
account transaction:" + transactionId
-                        + " update not allowed as it involves in account 
transfer", transactionId); }
+                + " update not allowed as it involves in account transfer", 
transactionId); }
 
         final LocalDate today = DateUtils.getLocalDateOfTenant();
 
@@ -1071,14 +1074,14 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
             if 
(!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
                     && 
this.holidayRepository.isHoliday(savingsAccount.officeId(), 
savingsAccountCharge.getDueLocalDate())) {
                 
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-                        
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
+                
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
                 if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
             }
 
             if 
(!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled()
                     && 
!this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate()))
 {
                 
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-                        
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
+                
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
                 if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
             }
         }
@@ -1126,14 +1129,14 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
             if 
(!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
                     && 
this.holidayRepository.isHoliday(savingsAccount.officeId(), 
savingsAccountCharge.getDueLocalDate())) {
                 
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-                        
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
+                
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
                 if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
             }
 
             if 
(!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled()
                     && 
!this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate()))
 {
                 
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-                        
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
+                
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
                 if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
             }
         }
@@ -1253,14 +1256,14 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         if 
(!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
                 && 
this.holidayRepository.isHoliday(savingsAccountCharge.savingsAccount().officeId(),
 transactionDate)) {
             
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate.toString(fmt))
-                    
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.on.holiday");
+            
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.on.holiday");
             if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
         }
 
         if 
(!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled()
                 && !this.workingDaysRepository.isWorkingDay(transactionDate)) {
             
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate.toString(fmt))
-                    
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.a.nonworking.day");
+            
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.a.nonworking.day");
             if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
         }
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
index 6b624f1..0e3cc7f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.portfolio.savings.service;
 
+import static 
org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType.ACTIVE;
+
 import java.util.List;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
@@ -26,8 +28,9 @@ import 
org.apache.fineract.infrastructure.jobs.service.JobName;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
 import 
org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
-import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
 import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -36,6 +39,8 @@ import org.springframework.stereotype.Service;
 @Service
 public class SavingsSchedularServiceImpl implements SavingsSchedularService {
 
+    private final static Logger LOG = 
LoggerFactory.getLogger(SavingsSchedularServiceImpl.class);
+
     private final SavingsAccountAssembler savingAccountAssembler;
     private final SavingsAccountWritePlatformService 
savingsAccountWritePlatformService;
     private final SavingsAccountReadPlatformService 
savingAccountReadPlatformService;
@@ -51,63 +56,54 @@ public class SavingsSchedularServiceImpl implements 
SavingsSchedularService {
         this.savingsAccountRepository = savingsAccountRepository;
     }
 
-    @CronTarget(jobName = JobName.POST_INTEREST_FOR_SAVINGS)
     @Override
+    @CronTarget(jobName = JobName.POST_INTEREST_FOR_SAVINGS)
     public void postInterestForAccounts() throws JobExecutionException {
         int page = 0;
         Integer initialSize = 500;
         Integer totalPageSize = 0;
-        StringBuffer sb = new StringBuffer();
+        int errors = 0;
         do {
             PageRequest pageRequest = PageRequest.of(page, initialSize);
-            Page<SavingsAccount> savingsAccounts = 
this.savingsAccountRepository.findByStatus(SavingsAccountStatusType.ACTIVE.getValue(),
-                    pageRequest);
+            Page<SavingsAccount> savingsAccounts = 
this.savingsAccountRepository.findByStatus(ACTIVE.getValue(), pageRequest);
             for (SavingsAccount savingsAccount : savingsAccounts.getContent()) 
{
                 try {
                     
this.savingAccountAssembler.assignSavingAccountHelpers(savingsAccount);
                     boolean postInterestAsOn = false;
                     LocalDate transactionDate = null;
-                    
this.savingsAccountWritePlatformService.postInterest(savingsAccount, 
postInterestAsOn,
-                            transactionDate);
+                    
this.savingsAccountWritePlatformService.postInterest(savingsAccount, 
postInterestAsOn, transactionDate);
                 } catch (Exception e) {
-                    Throwable realCause = e;
-                    if (e.getCause() != null) {
-                        realCause = e.getCause();
-                    }
-                    sb.append("failed to post interest for Savings with id " + 
savingsAccount.getId() + " with message "
-                            + realCause.getMessage());
+                    LOG.error("Failed to post interest for Savings with id 
{}", savingsAccount.getId(), e);
+                    ++errors;
                 }
             }
             page++;
             totalPageSize = savingsAccounts.getTotalPages();
         } while (page < totalPageSize);
 
-        if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); 
}
+        if (errors > 0) { throw new JobExecutionException(errors); }
     }
 
-    @CronTarget(jobName = JobName.UPDATE_SAVINGS_DORMANT_ACCOUNTS)
     @Override
+    @CronTarget(jobName = JobName.UPDATE_SAVINGS_DORMANT_ACCOUNTS)
     public void updateSavingsDormancyStatus() throws JobExecutionException {
-        final LocalDate tenantLocalDate = DateUtils.getLocalDateOfTenant();
+        LocalDate tenantLocalDate = DateUtils.getLocalDateOfTenant();
 
-        final List<Long> savingsPendingInactive = 
this.savingAccountReadPlatformService
-                                                        
.retrieveSavingsIdsPendingInactive(tenantLocalDate);
+        List<Long> savingsPendingInactive = 
savingAccountReadPlatformService.retrieveSavingsIdsPendingInactive(tenantLocalDate);
         if(null != savingsPendingInactive && savingsPendingInactive.size() > 
0){
             for(Long savingsId : savingsPendingInactive){
                 
this.savingsAccountWritePlatformService.setSubStatusInactive(savingsId);
             }
         }
 
-        final List<Long> savingsPendingDormant = 
this.savingAccountReadPlatformService
-                .retrieveSavingsIdsPendingDormant(tenantLocalDate);
+        List<Long> savingsPendingDormant = 
savingAccountReadPlatformService.retrieveSavingsIdsPendingDormant(tenantLocalDate);
         if(null != savingsPendingDormant && savingsPendingDormant.size() > 0){
             for(Long savingsId : savingsPendingDormant){
                 
this.savingsAccountWritePlatformService.setSubStatusDormant(savingsId);
             }
         }
 
-        final List<Long> savingsPendingEscheat = 
this.savingAccountReadPlatformService
-                .retrieveSavingsIdsPendingEscheat(tenantLocalDate);
+        List<Long> savingsPendingEscheat = 
savingAccountReadPlatformService.retrieveSavingsIdsPendingEscheat(tenantLocalDate);
         if(null != savingsPendingEscheat && savingsPendingEscheat.size() > 0){
             for(Long savingsId : savingsPendingEscheat){
                 this.savingsAccountWritePlatformService.escheat(savingsId);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
index 036ab7b..3f9f60d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
@@ -62,6 +62,7 @@ import org.springframework.util.CollectionUtils;
 public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService {
 
     private final static Logger logger = 
LoggerFactory.getLogger(ScheduledJobRunnerServiceImpl.class);
+
     private final DateTimeFormatter formatter = 
DateTimeFormat.forPattern("yyyy-MM-dd");
     private final DateTimeFormatter formatterWithTime = 
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
 
@@ -111,9 +112,9 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
         updateSqlBuilder.append("SUM(IFNULL(mr.interest_waived_derived,0)) as 
interest_waived_derived,");
         updateSqlBuilder.append("SUM(IFNULL(mr.interest_writtenoff_derived,0)) 
as interest_writtenoff_derived,");
         updateSqlBuilder
-                .append("SUM(IFNULL(mr.fee_charges_amount,0)) + IFNULL((select 
SUM(lc.amount) from  m_loan_charge lc where lc.loan_id=ml.id and lc.is_active=1 
and lc.charge_time_enum=1),0) as fee_charges_charged_derived,");
+        .append("SUM(IFNULL(mr.fee_charges_amount,0)) + IFNULL((select 
SUM(lc.amount) from  m_loan_charge lc where lc.loan_id=ml.id and lc.is_active=1 
and lc.charge_time_enum=1),0) as fee_charges_charged_derived,");
         updateSqlBuilder
-                .append("SUM(IFNULL(mr.fee_charges_completed_derived,0)) + 
IFNULL((select SUM(lc.amount_paid_derived) from  m_loan_charge lc where 
lc.loan_id=ml.id and lc.is_active=1 and lc.charge_time_enum=1),0) as 
fee_charges_repaid_derived,");
+        .append("SUM(IFNULL(mr.fee_charges_completed_derived,0)) + 
IFNULL((select SUM(lc.amount_paid_derived) from  m_loan_charge lc where 
lc.loan_id=ml.id and lc.is_active=1 and lc.charge_time_enum=1),0) as 
fee_charges_repaid_derived,");
         updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_waived_derived,0)) 
as fee_charges_waived_derived,");
         
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_writtenoff_derived,0)) as 
fee_charges_writtenoff_derived,");
         updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_amount,0)) as 
penalty_charges_charged_derived,");
@@ -130,45 +131,45 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
         updateSqlBuilder.append("m_loan.principal_repaid_derived = 
x.principal_repaid_derived,");
         updateSqlBuilder.append("m_loan.principal_writtenoff_derived = 
x.principal_writtenoff_derived,");
         updateSqlBuilder
-                .append("m_loan.principal_outstanding_derived = 
(x.principal_disbursed_derived - (x.principal_repaid_derived + 
x.principal_writtenoff_derived)),");
+        .append("m_loan.principal_outstanding_derived = 
(x.principal_disbursed_derived - (x.principal_repaid_derived + 
x.principal_writtenoff_derived)),");
         updateSqlBuilder.append("m_loan.interest_charged_derived = 
x.interest_charged_derived,");
         updateSqlBuilder.append("m_loan.interest_repaid_derived = 
x.interest_repaid_derived,");
         updateSqlBuilder.append("m_loan.interest_waived_derived = 
x.interest_waived_derived,");
         updateSqlBuilder.append("m_loan.interest_writtenoff_derived = 
x.interest_writtenoff_derived,");
         updateSqlBuilder
-                .append("m_loan.interest_outstanding_derived = 
(x.interest_charged_derived - (x.interest_repaid_derived + 
x.interest_waived_derived + x.interest_writtenoff_derived)),");
+        .append("m_loan.interest_outstanding_derived = 
(x.interest_charged_derived - (x.interest_repaid_derived + 
x.interest_waived_derived + x.interest_writtenoff_derived)),");
         updateSqlBuilder.append("m_loan.fee_charges_charged_derived = 
x.fee_charges_charged_derived,");
         updateSqlBuilder.append("m_loan.fee_charges_repaid_derived = 
x.fee_charges_repaid_derived,");
         updateSqlBuilder.append("m_loan.fee_charges_waived_derived = 
x.fee_charges_waived_derived,");
         updateSqlBuilder.append("m_loan.fee_charges_writtenoff_derived = 
x.fee_charges_writtenoff_derived,");
         updateSqlBuilder
-                .append("m_loan.fee_charges_outstanding_derived = 
(x.fee_charges_charged_derived - (x.fee_charges_repaid_derived + 
x.fee_charges_waived_derived + x.fee_charges_writtenoff_derived)),");
+        .append("m_loan.fee_charges_outstanding_derived = 
(x.fee_charges_charged_derived - (x.fee_charges_repaid_derived + 
x.fee_charges_waived_derived + x.fee_charges_writtenoff_derived)),");
         updateSqlBuilder.append("m_loan.penalty_charges_charged_derived = 
x.penalty_charges_charged_derived,");
         updateSqlBuilder.append("m_loan.penalty_charges_repaid_derived = 
x.penalty_charges_repaid_derived,");
         updateSqlBuilder.append("m_loan.penalty_charges_waived_derived = 
x.penalty_charges_waived_derived,");
         updateSqlBuilder.append("m_loan.penalty_charges_writtenoff_derived = 
x.penalty_charges_writtenoff_derived,");
         updateSqlBuilder
-                .append("m_loan.penalty_charges_outstanding_derived = 
(x.penalty_charges_charged_derived - (x.penalty_charges_repaid_derived + 
x.penalty_charges_waived_derived + x.penalty_charges_writtenoff_derived)),");
+        .append("m_loan.penalty_charges_outstanding_derived = 
(x.penalty_charges_charged_derived - (x.penalty_charges_repaid_derived + 
x.penalty_charges_waived_derived + x.penalty_charges_writtenoff_derived)),");
         updateSqlBuilder
-                .append("m_loan.total_expected_repayment_derived = 
(x.principal_disbursed_derived + x.interest_charged_derived + 
x.fee_charges_charged_derived + x.penalty_charges_charged_derived),");
+        .append("m_loan.total_expected_repayment_derived = 
(x.principal_disbursed_derived + x.interest_charged_derived + 
x.fee_charges_charged_derived + x.penalty_charges_charged_derived),");
         updateSqlBuilder
-                .append("m_loan.total_repayment_derived = 
(x.principal_repaid_derived + x.interest_repaid_derived + 
x.fee_charges_repaid_derived + x.penalty_charges_repaid_derived),");
+        .append("m_loan.total_repayment_derived = (x.principal_repaid_derived 
+ x.interest_repaid_derived + x.fee_charges_repaid_derived + 
x.penalty_charges_repaid_derived),");
         updateSqlBuilder
-                .append("m_loan.total_expected_costofloan_derived = 
(x.interest_charged_derived + x.fee_charges_charged_derived + 
x.penalty_charges_charged_derived),");
+        .append("m_loan.total_expected_costofloan_derived = 
(x.interest_charged_derived + x.fee_charges_charged_derived + 
x.penalty_charges_charged_derived),");
         updateSqlBuilder
-                .append("m_loan.total_costofloan_derived = 
(x.interest_repaid_derived + x.fee_charges_repaid_derived + 
x.penalty_charges_repaid_derived),");
+        .append("m_loan.total_costofloan_derived = (x.interest_repaid_derived 
+ x.fee_charges_repaid_derived + x.penalty_charges_repaid_derived),");
         updateSqlBuilder
-                .append("m_loan.total_waived_derived = 
(x.interest_waived_derived + x.fee_charges_waived_derived + 
x.penalty_charges_waived_derived),");
+        .append("m_loan.total_waived_derived = (x.interest_waived_derived + 
x.fee_charges_waived_derived + x.penalty_charges_waived_derived),");
         updateSqlBuilder
-                .append("m_loan.total_writtenoff_derived = 
(x.interest_writtenoff_derived +  x.fee_charges_writtenoff_derived + 
x.penalty_charges_writtenoff_derived),");
+        .append("m_loan.total_writtenoff_derived = 
(x.interest_writtenoff_derived +  x.fee_charges_writtenoff_derived + 
x.penalty_charges_writtenoff_derived),");
         updateSqlBuilder.append("m_loan.total_outstanding_derived=");
         updateSqlBuilder.append(" (x.principal_disbursed_derived - 
(x.principal_repaid_derived + x.principal_writtenoff_derived)) + ");
         updateSqlBuilder
-                .append(" (x.interest_charged_derived - 
(x.interest_repaid_derived + x.interest_waived_derived + 
x.interest_writtenoff_derived)) +");
+        .append(" (x.interest_charged_derived - (x.interest_repaid_derived + 
x.interest_waived_derived + x.interest_writtenoff_derived)) +");
         updateSqlBuilder
-                .append(" (x.fee_charges_charged_derived - 
(x.fee_charges_repaid_derived + x.fee_charges_waived_derived + 
x.fee_charges_writtenoff_derived)) +");
+        .append(" (x.fee_charges_charged_derived - 
(x.fee_charges_repaid_derived + x.fee_charges_waived_derived + 
x.fee_charges_writtenoff_derived)) +");
         updateSqlBuilder
-                .append(" (x.penalty_charges_charged_derived - 
(x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived + 
x.penalty_charges_writtenoff_derived))");
+        .append(" (x.penalty_charges_charged_derived - 
(x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived + 
x.penalty_charges_writtenoff_derived))");
 
         final int result = jdbcTemplate.update(updateSqlBuilder.toString());
 
@@ -187,23 +188,23 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
         final StringBuilder updateSqlBuilder = new StringBuilder(900);
 
         updateSqlBuilder
-                .append("INSERT INTO m_loan_paid_in_advance(loan_id, 
principal_in_advance_derived, interest_in_advance_derived, 
fee_charges_in_advance_derived, penalty_charges_in_advance_derived, 
total_in_advance_derived)");
+        .append("INSERT INTO m_loan_paid_in_advance(loan_id, 
principal_in_advance_derived, interest_in_advance_derived, 
fee_charges_in_advance_derived, penalty_charges_in_advance_derived, 
total_in_advance_derived)");
         updateSqlBuilder.append(" select ml.id as loanId,");
         updateSqlBuilder.append(" SUM(ifnull(mr.principal_completed_derived, 
0)) as principal_in_advance_derived,");
         updateSqlBuilder.append(" SUM(ifnull(mr.interest_completed_derived, 
0)) as interest_in_advance_derived,");
         updateSqlBuilder.append(" SUM(ifnull(mr.fee_charges_completed_derived, 
0)) as fee_charges_in_advance_derived,");
         updateSqlBuilder.append(" 
SUM(ifnull(mr.penalty_charges_completed_derived, 0)) as 
penalty_charges_in_advance_derived,");
         updateSqlBuilder
-                .append(" (SUM(ifnull(mr.principal_completed_derived, 0)) + 
SUM(ifnull(mr.interest_completed_derived, 0)) + 
SUM(ifnull(mr.fee_charges_completed_derived, 0)) + 
SUM(ifnull(mr.penalty_charges_completed_derived, 0))) as 
total_in_advance_derived");
+        .append(" (SUM(ifnull(mr.principal_completed_derived, 0)) + 
SUM(ifnull(mr.interest_completed_derived, 0)) + 
SUM(ifnull(mr.fee_charges_completed_derived, 0)) + 
SUM(ifnull(mr.penalty_charges_completed_derived, 0))) as 
total_in_advance_derived");
         updateSqlBuilder.append(" FROM m_loan ml ");
         updateSqlBuilder.append(" INNER JOIN m_loan_repayment_schedule mr on 
mr.loan_id = ml.id ");
         updateSqlBuilder.append(" WHERE ml.loan_status_id = 300 ");
         updateSqlBuilder.append(" and mr.duedate >= CURDATE() ");
         updateSqlBuilder.append(" GROUP BY ml.id");
         updateSqlBuilder
-                .append(" HAVING (SUM(ifnull(mr.principal_completed_derived, 
0)) + SUM(ifnull(mr.interest_completed_derived, 0)) +");
+        .append(" HAVING (SUM(ifnull(mr.principal_completed_derived, 0)) + 
SUM(ifnull(mr.interest_completed_derived, 0)) +");
         updateSqlBuilder
-                .append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) + 
SUM(ifnull(mr.penalty_charges_completed_derived, 0))) > 0.0");
+        .append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) + 
SUM(ifnull(mr.penalty_charges_completed_derived, 0))) > 0.0");
 
         final int result = jdbcTemplate.update(updateSqlBuilder.toString());
 
@@ -238,31 +239,21 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
     @Override
     @CronTarget(jobName = JobName.PAY_DUE_SAVINGS_CHARGES)
     public void applyDueChargesForSavings() throws JobExecutionException {
-        final Collection<SavingsAccountAnnualFeeData> chargesDueData = 
this.savingsAccountChargeReadPlatformService
-                .retrieveChargesWithDue();
-        final StringBuilder errorMsg = new StringBuilder();
-
+        final Collection<SavingsAccountAnnualFeeData> chargesDueData = 
this.savingsAccountChargeReadPlatformService.retrieveChargesWithDue();
+        int numberOfErrors = 0;
         for (final SavingsAccountAnnualFeeData savingsAccountReference : 
chargesDueData) {
             try {
-                
this.savingsAccountWritePlatformService.applyChargeDue(savingsAccountReference.getId(),
-                        savingsAccountReference.getAccountId());
+                
this.savingsAccountWritePlatformService.applyChargeDue(savingsAccountReference.getId(),
 savingsAccountReference.getAccountId());
             } catch (final PlatformApiDataValidationException e) {
                 final List<ApiParameterError> errors = e.getErrors();
                 for (final ApiParameterError error : errors) {
-                    logger.error("Apply Charges due for savings failed for 
account:" + savingsAccountReference.getAccountNo()
-                            + " with message " + error.getDeveloperMessage());
-                    errorMsg.append("Apply Charges due for savings failed for 
account:").append(savingsAccountReference.getAccountNo())
-                            .append(" with message 
").append(error.getDeveloperMessage());
+                    logger.error("Apply Charges due for savings failed for 
account {} with message: {}", savingsAccountReference.getAccountNo(), 
error.getDeveloperMessage(), e);
+                    ++numberOfErrors;
                 }
             }
         }
-
-        logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Savings 
accounts affected by update: " + chargesDueData.size());
-
-        /*
-         * throw exception if any charge payment fails.
-         */
-        if (errorMsg.length() > 0) { throw new 
JobExecutionException(errorMsg.toString()); }
+        logger.info("{}: Savings accounts affected by update: {}", 
ThreadLocalContextUtil.getTenant().getName(), chargesDueData.size());
+        if (numberOfErrors > 0) { throw new 
JobExecutionException(numberOfErrors); }
     }
 
     @Transactional
@@ -279,7 +270,7 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
         resetNPASqlBuilder.append("set loan.is_npa = 0 ");
         resetNPASqlBuilder.append("where  loan.loan_status_id = 300 and 
mpl.account_moves_out_of_npa_only_on_arrears_completion = 0 ");
         resetNPASqlBuilder
-                .append("or 
(mpl.account_moves_out_of_npa_only_on_arrears_completion = 1 and 
laa.overdue_since_date_derived is null)");
+        .append("or (mpl.account_moves_out_of_npa_only_on_arrears_completion = 
1 and laa.overdue_since_date_derived is null)");
 
         jdbcTemplate.update(resetNPASqlBuilder.toString());
 
@@ -383,65 +374,62 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
     @Override
     @CronTarget(jobName = JobName.POST_DIVIDENTS_FOR_SHARES)
     public void postDividends() throws JobExecutionException {
+        int numberOfErrors = 0;
         List<Map<String, Object>> dividendDetails = 
this.shareAccountDividendReadPlatformService.retriveDividendDetailsForPostDividents();
-        StringBuilder errorMsg = new StringBuilder();
         for (Map<String, Object> dividendMap : dividendDetails) {
             Long id = null ;
             Long savingsId = null ;
-            if(dividendMap.get("id") instanceof BigInteger) { //Drizzle is 
returning BigInteger
-                id = ((BigInteger)dividendMap.get("id")).longValue() ;
-                savingsId = 
((BigInteger)dividendMap.get("savingsAccountId")).longValue() ;
-            }else { //MySQL connector is returning Long
-                id = (Long) dividendMap.get("id") ;
-                savingsId = (Long) dividendMap.get("savingsAccountId") ;
+            if (dividendMap.get("id") instanceof BigInteger) {
+                // Drizzle is returningBigInteger
+                id = ((BigInteger) dividendMap.get("id")).longValue();
+                savingsId = ((BigInteger) 
dividendMap.get("savingsAccountId")).longValue();
+            } else { // MySQL connector is returning Long
+                id = (Long) dividendMap.get("id");
+                savingsId = (Long) dividendMap.get("savingsAccountId");
             }
             try {
                 this.shareAccountSchedularService.postDividend(id, savingsId);
             } catch (final PlatformApiDataValidationException e) {
                 final List<ApiParameterError> errors = e.getErrors();
                 for (final ApiParameterError error : errors) {
-                    logger.error("Post Dividends to savings failed for 
Divident detail Id:" + id + " and savings Id: " + savingsId
-                            + " with message " + error.getDeveloperMessage());
-                    errorMsg.append("Post Dividends to savings failed for 
Divident detail Id:").append(id).append(" and savings Id:")
-                            .append(savingsId).append(" with message 
").append(error.getDeveloperMessage());
+                    logger.error("Post Dividends to savings failed due to 
ApiParameterError for Divident detail Id: {} and savings Id: {} with message: 
", id, savingsId, error.getDeveloperMessage(), e);
+                    ++numberOfErrors;
                 }
             } catch (final Exception e) {
-                logger.error("Post Dividends to savings failed for Divident 
detail Id:" + id + " and savings Id: " + savingsId
-                        + " with message " + e.getLocalizedMessage());
-                errorMsg.append("Post Dividends to savings failed for Divident 
detail Id:").append(id).append(" and savings Id:")
-                        .append(savingsId).append(" with message 
").append(e.getLocalizedMessage());
+                logger.error("Post Dividends to savings failed for Divident 
detail Id: {} and savings Id: {}", id, savingsId, e);
+                ++numberOfErrors;
             }
         }
 
-        if (errorMsg.length() > 0) { throw new 
JobExecutionException(errorMsg.toString()); }
+        if (numberOfErrors > 0) { throw new 
JobExecutionException(numberOfErrors); }
     }
 
+    @Override
     @CronTarget(jobName = JobName.UPDATE_TRAIL_BALANCE_DETAILS)
     public void updateTrialBalanceDetails() throws JobExecutionException {
         final JdbcTemplate jdbcTemplate = new 
JdbcTemplate(this.dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
         final StringBuilder tbGapSqlBuilder = new StringBuilder(500);
         tbGapSqlBuilder.append("select distinct(je.transaction_date) ")
-                .append("from acc_gl_journal_entry je ")
-                .append("where je.transaction_date > (select 
IFNULL(MAX(created_date),'2010-01-01') from m_trial_balance)");
+        .append("from acc_gl_journal_entry je ")
+        .append("where je.transaction_date > (select 
IFNULL(MAX(created_date),'2010-01-01') from m_trial_balance)");
 
         final List<Date> tbGaps = 
jdbcTemplate.queryForList(tbGapSqlBuilder.toString(), Date.class);
 
         for(Date tbGap : tbGaps) {
             LocalDate convDate = new DateTime(tbGap).toLocalDate();
             int days = Days.daysBetween(convDate, 
DateUtils.getLocalDateOfTenant()).getDays();
-            if(days < 1)
+            if(days < 1) {
                 continue;
+            }
             final String formattedDate = new 
SimpleDateFormat("yyyy-MM-dd").format(tbGap);
             final StringBuilder sqlBuilder = new StringBuilder(600);
             sqlBuilder.append("Insert Into m_trial_balance(office_id, 
account_id, Amount, entry_date, created_date,closing_balance) ")
-                    .append("Select je.office_id, je.account_id, 
sum(if(je.type_enum=1, (-1) * je.amount, je.amount)) ")
-                    .append("as Amount, Date(je.entry_date) as 'Entry_Date', 
je.transaction_date as 'Created_Date',sum(je.amount) as closing_balance ")
-                    .append("from acc_gl_journal_entry je WHERE 
je.transaction_date = ? ")
-                    .append("group by je.account_id, je.office_id, 
je.transaction_date, Date(je.entry_date)");
-
-            final int result = jdbcTemplate.update(sqlBuilder.toString(), new 
Object[] {
-                    formattedDate
-            });
+            .append("Select je.office_id, je.account_id, 
sum(if(je.type_enum=1, (-1) * je.amount, je.amount)) ")
+            .append("as Amount, Date(je.entry_date) as 'Entry_Date', 
je.transaction_date as 'Created_Date',sum(je.amount) as closing_balance ")
+            .append("from acc_gl_journal_entry je WHERE je.transaction_date = 
? ")
+            .append("group by je.account_id, je.office_id, 
je.transaction_date, Date(je.entry_date)");
+
+            final int result = jdbcTemplate.update(sqlBuilder.toString(), 
formattedDate);
             logger.info(ThreadLocalContextUtil.getTenant().getName() + ": 
Results affected by update: " + result);
         }
 
@@ -459,8 +447,9 @@ public class ScheduledJobRunnerServiceImpl implements 
ScheduledJobRunnerService
                 List<BigDecimal> closingBalanceData = 
jdbcTemplate.queryForList(closingBalanceQuery, new Object[] {officeId, 
accountId}, BigDecimal.class);
                 List<TrialBalance> tbRows = 
this.trialBalanceRepositoryWrapper.findNewByOfficeAndAccount(officeId, 
accountId);
                 BigDecimal closingBalance = null;
-                if(!CollectionUtils.isEmpty(closingBalanceData))
+                if(!CollectionUtils.isEmpty(closingBalanceData)) {
                     closingBalance = closingBalanceData.get(0);
+                }
                 if(CollectionUtils.isEmpty(closingBalanceData)) {
                     closingBalance = BigDecimal.ZERO;
                     for(TrialBalance row : tbRows) {

Reply via email to