diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java index bef99cb4d..43647f426 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java @@ -211,7 +211,11 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer } private void publishHookErrorEvent(CommandWrapper wrapper, JsonCommand command, ErrorInfo errorInfo) { - publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, gson.toJson(errorInfo)); + try { + publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, gson.toJson(errorInfo)); + } catch (Exception e) { + log.error("Failed to publish hook error event for entity: {}, action: {}", wrapper.entityName(), wrapper.actionName(), e); + } } private void exceptionWhenTheRequestAlreadyProcessed(CommandWrapper wrapper, String idempotencyKey, boolean retry) { @@ -323,66 +327,70 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer } protected void publishHookEvent(final String entityName, final String actionName, JsonCommand command, final Object result) { + try { + final AppUser appUser = 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); - final HookEventSource hookEventSource = new HookEventSource(entityName, actionName); + // TODO: Add support for publishing array events + if (command.json() != null) { + Type type = new TypeToken>() { - // TODO: Add support for publishing array events - if (command.json() != null) { - Type type = new TypeToken>() { + }.getType(); - }.getType(); - - Map myMap; - - try { - myMap = gson.fromJson(command.json(), type); - } catch (Exception e) { - throw new PlatformApiDataValidationException("error.msg.invalid.json", "The provided JSON is invalid.", new ArrayList<>(), - e); - } - - Map reqmap = new HashMap<>(); - reqmap.put("entityName", entityName); - reqmap.put("actionName", actionName); - reqmap.put("createdBy", context.authenticatedUser().getId()); - reqmap.put("createdByName", context.authenticatedUser().getUsername()); - reqmap.put("createdByFullName", context.authenticatedUser().getDisplayName()); - - reqmap.put("request", myMap); - if (result instanceof CommandProcessingResult) { - CommandProcessingResult resultCopy = CommandProcessingResult.fromCommandProcessingResult((CommandProcessingResult) result); - - reqmap.put("officeId", resultCopy.getOfficeId()); - reqmap.put("clientId", resultCopy.getClientId()); - resultCopy.setOfficeId(null); - reqmap.put("response", resultCopy); - } else if (result instanceof ErrorInfo ex) { - reqmap.put("status", "Exception"); - - Map errorMap = new HashMap<>(); + Map myMap; try { - errorMap = gson.fromJson(ex.getMessage(), type); + myMap = gson.fromJson(command.json(), type); } catch (Exception e) { - errorMap.put("errorMessage", ex.getMessage()); + throw new PlatformApiDataValidationException("error.msg.invalid.json", "The provided JSON is invalid.", + new ArrayList<>(), e); } - errorMap.put("errorCode", ex.getErrorCode()); - errorMap.put("statusCode", ex.getStatusCode()); + Map reqmap = new HashMap<>(); + reqmap.put("entityName", entityName); + reqmap.put("actionName", actionName); + reqmap.put("createdBy", context.authenticatedUser().getId()); + reqmap.put("createdByName", context.authenticatedUser().getUsername()); + reqmap.put("createdByFullName", context.authenticatedUser().getDisplayName()); - reqmap.put("response", errorMap); + reqmap.put("request", myMap); + if (result instanceof CommandProcessingResult) { + CommandProcessingResult resultCopy = CommandProcessingResult + .fromCommandProcessingResult((CommandProcessingResult) result); + + reqmap.put("officeId", resultCopy.getOfficeId()); + reqmap.put("clientId", resultCopy.getClientId()); + resultCopy.setOfficeId(null); + reqmap.put("response", resultCopy); + } else if (result instanceof ErrorInfo ex) { + reqmap.put("status", "Exception"); + + Map errorMap = new HashMap<>(); + + try { + errorMap = gson.fromJson(ex.getMessage(), type); + } catch (Exception e) { + errorMap.put("errorMessage", ex.getMessage()); + } + + errorMap.put("errorCode", ex.getErrorCode()); + errorMap.put("statusCode", ex.getStatusCode()); + + reqmap.put("response", errorMap); + } + + reqmap.put("timestamp", Instant.now().toString()); + + final String serializedResult = toApiJsonSerializer.serialize(reqmap); + + final HookEvent applicationEvent = new HookEvent(hookEventSource, serializedResult, appUser, + ThreadLocalContextUtil.getContext()); + + applicationContext.publishEvent(applicationEvent); } - - reqmap.put("timestamp", Instant.now().toString()); - - final String serializedResult = toApiJsonSerializer.serialize(reqmap); - - final HookEvent applicationEvent = new HookEvent(hookEventSource, serializedResult, appUser, - ThreadLocalContextUtil.getContext()); - - applicationContext.publishEvent(applicationEvent); + } catch (Exception e) { + log.error("Failed to publish hook event for entity: {}, action: {}", entityName, actionName, e); } } } diff --git a/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java index 31cefcbd7..4f45f8326 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.commands.service; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -53,7 +54,6 @@ import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder; import org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessUnderProcessingException; -import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.useradministration.domain.AppUser; @@ -473,7 +473,8 @@ public class SynchronousCommandProcessingServiceTest { when(command.json()).thenReturn(invalidJson); - assertThrows(PlatformApiDataValidationException.class, () -> { + // Test that no exception is thrown (exceptions are caught and logged) + assertDoesNotThrow(() -> { underTest.publishHookEvent(entityName, actionName, command, Object.class); }); }