@Override
    public BulkOperationResponse executeBulkOperation(final BulkOperationRequest bulkOperationRequest, final C userContext, final AuditParams params) {
        if (bulkOperationRequest.entityIds() == null || bulkOperationRequest.entityIds().isEmpty()) {
            throw new BadRequestException(NO_ENTITY_IDS_ERROR);
        }

        List<BulkOperationFailure> capturedFailures = new LinkedList<>();
        for (String entityId : bulkOperationRequest.entityIds()) {
            try {
                T entityModel = singleEntityOperationExecutor.execute(entityId, userContext);
                try {
                    if (params != null) {
                        auditEventSender.success(getAuditActor(userContext), params.eventType(), successAuditLogContextCreator.create(entityModel, params.entityClass()));
                    }
                } catch (Exception auditLogStoreException) {
                    //exception on audit log storing should not result in failure report, as the operation itself is successful
                    LOG.error("Failed to store in the audit log information about successful entity removal via bulk action ", auditLogStoreException);
                }
            } catch (Exception ex) {
                capturedFailures.add(new BulkOperationFailure(entityId, ex.getMessage()));
                try {
                    if (params != null) {
                        auditEventSender.failure(getAuditActor(userContext), params.eventType(), failureAuditLogContextCreator.create(params.entityIdInPathParam(), entityId));
                    }
                } catch (Exception auditLogStoreException) {
                    //exception on audit log storing should not result in failure report, as the operation itself is successful
                    LOG.error("Failed to store in the audit log information about failed entity removal via bulk action ", auditLogStoreException);
                }
            }
        }

        return new BulkOperationResponse(
                bulkOperationRequest.entityIds().size() - capturedFailures.size(),
                capturedFailures);
    }
@Test
    void returnsProperResponseOnFailedBulkRemoval() throws Exception {
        mockUserContext();
        doThrow(new NotFoundException("!?!?")).when(singleEntityOperationExecutor).execute(any(), eq(context));
        final BulkOperationResponse bulkOperationResponse = toTest.executeBulkOperation(new BulkOperationRequest(List.of("no", "good", "ids")), context, params);
        assertThat(bulkOperationResponse.successfullyPerformed()).isEqualTo(0);
        assertThat(bulkOperationResponse.failures())
                .hasSize(3)
                .containsExactly(
                        new BulkOperationFailure("no", "!?!?"),
                        new BulkOperationFailure("good", "!?!?"),
                        new BulkOperationFailure("ids", "!?!?")
                );
        verify(singleEntityOperationExecutor).execute("no", context);
        verify(singleEntityOperationExecutor).execute("good", context);
        verify(singleEntityOperationExecutor).execute("ids", context);
        verifyNoMoreInteractions(singleEntityOperationExecutor);
        verifyNoInteractions(successAuditLogContextCreator);

        verify(failureAuditLogContextCreator).create(entityIdInPathParam, "no");
        verify(failureAuditLogContextCreator).create(entityIdInPathParam, "good");
        verify(failureAuditLogContextCreator).create(entityIdInPathParam, "ids");
        verifyNoMoreInteractions(failureAuditLogContextCreator);

        verify(auditEventSender, times(3)).failure(any(), eq(eventType), any());
    }