From b213b0a8768e9eccb4a65fd2a5393728aaf11403 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 28 Feb 2023 10:56:37 +0100 Subject: [PATCH] SEBSERV-353 fixed delete with references --- .../page/AbstractBatchActionWizard.java | 13 +- .../bulkaction/impl/DeleteExamAction.java | 51 +++++++- .../servicelayer/dao/ClientConnectionDAO.java | 7 + .../servicelayer/dao/ClientGroupDAO.java | 7 + .../dao/ExamConfigurationMapDAO.java | 7 + .../servicelayer/dao/IndicatorDAO.java | 7 + .../dao/impl/ClientConnectionDAOImpl.java | 123 +++++++++++------- .../dao/impl/ClientGroupDAOImpl.java | 29 +++++ .../dao/impl/ExamConfigurationMapDAOImpl.java | 38 ++++++ .../dao/impl/IndicatorDAOImpl.java | 34 +++++ .../lms/impl/SEBRestrictionServiceImpl.java | 21 +++ src/main/resources/messages.properties | 4 +- 12 files changed, 289 insertions(+), 52 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/AbstractBatchActionWizard.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/AbstractBatchActionWizard.java index 318cf440..cb31b424 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/AbstractBatchActionWizard.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/AbstractBatchActionWizard.java @@ -138,7 +138,7 @@ public abstract class AbstractBatchActionWizard { pageService, formContext, multiSelection, - false) + false, false) .build(); applySelectionList(formContext, multiSelection); @@ -181,7 +181,7 @@ public abstract class AbstractBatchActionWizard { this.pageService, formContext, multiSelection, - true) + true, true) .build(); this.serverPushService.runServerPush( @@ -234,7 +234,8 @@ public abstract class AbstractBatchActionWizard { final PageService pageService, final PageContext formContext, final Set multiSelection, - final boolean readonly) { + final boolean readonly, + final boolean resultPage) { final FormBuilder formBuilder = pageService .formBuilder(formContext) @@ -245,7 +246,11 @@ public abstract class AbstractBatchActionWizard { .readonly(true)); buildSpecificFormFields(formContext, formBuilder, readonly); - return buildProgressFields(formBuilder, readonly); + if (resultPage) { + return buildProgressFields(formBuilder, readonly); + } else { + return formBuilder; + } } protected FormBuilder buildProgressFields(final FormBuilder formHead, final boolean readonly) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/DeleteExamAction.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/DeleteExamAction.java index 8779bc40..84d36759 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/DeleteExamAction.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/DeleteExamAction.java @@ -13,8 +13,11 @@ import java.util.Collection; import java.util.HashSet; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import ch.ethz.seb.sebserver.gbl.api.API.BatchActionType; import ch.ethz.seb.sebserver.gbl.api.APIMessage; @@ -27,7 +30,12 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BatchActionExec; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientGroupDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; @@ -36,18 +44,32 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; @WebServiceProfile public class DeleteExamAction implements BatchActionExec { + private static final Logger log = LoggerFactory.getLogger(DeleteExamAction.class); + private final ExamDAO examDAO; + private final ClientConnectionDAO clientConnectionDAO; + private final ExamConfigurationMapDAO examConfigurationMapDAO; + private final ClientGroupDAO clientGroupDAO; + private final IndicatorDAO indicatorDAO; private final AuthorizationService authorization; private final UserActivityLogDAO userActivityLogDAO; private final ExamSessionService examSessionService; public DeleteExamAction( final ExamDAO examDAO, + final ClientConnectionDAO clientConnectionDAO, + final ExamConfigurationMapDAO examConfigurationMapDAO, + final ClientGroupDAO clientGroupDAO, + final IndicatorDAO indicatorDAO, final AuthorizationService authorization, final UserActivityLogDAO userActivityLogDAO, final ExamSessionService examSessionService) { this.examDAO = examDAO; + this.clientConnectionDAO = clientConnectionDAO; + this.examConfigurationMapDAO = examConfigurationMapDAO; + this.clientGroupDAO = clientGroupDAO; + this.indicatorDAO = indicatorDAO; this.authorization = authorization; this.userActivityLogDAO = userActivityLogDAO; this.examSessionService = examSessionService; @@ -65,13 +87,40 @@ public class DeleteExamAction implements BatchActionExec { } @Override + @Transactional public Result doSingleAction(final String modelId, final BatchAction batchAction) { return this.examDAO.byModelId(modelId) .flatMap(this::checkWriteAccess) .flatMap(this::checkNoActiveSEBClientConnections) + .flatMap(this::deleteExamDependencies) .flatMap(this::deleteExamWithRefs) .flatMap(exam -> logDeleted(exam, batchAction)) - .map(Exam::getEntityKey); + .map(Exam::getEntityKey) + .onError(TransactionHandler::rollback); + } + + private Result deleteExamDependencies(final Exam entity) { + return this.clientConnectionDAO.deleteAllForExam(entity.id) + .map(this::logDelete) + .flatMap(res -> this.examConfigurationMapDAO.deleteAllForExam(entity.id)) + .map(this::logDelete) + .flatMap(res -> this.clientGroupDAO.deleteAllForExam(entity.id)) + .map(this::logDelete) + .flatMap(res -> this.indicatorDAO.deleteAllForExam(entity.id)) + .map(this::logDelete) + .map(res -> entity); + } + + private Collection logDelete(final Collection deletedKeys) { + try { + if (log.isDebugEnabled()) { + log.debug("Exam deletion, deleted references: {}", deletedKeys); + } + } catch (final Exception e) { + log.error("Failed to log deletion for: {}", deletedKeys, e); + } + + return deletedKeys; } private Result deleteExamWithRefs(final Exam entity) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientConnectionDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientConnectionDAO.java index d67bb637..a2a84c8d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientConnectionDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientConnectionDAO.java @@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -212,4 +213,10 @@ public interface ClientConnectionDAO extends * @return Result refer to the given check status or to an error when happened */ Result saveSEBClientVersionCheckStatus(Long connectionId, Boolean checkStatus); + /** Delete all client connections for a particular exam. + * + * @param examId the exam identifier + * @return Result refer to the list of deleted client connections or to an error when happened */ + Result> deleteAllForExam(Long examId); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientGroupDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientGroupDAO.java index 5f63f1da..b0542958 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientGroupDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientGroupDAO.java @@ -13,6 +13,7 @@ import java.util.Collection; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; @@ -40,4 +41,10 @@ public interface ClientGroupDAO extends EntityDAO, Bul // just evict the cache } + /** Delete all client groups for a particular exam. + * + * @param examId the exam identifier + * @return Result refer to the list of deleted client groups or to an error when happened */ + Result> deleteAllForExam(Long examId); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java index dc013076..43164f14 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java @@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao; import java.util.Collection; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; @@ -76,4 +77,10 @@ public interface ExamConfigurationMapDAO extends * if happened */ Result checkNoActiveExamReferences(Long configurationNodeId); + /** Delete all configuration mappings for a particular exam. + * + * @param examId the exam identifier + * @return Result refer to the list of deleted configuration mappings or to an error when happened */ + Result> deleteAllForExam(Long examId); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/IndicatorDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/IndicatorDAO.java index 86da7e9f..577968ba 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/IndicatorDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/IndicatorDAO.java @@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao; import java.util.Collection; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; @@ -23,4 +24,10 @@ public interface IndicatorDAO extends EntityDAO, BulkActio * @return Result referring to the collection of Indicators of an Exam or to an error if happened */ Result> allForExam(Long examId); + /** Delete all indicators for a particular exam. + * + * @param examId the exam identifier + * @return Result refer to the list of deleted indicators or to an error when happened */ + Result> deleteAllForExam(Long examId); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java index 4a1e9b6f..30753254 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java @@ -568,52 +568,8 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { ids.stream().forEach(this::clearConnecionTokenCache); - // delete all related client indicators - this.clientIndicatorRecordMapper.deleteByExample() - .where( - ClientIndicatorRecordDynamicSqlSupport.clientConnectionId, - SqlBuilder.isIn(ids)) - .build() - .execute(); + deleteAllRelations(ids); - // delete all related client events - this.clientEventRecordMapper.deleteByExample() - .where( - ClientEventRecordDynamicSqlSupport.clientConnectionId, - SqlBuilder.isIn(ids)) - .build() - .execute(); - - // delete all related client notifications - this.clientNotificationRecordMapper.deleteByExample() - .where( - ClientNotificationRecordDynamicSqlSupport.clientConnectionId, - SqlBuilder.isIn(ids)) - .build() - .execute(); - - // then delete all related client instructions - final List connectionTokens = this.clientConnectionRecordMapper.selectByExample() - .where( - ClientConnectionRecordDynamicSqlSupport.id, - SqlBuilder.isIn(ids)) - .build() - .execute() - .stream() - .map(r -> r.getConnectionToken()) - .collect(Collectors.toList()); - - if (connectionTokens != null && !connectionTokens.isEmpty()) { - - this.clientInstructionRecordMapper.deleteByExample() - .where( - ClientInstructionRecordDynamicSqlSupport.connectionToken, - SqlBuilder.isIn(connectionTokens)) - .build() - .execute(); - } - - // then delete all requested client-connections this.clientConnectionRecordMapper.deleteByExample() .where( ClientConnectionRecordDynamicSqlSupport.id, @@ -882,6 +838,36 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { .execute()); } + @Override + @Transactional + public Result> deleteAllForExam(final Long examId) { + return Result.> tryCatch(() -> { + + final List ids = this.clientConnectionRecordMapper.selectIdsByExample() + .where(ClientConnectionRecordDynamicSqlSupport.examId, isEqualTo(examId)) + .build() + .execute(); + + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + + deleteAllRelations(ids); + + this.clientConnectionRecordMapper.deleteByExample() + .where( + ClientConnectionRecordDynamicSqlSupport.id, + SqlBuilder.isIn(ids)) + .build() + .execute(); + + return ids.stream() + .map(id -> new EntityKey(id, EntityType.CLIENT_CONNECTION)) + .collect(Collectors.toList()); + }) + .onError(TransactionHandler::rollback); + } + private Result recordById(final Long id) { return Result.tryCatch(() -> { @@ -1025,4 +1011,51 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { return id; } + private void deleteAllRelations(final List ids) { + // delete all related client indicators + this.clientIndicatorRecordMapper.deleteByExample() + .where( + ClientIndicatorRecordDynamicSqlSupport.clientConnectionId, + SqlBuilder.isIn(ids)) + .build() + .execute(); + + // delete all related client events + this.clientEventRecordMapper.deleteByExample() + .where( + ClientEventRecordDynamicSqlSupport.clientConnectionId, + SqlBuilder.isIn(ids)) + .build() + .execute(); + + // delete all related client notifications + this.clientNotificationRecordMapper.deleteByExample() + .where( + ClientNotificationRecordDynamicSqlSupport.clientConnectionId, + SqlBuilder.isIn(ids)) + .build() + .execute(); + + // then delete all related client instructions + final List connectionTokens = this.clientConnectionRecordMapper.selectByExample() + .where( + ClientConnectionRecordDynamicSqlSupport.id, + SqlBuilder.isIn(ids)) + .build() + .execute() + .stream() + .map(r -> r.getConnectionToken()) + .collect(Collectors.toList()); + + if (connectionTokens != null && !connectionTokens.isEmpty()) { + + this.clientInstructionRecordMapper.deleteByExample() + .where( + ClientInstructionRecordDynamicSqlSupport.connectionToken, + SqlBuilder.isIn(connectionTokens)) + .build() + .execute(); + } + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientGroupDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientGroupDAOImpl.java index f44d862a..1f3c5ac3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientGroupDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientGroupDAOImpl.java @@ -233,6 +233,35 @@ public class ClientGroupDAOImpl implements ClientGroupDAO { return getDependencies(bulkAction, selectionFunction); } + @Override + @Transactional + public Result> deleteAllForExam(final Long examId) { + return Result.> tryCatch(() -> { + + final List ids = this.clientGroupRecordMapper.selectIdsByExample() + .where(ClientGroupRecordDynamicSqlSupport.examId, isEqualTo(examId)) + .build() + .execute(); + + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + + // delete all client groups + this.clientGroupRecordMapper + .deleteByExample() + .where(ClientGroupRecordDynamicSqlSupport.id, isIn(ids)) + .build() + .execute(); + + return ids.stream() + .map(id -> new EntityKey(id, EntityType.CLIENT_GROUP)) + .collect(Collectors.toList()); + + }) + .onError(TransactionHandler::rollback); + } + private Result> allIdsOfInstitution(final EntityKey institutionKey) { return Result.tryCatch(() -> this.clientGroupRecordMapper .selectByExample() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java index 42a59c68..b9eb515c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java @@ -394,6 +394,44 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { .isPresent()); } + @Override + @Transactional + public Result> deleteAllForExam(final Long examId) { + return Result.> tryCatch(() -> { + + final List ids = this.examConfigurationMapRecordMapper.selectIdsByExample() + .where(ExamConfigurationMapRecordDynamicSqlSupport.examId, isEqualTo(examId)) + .build() + .execute(); + + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + + // get all involved configurations + final List configIds = this.examConfigurationMapRecordMapper.selectByExample() + .where(ExamConfigurationMapRecordDynamicSqlSupport.id, isIn(ids)) + .build() + .execute() + .stream() + .map(rec -> rec.getConfigurationNodeId()) + .collect(Collectors.toList()); + + this.examConfigurationMapRecordMapper.deleteByExample() + .where(ExamConfigurationMapRecordDynamicSqlSupport.id, isIn(ids)) + .build() + .execute(); + + updateConfigurationStates(configIds) + .onError(error -> log.error("Unexpected error while update exam configuration state: ", error)); + + return ids.stream() + .map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP)) + .collect(Collectors.toList()); + }) + .onError(TransactionHandler::rollback); + } + private boolean isExamActive(final Long examId) { try { final boolean active = this.examRecordMapper.countByExample() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java index b8fd8bbd..af9f416a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java @@ -270,6 +270,40 @@ public class IndicatorDAOImpl implements IndicatorDAO { return getDependencies(bulkAction, selectionFunction); } + @Override + @Transactional + public Result> deleteAllForExam(final Long examId) { + return Result.> tryCatch(() -> { + + final List ids = this.indicatorRecordMapper.selectIdsByExample() + .where(IndicatorRecordDynamicSqlSupport.examId, isEqualTo(examId)) + .build() + .execute(); + + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + + // first delete all thresholds of indicators + this.thresholdRecordMapper.deleteByExample() + .where(ThresholdRecordDynamicSqlSupport.indicatorId, isIn(ids)) + .build() + .execute(); + + // then delete all indicators + this.indicatorRecordMapper.deleteByExample() + .where(IndicatorRecordDynamicSqlSupport.id, isIn(ids)) + .build() + .execute(); + + return ids.stream() + .map(id -> new EntityKey(id, EntityType.INDICATOR)) + .collect(Collectors.toList()); + + }) + .onError(TransactionHandler::rollback); + } + private Result> allIdsOfInstitution(final EntityKey institutionKey) { return Result.tryCatch(() -> this.indicatorRecordMapper.selectByExample() .leftJoin(ExamRecordDynamicSqlSupport.examRecord) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SEBRestrictionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SEBRestrictionServiceImpl.java index adc54dd2..f3ae3269 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SEBRestrictionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SEBRestrictionServiceImpl.java @@ -38,6 +38,7 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl.ExamDeletionEvent; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; @@ -232,6 +233,26 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService { error)); } + @EventListener(ExamDeletionEvent.class) + public void notifyExamDeletion(final ExamDeletionEvent event) { + + if (log.isDebugEnabled()) { + log.debug("ExamDeletionEvent received, process releaseSEBClientRestriction..."); + } + + event.ids.stream().forEach(examId -> { + this.examDAO + .byPK(examId) + .onSuccess(exam -> { + releaseSEBClientRestriction(exam) + .onError(error -> log.error( + "Failed to release SEB restrictions for finished exam: {}", + exam, + error)); + }); + }); + } + @Override public Result applySEBClientRestriction(final Exam exam) { return Result.tryCatch(() -> { diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 912a00ff..4384db8f 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -519,9 +519,9 @@ sebserver.exam.list.action.archive=Archive Selected Exams sebserver.exam.list.action.delete=Delete Selected Exams sebserver.exam.list.batch.archive.title=Archive all Exams in Batch Action sebserver.exam.list.batch.action.archive=Archive All -sebserver.exam.list.batch.action.archive.info=This batch action archives all selected exams below. To archive an exam it must be finished (Finished state)
If a particular exam is in a invalid state for archiving it will be ignored. Archive is an irreversible action and once an exam is archived it cannot be reactivated anymore,
please make sure all exams below shall be archived before applying the batch action. +sebserver.exam.list.batch.action.archive.info=This batch action archives all selected exams below. To archive an exam it must be finished (Finished state)
If a particular exam is in a invalid state for archiving it will be ignored.
Archive is an irreversible action and once an exam is archived it cannot be reactivated anymore,
please make sure all exams below shall be archived before applying the batch action. sebserver.exam.list.batch.delete.title=Delete all Exams in Batch Action -sebserver.exam.list.batch.action.delete=Delete Selected Exams +sebserver.exam.list.batch.action.delete=Delete All sebserver.exam.list.batch.action.delete.info=This batch action deletes all selected exams below.
If a particular exam is in a invalid state for deleting it will be ignored.
Delete is an action is an irreversible action and all deleted exams will be lost.
Please make sure that all selected exams below shall be deleted and use Cancel to abort the action if not so. sebserver.exam.consistency.title=Note: This exam is already running but has some missing settings