Skip to content

Commit 86024b8

Browse files
budaidevadamsaghy
authored andcommitted
FINERACT-2304: Making sure that in the publishHookErrorEvent or publishHookEvent does not throw any exception
1 parent f090551 commit 86024b8

2 files changed

Lines changed: 59 additions & 50 deletions

File tree

fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,11 @@ private void storeCommandIdInContext(CommandSource savedCommandSource) {
211211
}
212212

213213
private void publishHookErrorEvent(CommandWrapper wrapper, JsonCommand command, ErrorInfo errorInfo) {
214-
publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, gson.toJson(errorInfo));
214+
try {
215+
publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, gson.toJson(errorInfo));
216+
} catch (Exception e) {
217+
log.error("Failed to publish hook error event for entity: {}, action: {}", wrapper.entityName(), wrapper.actionName(), e);
218+
}
215219
}
216220

217221
private void exceptionWhenTheRequestAlreadyProcessed(CommandWrapper wrapper, String idempotencyKey, boolean retry) {
@@ -323,66 +327,70 @@ public boolean validateRollbackCommand(final CommandWrapper commandWrapper, fina
323327
}
324328

325329
protected void publishHookEvent(final String entityName, final String actionName, JsonCommand command, final Object result) {
330+
try {
331+
final AppUser appUser = context.authenticatedUser(CommandWrapper.wrap(actionName, entityName, null, null));
326332

327-
final AppUser appUser = context.authenticatedUser(CommandWrapper.wrap(actionName, entityName, null, null));
328-
329-
final HookEventSource hookEventSource = new HookEventSource(entityName, actionName);
330-
331-
// TODO: Add support for publishing array events
332-
if (command.json() != null) {
333-
Type type = new TypeToken<Map<String, Object>>() {
334-
335-
}.getType();
336-
337-
Map<String, Object> myMap;
338-
339-
try {
340-
myMap = gson.fromJson(command.json(), type);
341-
} catch (Exception e) {
342-
throw new PlatformApiDataValidationException("error.msg.invalid.json", "The provided JSON is invalid.", new ArrayList<>(),
343-
e);
344-
}
345-
346-
Map<String, Object> reqmap = new HashMap<>();
347-
reqmap.put("entityName", entityName);
348-
reqmap.put("actionName", actionName);
349-
reqmap.put("createdBy", context.authenticatedUser().getId());
350-
reqmap.put("createdByName", context.authenticatedUser().getUsername());
351-
reqmap.put("createdByFullName", context.authenticatedUser().getDisplayName());
333+
final HookEventSource hookEventSource = new HookEventSource(entityName, actionName);
352334

353-
reqmap.put("request", myMap);
354-
if (result instanceof CommandProcessingResult) {
355-
CommandProcessingResult resultCopy = CommandProcessingResult.fromCommandProcessingResult((CommandProcessingResult) result);
335+
// TODO: Add support for publishing array events
336+
if (command.json() != null) {
337+
Type type = new TypeToken<Map<String, Object>>() {
356338

357-
reqmap.put("officeId", resultCopy.getOfficeId());
358-
reqmap.put("clientId", resultCopy.getClientId());
359-
resultCopy.setOfficeId(null);
360-
reqmap.put("response", resultCopy);
361-
} else if (result instanceof ErrorInfo ex) {
362-
reqmap.put("status", "Exception");
339+
}.getType();
363340

364-
Map<String, Object> errorMap = new HashMap<>();
341+
Map<String, Object> myMap;
365342

366343
try {
367-
errorMap = gson.fromJson(ex.getMessage(), type);
344+
myMap = gson.fromJson(command.json(), type);
368345
} catch (Exception e) {
369-
errorMap.put("errorMessage", ex.getMessage());
346+
throw new PlatformApiDataValidationException("error.msg.invalid.json", "The provided JSON is invalid.",
347+
new ArrayList<>(), e);
370348
}
371349

372-
errorMap.put("errorCode", ex.getErrorCode());
373-
errorMap.put("statusCode", ex.getStatusCode());
374-
375-
reqmap.put("response", errorMap);
376-
}
350+
Map<String, Object> reqmap = new HashMap<>();
351+
reqmap.put("entityName", entityName);
352+
reqmap.put("actionName", actionName);
353+
reqmap.put("createdBy", context.authenticatedUser().getId());
354+
reqmap.put("createdByName", context.authenticatedUser().getUsername());
355+
reqmap.put("createdByFullName", context.authenticatedUser().getDisplayName());
356+
357+
reqmap.put("request", myMap);
358+
if (result instanceof CommandProcessingResult) {
359+
CommandProcessingResult resultCopy = CommandProcessingResult
360+
.fromCommandProcessingResult((CommandProcessingResult) result);
361+
362+
reqmap.put("officeId", resultCopy.getOfficeId());
363+
reqmap.put("clientId", resultCopy.getClientId());
364+
resultCopy.setOfficeId(null);
365+
reqmap.put("response", resultCopy);
366+
} else if (result instanceof ErrorInfo ex) {
367+
reqmap.put("status", "Exception");
368+
369+
Map<String, Object> errorMap = new HashMap<>();
370+
371+
try {
372+
errorMap = gson.fromJson(ex.getMessage(), type);
373+
} catch (Exception e) {
374+
errorMap.put("errorMessage", ex.getMessage());
375+
}
376+
377+
errorMap.put("errorCode", ex.getErrorCode());
378+
errorMap.put("statusCode", ex.getStatusCode());
379+
380+
reqmap.put("response", errorMap);
381+
}
377382

378-
reqmap.put("timestamp", Instant.now().toString());
383+
reqmap.put("timestamp", Instant.now().toString());
379384

380-
final String serializedResult = toApiJsonSerializer.serialize(reqmap);
385+
final String serializedResult = toApiJsonSerializer.serialize(reqmap);
381386

382-
final HookEvent applicationEvent = new HookEvent(hookEventSource, serializedResult, appUser,
383-
ThreadLocalContextUtil.getContext());
387+
final HookEvent applicationEvent = new HookEvent(hookEventSource, serializedResult, appUser,
388+
ThreadLocalContextUtil.getContext());
384389

385-
applicationContext.publishEvent(applicationEvent);
390+
applicationContext.publishEvent(applicationEvent);
391+
}
392+
} catch (Exception e) {
393+
log.error("Failed to publish hook event for entity: {}, action: {}", entityName, actionName, e);
386394
}
387395
}
388396
}

fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.fineract.commands.service;
2020

21+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2122
import static org.junit.jupiter.api.Assertions.assertEquals;
2223
import static org.junit.jupiter.api.Assertions.assertThrows;
2324
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -53,7 +54,6 @@
5354
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
5455
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
5556
import org.apache.fineract.infrastructure.core.exception.IdempotentCommandProcessUnderProcessingException;
56-
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
5757
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
5858
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
5959
import org.apache.fineract.useradministration.domain.AppUser;
@@ -473,7 +473,8 @@ public void publishHookEventHandlesInvalidJson() {
473473

474474
when(command.json()).thenReturn(invalidJson);
475475

476-
assertThrows(PlatformApiDataValidationException.class, () -> {
476+
// Test that no exception is thrown (exceptions are caught and logged)
477+
assertDoesNotThrow(() -> {
477478
underTest.publishHookEvent(entityName, actionName, command, Object.class);
478479
});
479480
}

0 commit comments

Comments
 (0)