You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2022/09/13 11:40:32 UTC

[fineract] branch develop updated: FINERACT-1744: Tiny refactorings as a preparation for idempotency implementation

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

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new b5b189d61 FINERACT-1744: Tiny refactorings as a preparation for idempotency implementation
b5b189d61 is described below

commit b5b189d610180fc1dadcf3a9e5340b63100cc565
Author: Arnold Galovics <ga...@gmail.com>
AuthorDate: Mon Sep 12 15:25:57 2022 +0200

    FINERACT-1744: Tiny refactorings as a preparation for idempotency implementation
---
 .../domain/CommandProcessingResultType.java        | 34 ++---------
 .../commands/provider/CommandHandlerProvider.java  | 49 ++++++++--------
 .../commands/service/CommandProcessingService.java |  2 +-
 ...folioCommandSourceWritePlatformServiceImpl.java |  6 +-
 .../SynchronousCommandProcessingService.java       | 65 +++++++++++-----------
 .../hooks/listener/FineractHookListener.java       |  4 +-
 .../service/SchedulerJobRunnerReadServiceImpl.java |  2 +-
 ...a => UpdateLoanDisburseDateCommandHandler.java} |  2 +-
 8 files changed, 70 insertions(+), 94 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java b/fineract-provider/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java
index 5a1993fde..f25287e7f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java
@@ -18,6 +18,11 @@
  */
 package org.apache.fineract.commands.domain;
 
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor
 public enum CommandProcessingResultType {
 
     INVALID(0, "commandProcessingResultType.invalid"), //
@@ -27,33 +32,4 @@ public enum CommandProcessingResultType {
 
     private final Integer value;
     private final String code;
-
-    CommandProcessingResultType(final Integer value, final String code) {
-        this.value = value;
-        this.code = code;
-    }
-
-    public Integer getValue() {
-        return this.value;
-    }
-
-    public String getCode() {
-        return this.code;
-    }
-
-    public static CommandProcessingResultType fromInt(final Integer typeValue) {
-        CommandProcessingResultType type = CommandProcessingResultType.INVALID;
-        switch (typeValue) {
-            case 1:
-                type = PROCESSED;
-            break;
-            case 2:
-                type = AWAITING_APPROVAL;
-            break;
-            case 3:
-                type = REJECTED;
-            break;
-        }
-        return type;
-    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/provider/CommandHandlerProvider.java b/fineract-provider/src/main/java/org/apache/fineract/commands/provider/CommandHandlerProvider.java
index cdefacc81..a4297f9d5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/provider/CommandHandlerProvider.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/provider/CommandHandlerProvider.java
@@ -28,6 +28,7 @@ import org.apache.fineract.commands.annotation.CommandType;
 import org.apache.fineract.commands.exception.UnsupportedCommandException;
 import org.apache.fineract.commands.handler.NewCommandSourceHandler;
 import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.stereotype.Component;
@@ -47,10 +48,30 @@ import org.springframework.stereotype.Component;
 @Component
 @NoArgsConstructor
 @Slf4j
-public class CommandHandlerProvider implements ApplicationContextAware {
+public class CommandHandlerProvider implements ApplicationContextAware, InitializingBean {
 
+    private final HashMap<String, String> registeredHandlers = new HashMap<>();
     private ApplicationContext applicationContext;
-    private HashMap<String, String> registeredHandlers;
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        initializeHandlerRegistry();
+    }
+
+    private void initializeHandlerRegistry() {
+        final String[] commandHandlerBeans = applicationContext.getBeanNamesForAnnotation(CommandType.class);
+        if (ArrayUtils.isNotEmpty(commandHandlerBeans)) {
+            for (final String commandHandlerName : commandHandlerBeans) {
+                log.debug("Register command handler '{}' ...", commandHandlerName);
+                final CommandType commandType = applicationContext.findAnnotationOnBean(commandHandlerName, CommandType.class);
+                try {
+                    registeredHandlers.put(commandType.entity() + "|" + commandType.action(), commandHandlerName);
+                } catch (final Throwable th) {
+                    log.error("Unable to register command handler '{}'!", commandHandlerName, th);
+                }
+            }
+        }
+    }
 
     /**
      * Returns a handler for the given entity and action.<br>
@@ -68,34 +89,14 @@ public class CommandHandlerProvider implements ApplicationContextAware {
         Preconditions.checkArgument(StringUtils.isNoneEmpty(action), "An action must be given!");
 
         final String key = entity + "|" + action;
-        if (!this.registeredHandlers.containsKey(key)) {
+        if (!registeredHandlers.containsKey(key)) {
             throw new UnsupportedCommandException(key);
         }
-        return (NewCommandSourceHandler) this.applicationContext.getBean(this.registeredHandlers.get(key));
-    }
-
-    private void initializeHandlerRegistry() {
-        if (this.registeredHandlers == null) {
-            this.registeredHandlers = new HashMap<>();
-
-            final String[] commandHandlerBeans = this.applicationContext.getBeanNamesForAnnotation(CommandType.class);
-            if (ArrayUtils.isNotEmpty(commandHandlerBeans)) {
-                for (final String commandHandlerName : commandHandlerBeans) {
-                    log.debug("Register command handler '{}' ...", commandHandlerName);
-                    final CommandType commandType = this.applicationContext.findAnnotationOnBean(commandHandlerName, CommandType.class);
-                    try {
-                        this.registeredHandlers.put(commandType.entity() + "|" + commandType.action(), commandHandlerName);
-                    } catch (final Throwable th) {
-                        log.error("Unable to register command handler '{}'!", commandHandlerName, th);
-                    }
-                }
-            }
-        }
+        return (NewCommandSourceHandler) applicationContext.getBean(registeredHandlers.get(key));
     }
 
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         this.applicationContext = applicationContext;
-        this.initializeHandlerRegistry();
     }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandProcessingService.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandProcessingService.java
index 50c62e436..d566c6222 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandProcessingService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandProcessingService.java
@@ -26,7 +26,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
 
 public interface CommandProcessingService {
 
-    CommandProcessingResult processAndLogCommand(CommandWrapper wrapper, JsonCommand command, boolean isApprovedByChecker);
+    CommandProcessingResult executeCommand(CommandWrapper wrapper, JsonCommand command, boolean isApprovedByChecker);
 
     CommandProcessingResult logCommand(CommandSource commandSourceResult);
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java
index ad64791a1..38b7e937e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java
@@ -77,7 +77,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
 
         final String json = wrapper.getJson();
         CommandProcessingResult result = null;
-        JsonCommand command = null;
+        JsonCommand command;
         int numberOfRetries = 0;
         int maxNumberOfRetries = ThreadLocalContextUtil.getTenant().getConnection().getMaxRetriesOnDeadlock();
         int maxIntervalBetweenRetries = ThreadLocalContextUtil.getTenant().getConnection().getMaxIntervalBetweenRetries();
@@ -88,7 +88,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
                 wrapper.getOrganisationCreditBureauId());
         while (numberOfRetries <= maxNumberOfRetries) {
             try {
-                result = this.processAndLogCommandService.processAndLogCommand(wrapper, command, isApprovedByChecker);
+                result = this.processAndLogCommandService.executeCommand(wrapper, command, isApprovedByChecker);
                 numberOfRetries = maxNumberOfRetries + 1;
             } catch (CannotAcquireLockException | ObjectOptimisticLockingFailureException exception) {
                 log.info("The following command {} has been retried  {} time(s)", command.json(), numberOfRetries);
@@ -140,7 +140,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
                 commandSourceInput.getOrganisationCreditBureauId());
 
         final boolean makerCheckerApproval = true;
-        return this.processAndLogCommandService.processAndLogCommand(wrapper, command, makerCheckerApproval);
+        return this.processAndLogCommandService.executeCommand(wrapper, command, makerCheckerApproval);
     }
 
     @Transactional
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java
index 1d6c5fccf..c15376007 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java
@@ -65,10 +65,10 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
 
     @Transactional
     @Override
-    public CommandProcessingResult processAndLogCommand(final CommandWrapper wrapper, final JsonCommand command,
+    public CommandProcessingResult executeCommand(final CommandWrapper wrapper, final JsonCommand command,
             final boolean isApprovedByChecker) {
 
-        final boolean rollbackTransaction = this.configurationDomainService.isMakerCheckerEnabledForTask(wrapper.taskPermissionName());
+        final boolean rollbackTransaction = configurationDomainService.isMakerCheckerEnabledForTask(wrapper.taskPermissionName());
 
         final NewCommandSourceHandler handler = findCommandHandler(wrapper);
 
@@ -76,16 +76,15 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
         try {
             result = handler.processCommand(command);
         } catch (Throwable t) {
-            // publish error event
-            publishErrorEvent(wrapper, command, t);
+            publishHookErrorEvent(wrapper, command, t);
             throw t;
         }
 
-        final AppUser maker = this.context.authenticatedUser(wrapper);
+        final AppUser maker = context.authenticatedUser(wrapper);
 
         CommandSource commandSourceResult;
         if (command.commandId() != null) {
-            commandSourceResult = this.commandSourceRepository.findById(command.commandId())
+            commandSourceResult = commandSourceRepository.findById(command.commandId())
                     .orElseThrow(() -> new CommandNotFoundException(command.commandId()));
             commandSourceResult.markAsChecked(maker);
         } else {
@@ -98,7 +97,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
         String changesOnlyJson;
         boolean rollBack = (rollbackTransaction || result.isRollbackTransaction()) && !isApprovedByChecker;
         if (result.hasChanges() && !rollBack) {
-            changesOnlyJson = this.toApiJsonSerializer.serializeResult(result.getChanges());
+            changesOnlyJson = toApiJsonSerializer.serializeResult(result.getChanges());
             commandSourceResult.updateJsonTo(changesOnlyJson);
         }
 
@@ -107,7 +106,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
         }
 
         if (commandSourceResult.hasJson()) {
-            this.commandSourceRepository.save(commandSourceResult);
+            commandSourceRepository.save(commandSourceResult);
         }
 
         if ((rollbackTransaction || result.isRollbackTransaction()) && !isApprovedByChecker) {
@@ -125,7 +124,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
         }
         result.setRollbackTransaction(null);
 
-        publishEvent(wrapper.entityName(), wrapper.actionName(), command, result);
+        publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, result);
 
         return result;
     }
@@ -135,7 +134,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
     public CommandProcessingResult logCommand(CommandSource commandSourceResult) {
 
         commandSourceResult.markAsAwaitingApproval();
-        commandSourceResult = this.commandSourceRepository.saveAndFlush(commandSourceResult);
+        commandSourceResult = commandSourceRepository.saveAndFlush(commandSourceResult);
 
         return new CommandProcessingResultBuilder().withCommandId(commandSourceResult.getId())
                 .withEntityId(commandSourceResult.getResourceId()).build();
@@ -146,54 +145,54 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
 
         if (wrapper.isDatatableResource()) {
             if (wrapper.isCreateDatatable()) {
-                handler = this.applicationContext.getBean("createDatatableCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("createDatatableCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isDeleteDatatable()) {
-                handler = this.applicationContext.getBean("deleteDatatableCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("deleteDatatableCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isUpdateDatatable()) {
-                handler = this.applicationContext.getBean("updateDatatableCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("updateDatatableCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isCreate()) {
-                handler = this.applicationContext.getBean("createDatatableEntryCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("createDatatableEntryCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isUpdateMultiple()) {
-                handler = this.applicationContext.getBean("updateOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("updateOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isUpdateOneToOne()) {
-                handler = this.applicationContext.getBean("updateOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("updateOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isDeleteMultiple()) {
-                handler = this.applicationContext.getBean("deleteOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("deleteOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isDeleteOneToOne()) {
-                handler = this.applicationContext.getBean("deleteOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("deleteOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isRegisterDatatable()) {
-                handler = this.applicationContext.getBean("registerDatatableCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("registerDatatableCommandHandler", NewCommandSourceHandler.class);
             } else {
                 throw new UnsupportedCommandException(wrapper.commandName());
             }
         } else if (wrapper.isNoteResource()) {
             if (wrapper.isCreate()) {
-                handler = this.applicationContext.getBean("createNoteCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("createNoteCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isUpdate()) {
-                handler = this.applicationContext.getBean("updateNoteCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("updateNoteCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isDelete()) {
-                handler = this.applicationContext.getBean("deleteNoteCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("deleteNoteCommandHandler", NewCommandSourceHandler.class);
             } else {
                 throw new UnsupportedCommandException(wrapper.commandName());
             }
         } else if (wrapper.isSurveyResource()) {
             if (wrapper.isRegisterSurvey()) {
-                handler = this.applicationContext.getBean("registerSurveyCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("registerSurveyCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.isFullFilSurvey()) {
-                handler = this.applicationContext.getBean("fullFilSurveyCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("fullFilSurveyCommandHandler", NewCommandSourceHandler.class);
             } else {
                 throw new UnsupportedCommandException(wrapper.commandName());
             }
         } else if (wrapper.isLoanDisburseDetailResource()) {
             if (wrapper.isUpdateDisbursementDate()) {
-                handler = this.applicationContext.getBean("updateLoanDisbuseDateCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("updateLoanDisburseDateCommandHandler", NewCommandSourceHandler.class);
             } else if (wrapper.addAndDeleteDisbursementDetails()) {
-                handler = this.applicationContext.getBean("addAndDeleteLoanDisburseDetailsCommandHandler", NewCommandSourceHandler.class);
+                handler = applicationContext.getBean("addAndDeleteLoanDisburseDetailsCommandHandler", NewCommandSourceHandler.class);
             } else {
                 throw new UnsupportedCommandException(wrapper.commandName());
             }
         } else {
-            handler = this.commandHandlerProvider.getHandler(wrapper.entityName(), wrapper.actionName());
+            handler = commandHandlerProvider.getHandler(wrapper.entityName(), wrapper.actionName());
         }
 
         return handler;
@@ -201,12 +200,12 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
 
     @Override
     public boolean validateCommand(final CommandWrapper commandWrapper, final AppUser user) {
-        boolean rollbackTransaction = this.configurationDomainService.isMakerCheckerEnabledForTask(commandWrapper.taskPermissionName());
+        boolean rollbackTransaction = configurationDomainService.isMakerCheckerEnabledForTask(commandWrapper.taskPermissionName());
         user.validateHasPermissionTo(commandWrapper.getTaskPermissionName());
         return rollbackTransaction;
     }
 
-    private void publishErrorEvent(CommandWrapper wrapper, JsonCommand command, Throwable t) {
+    private void publishHookErrorEvent(CommandWrapper wrapper, JsonCommand command, Throwable t) {
 
         ErrorInfo ex;
         if (t instanceof final RuntimeException e) {
@@ -215,13 +214,13 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
             ex = new ErrorInfo(500, 9999, "{\"Exception\": " + t.toString() + "}");
         }
 
-        publishEvent(wrapper.entityName(), wrapper.actionName(), command, ex);
+        publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, ex);
     }
 
-    private void publishEvent(final String entityName, final String actionName, JsonCommand command, final Object result) {
+    private void publishHookEvent(final String entityName, final String actionName, JsonCommand command, final Object result) {
         Gson gson = new Gson();
         try {
-            final AppUser appUser = this.context.authenticatedUser(CommandWrapper.wrap(actionName, entityName, null, null));
+            final AppUser appUser = context.authenticatedUser(CommandWrapper.wrap(actionName, entityName, null, null));
 
             final HookEventSource hookEventSource = new HookEventSource(entityName, actionName);
 
@@ -260,7 +259,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
 
                 reqmap.put("timestamp", Instant.now().toString());
 
-                final String serializedResult = this.toApiResultJsonSerializer.serialize(reqmap);
+                final String serializedResult = toApiResultJsonSerializer.serialize(reqmap);
 
                 final HookEvent applicationEvent = new HookEvent(hookEventSource, serializedResult, appUser,
                         ThreadLocalContextUtil.getContext());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/listener/FineractHookListener.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/listener/FineractHookListener.java
index 90c307ae1..53e10c4dd 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/listener/FineractHookListener.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/listener/FineractHookListener.java
@@ -52,11 +52,11 @@ public class FineractHookListener implements HookListener {
         final String actionName = hookEventSource.getActionName();
         final String payload = event.getPayload();
 
-        final List<Hook> hooks = this.hookReadPlatformService.retrieveHooksByEvent(hookEventSource.getEntityName(),
+        final List<Hook> hooks = hookReadPlatformService.retrieveHooksByEvent(hookEventSource.getEntityName(),
                 hookEventSource.getActionName());
 
         for (final Hook hook : hooks) {
-            final HookProcessor processor = this.hookProcessorProvider.getProcessor(hook);
+            final HookProcessor processor = hookProcessorProvider.getProcessor(hook);
             try {
                 processor.process(hook, payload, entityName, actionName, fineractContext);
             } catch (Throwable e) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedulerJobRunnerReadServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedulerJobRunnerReadServiceImpl.java
index b915521a5..10cce9a94 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedulerJobRunnerReadServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedulerJobRunnerReadServiceImpl.java
@@ -125,7 +125,7 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
     public boolean isUpdatesAllowed() {
         final String sql = "select job.display_name from job job where job.currently_running=true and job.updates_allowed=false";
         final List<String> names = this.jdbcTemplate.queryForList(sql, String.class);
-        if (names != null && names.size() > 0) {
+        if (names.size() > 0) {
             final String listVals = names.toString();
             final String jobNames = listVals.substring(listVals.indexOf("[") + 1, listVals.indexOf("]"));
             throw new OperationNotAllowedException(jobNames);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UpdateLoanDisbuseDateCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UpdateLoanDisburseDateCommandHandler.java
similarity index 95%
rename from fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UpdateLoanDisbuseDateCommandHandler.java
rename to fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UpdateLoanDisburseDateCommandHandler.java
index af5cde066..17fa829dc 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UpdateLoanDisbuseDateCommandHandler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UpdateLoanDisburseDateCommandHandler.java
@@ -28,7 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Service
 @RequiredArgsConstructor
-public class UpdateLoanDisbuseDateCommandHandler implements NewCommandSourceHandler {
+public class UpdateLoanDisburseDateCommandHandler implements NewCommandSourceHandler {
 
     private final LoanWritePlatformService writePlatformService;