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

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


The following commit(s) were added to refs/heads/develop by this push:
     new ae6dde022 FINERACT-1269: (fix) add a try-catch block to ensure that 
the json is deserialized successfully.
ae6dde022 is described below

commit ae6dde0224f66f82d86121a711d972cca199670a
Author: zeyad2003 <[email protected]>
AuthorDate: Wed Mar 27 11:32:09 2024 +0200

    FINERACT-1269: (fix) add a try-catch block to ensure that the json is 
deserialized successfully.
    
    - Wrap the fromJson() method with try-catch block and throw proper 
exception.
    - Add `publishHookEventHandlesInvalidJson()` method to test the invalid 
json is handled successfully.
---
 .../SynchronousCommandProcessingService.java       | 89 +++++++++++++---------
 .../SynchronousCommandProcessingServiceTest.java   | 19 ++++-
 2 files changed, 68 insertions(+), 40 deletions(-)

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 6b3a6ae88..3df570b1f 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
@@ -27,6 +27,7 @@ import com.google.gson.reflect.TypeToken;
 import io.github.resilience4j.retry.annotation.Retry;
 import java.lang.reflect.Type;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import lombok.RequiredArgsConstructor;
@@ -47,6 +48,7 @@ import 
org.apache.fineract.infrastructure.core.exception.ErrorHandler;
 import 
org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessFailedException;
 import 
org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessSucceedException;
 import 
org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessUnderProcessingException;
+import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import 
org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
 import 
org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@@ -261,56 +263,67 @@ public class SynchronousCommandProcessingService 
implements CommandProcessingSer
         return isMakerChecker && !user.isCheckerSuperUser();
     }
 
-    private 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 HookEventSource hookEventSource = new 
HookEventSource(entityName, actionName);
+    protected void publishHookEvent(final String entityName, final String 
actionName, JsonCommand command, final Object result) {
 
-            // TODO: Add support for publishing array events
-            if (command.json() != null && command.json().startsWith("{")) {
-                Type type = new TypeToken<Map<String, Object>>() {
+        final AppUser appUser = 
context.authenticatedUser(CommandWrapper.wrap(actionName, entityName, null, 
null));
 
-                }.getType();
-                Map<String, Object> myMap = gson.fromJson(command.json(), 
type);
+        final HookEventSource hookEventSource = new 
HookEventSource(entityName, actionName);
 
-                Map<String, Object> 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());
+        // TODO: Add support for publishing array events
+        if (command.json() != null) {
+            Type type = new TypeToken<Map<String, Object>>() {
 
-                reqmap.put("request", myMap);
-                if (result instanceof CommandProcessingResult) {
-                    CommandProcessingResult resultCopy = 
CommandProcessingResult
-                            
.fromCommandProcessingResult((CommandProcessingResult) result);
+            }.getType();
 
-                    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<String, Object> myMap;
 
-                    Map<String, Object> errorMap = 
gson.fromJson(ex.getMessage(), type);
-                    errorMap.put("errorCode", ex.getErrorCode());
-                    errorMap.put("statusCode", ex.getStatusCode());
+            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);
+            }
 
-                    reqmap.put("response", errorMap);
+            Map<String, Object> 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<String, Object> errorMap = new HashMap<>();
+
+                try {
+                    errorMap = gson.fromJson(ex.getMessage(), type);
+                } catch (Exception e) {
+                    errorMap.put("errorMessage", ex.getMessage());
                 }
 
-                reqmap.put("timestamp", Instant.now().toString());
+                errorMap.put("errorCode", ex.getErrorCode());
+                errorMap.put("statusCode", ex.getStatusCode());
 
-                final String serializedResult = 
toApiResultJsonSerializer.serialize(reqmap);
+                reqmap.put("response", errorMap);
+            }
 
-                final HookEvent applicationEvent = new 
HookEvent(hookEventSource, serializedResult, appUser,
-                        ThreadLocalContextUtil.getContext());
+            reqmap.put("timestamp", Instant.now().toString());
 
-                applicationContext.publishEvent(applicationEvent);
-            }
-        } catch (Exception e) {
-            log.error("Error", e);
+            final String serializedResult = 
toApiResultJsonSerializer.serialize(reqmap);
+
+            final HookEvent applicationEvent = new HookEvent(hookEventSource, 
serializedResult, appUser,
+                    ThreadLocalContextUtil.getContext());
+
+            applicationContext.publishEvent(applicationEvent);
         }
     }
 }
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 4e6e0c436..361d0361e 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
@@ -19,6 +19,7 @@
 package org.apache.fineract.commands.service;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -34,10 +35,10 @@ import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDoma
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import 
org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
+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;
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
@@ -163,11 +164,25 @@ public class SynchronousCommandProcessingServiceTest {
         when(commandSourceService.processCommand(commandHandler, jsonCommand, 
commandSource, appUser, false, false))
                 .thenThrow(runtimeException);
 
-        Assertions.assertThrows(RuntimeException.class, () -> {
+        assertThrows(RuntimeException.class, () -> {
             underTest.executeCommand(commandWrapper, jsonCommand, false);
         });
 
         verify(commandSourceService).getCommandSource(commandId);
         verify(commandSourceService).generateErrorInfo(runtimeException);
     }
+
+    @Test
+    public void publishHookEventHandlesInvalidJson() {
+        String entityName = "entity";
+        String actionName = "action";
+        JsonCommand command = Mockito.mock(JsonCommand.class);
+        String invalidJson = "{ invalidJson }";
+
+        when(command.json()).thenReturn(invalidJson);
+
+        assertThrows(PlatformApiDataValidationException.class, () -> {
+            underTest.publishHookEvent(entityName, actionName, command, 
Object.class);
+        });
+    }
 }

Reply via email to