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.
This commit is contained in:
+51
-38
@@ -27,6 +27,7 @@ import com.google.gson.reflect.TypeToken;
|
|||||||
import io.github.resilience4j.retry.annotation.Retry;
|
import io.github.resilience4j.retry.annotation.Retry;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import lombok.RequiredArgsConstructor;
|
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.IdempotentCommandProcessFailedException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessSucceedException;
|
import org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessSucceedException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessUnderProcessingException;
|
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.GoogleGsonSerializerHelper;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
@@ -261,56 +263,67 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
return isMakerChecker && !user.isCheckerSuperUser();
|
return isMakerChecker && !user.isCheckerSuperUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishHookEvent(final String entityName, final String actionName, JsonCommand command, final Object result) {
|
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 HookEventSource hookEventSource = new HookEventSource(entityName, actionName);
|
final AppUser appUser = context.authenticatedUser(CommandWrapper.wrap(actionName, entityName, null, null));
|
||||||
|
|
||||||
// TODO: Add support for publishing array events
|
final HookEventSource hookEventSource = new HookEventSource(entityName, actionName);
|
||||||
if (command.json() != null && command.json().startsWith("{")) {
|
|
||||||
Type type = new TypeToken<Map<String, Object>>() {
|
|
||||||
|
|
||||||
}.getType();
|
// TODO: Add support for publishing array events
|
||||||
Map<String, Object> myMap = gson.fromJson(command.json(), type);
|
if (command.json() != null) {
|
||||||
|
Type type = new TypeToken<Map<String, Object>>() {
|
||||||
|
|
||||||
Map<String, Object> reqmap = new HashMap<>();
|
}.getType();
|
||||||
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);
|
Map<String, Object> myMap;
|
||||||
if (result instanceof CommandProcessingResult) {
|
|
||||||
CommandProcessingResult resultCopy = CommandProcessingResult
|
|
||||||
.fromCommandProcessingResult((CommandProcessingResult) result);
|
|
||||||
|
|
||||||
reqmap.put("officeId", resultCopy.getOfficeId());
|
try {
|
||||||
reqmap.put("clientId", resultCopy.getClientId());
|
myMap = gson.fromJson(command.json(), type);
|
||||||
resultCopy.setOfficeId(null);
|
} catch (Exception e) {
|
||||||
reqmap.put("response", resultCopy);
|
throw new PlatformApiDataValidationException("error.msg.invalid.json", "The provided JSON is invalid.", new ArrayList<>(),
|
||||||
} else if (result instanceof ErrorInfo ex) {
|
e);
|
||||||
reqmap.put("status", "Exception");
|
}
|
||||||
|
|
||||||
Map<String, Object> errorMap = gson.fromJson(ex.getMessage(), type);
|
Map<String, Object> reqmap = new HashMap<>();
|
||||||
errorMap.put("errorCode", ex.getErrorCode());
|
reqmap.put("entityName", entityName);
|
||||||
errorMap.put("statusCode", ex.getStatusCode());
|
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<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());
|
|
||||||
|
|
||||||
applicationContext.publishEvent(applicationEvent);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error", e);
|
reqmap.put("timestamp", Instant.now().toString());
|
||||||
|
|
||||||
|
final String serializedResult = toApiResultJsonSerializer.serialize(reqmap);
|
||||||
|
|
||||||
|
final HookEvent applicationEvent = new HookEvent(hookEventSource, serializedResult, appUser,
|
||||||
|
ThreadLocalContextUtil.getContext());
|
||||||
|
|
||||||
|
applicationContext.publishEvent(applicationEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-2
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.commands.service;
|
package org.apache.fineract.commands.service;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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.verify;
|
||||||
import static org.mockito.Mockito.when;
|
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.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
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.core.serialization.ToApiJsonSerializer;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -163,11 +164,25 @@ public class SynchronousCommandProcessingServiceTest {
|
|||||||
when(commandSourceService.processCommand(commandHandler, jsonCommand, commandSource, appUser, false, false))
|
when(commandSourceService.processCommand(commandHandler, jsonCommand, commandSource, appUser, false, false))
|
||||||
.thenThrow(runtimeException);
|
.thenThrow(runtimeException);
|
||||||
|
|
||||||
Assertions.assertThrows(RuntimeException.class, () -> {
|
assertThrows(RuntimeException.class, () -> {
|
||||||
underTest.executeCommand(commandWrapper, jsonCommand, false);
|
underTest.executeCommand(commandWrapper, jsonCommand, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
verify(commandSourceService).getCommandSource(commandId);
|
verify(commandSourceService).getCommandSource(commandId);
|
||||||
verify(commandSourceService).generateErrorInfo(runtimeException);
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user