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