Skip to content

Commit

Permalink
FINERACT-1269: (fix) add a try-catch block to ensure that the json is…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
Zeyad2003 authored and adamsaghy committed Mar 27, 2024
1 parent ed5098b commit ae6dde0
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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;
Expand All @@ -47,6 +48,7 @@
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;
Expand Down Expand Up @@ -261,56 +263,67 @@ public boolean validateRollbackCommand(final CommandWrapper commandWrapper, fina
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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -34,10 +35,10 @@
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;
Expand Down Expand Up @@ -163,11 +164,25 @@ public void testExecuteCommandFails() {
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);
});
}
}

0 comments on commit ae6dde0

Please sign in to comment.