diff --git a/pom.xml b/pom.xml
index ef7a7725..6426509d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
jar
- 1.2.1
+ 1.2.2
${sebserver-version}
${sebserver-version}
UTF-8
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java
index 18135a48..a258846e 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java
@@ -30,6 +30,7 @@ import org.joda.time.DateTime;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
@@ -78,17 +79,20 @@ public class ExamDAOImpl implements ExamDAO {
private final ExamRecordMapper examRecordMapper;
private final ClientConnectionRecordMapper clientConnectionRecordMapper;
private final AdditionalAttributeRecordMapper additionalAttributeRecordMapper;
+ private final ApplicationEventPublisher applicationEventPublisher;
private final LmsAPIService lmsAPIService;
public ExamDAOImpl(
final ExamRecordMapper examRecordMapper,
final ClientConnectionRecordMapper clientConnectionRecordMapper,
final AdditionalAttributeRecordMapper additionalAttributeRecordMapper,
+ final ApplicationEventPublisher applicationEventPublisher,
final LmsAPIService lmsAPIService) {
this.examRecordMapper = examRecordMapper;
this.clientConnectionRecordMapper = clientConnectionRecordMapper;
this.additionalAttributeRecordMapper = additionalAttributeRecordMapper;
+ this.applicationEventPublisher = applicationEventPublisher;
this.lmsAPIService = lmsAPIService;
}
@@ -650,6 +654,9 @@ public class ExamDAOImpl implements ExamDAO {
final List ids = extractListOfPKs(all);
+ // notify exam deletition listener about following deletion, to cleanup stuff before deletion
+ this.applicationEventPublisher.publishEvent(new ExamDeletionEvent(ids));
+
this.examRecordMapper.deleteByExample()
.where(ExamRecordDynamicSqlSupport.id, isIn(ids))
.build()
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDeletionEvent.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDeletionEvent.java
new file mode 100644
index 00000000..0c2e2f11
--- /dev/null
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDeletionEvent.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
+
+import java.util.List;
+
+import org.springframework.context.ApplicationEvent;
+
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+
+public class ExamDeletionEvent extends ApplicationEvent {
+
+ private static final long serialVersionUID = -8910368901893082365L;
+
+ public final List ids;
+
+ public ExamDeletionEvent(final List ids) {
+ super(ids);
+ this.ids = Utils.immutableListOf(ids);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/RemoteProctoringRoomDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/RemoteProctoringRoomDAOImpl.java
index 9f11d9a0..2d4fef85 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/RemoteProctoringRoomDAOImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/RemoteProctoringRoomDAOImpl.java
@@ -246,11 +246,17 @@ public class RemoteProctoringRoomDAOImpl implements RemoteProctoringRoomDAO {
@Transactional
public Result> deleteRooms(final Long examId) {
final Result> tryCatch = Result.tryCatch(() -> {
- final List ids = this.remoteProctoringRoomRecordMapper.selectIdsByExample()
+ final List ids = this.remoteProctoringRoomRecordMapper
+ .selectIdsByExample()
.where(RemoteProctoringRoomRecordDynamicSqlSupport.examId, isEqualTo(examId))
.build()
.execute();
+ if (ids == null || ids.isEmpty()) {
+ log.info("No proctoring rooms found for exam to delete: {}", examId);
+ return Collections.emptyList();
+ }
+
this.remoteProctoringRoomRecordMapper.deleteByExample()
.where(RemoteProctoringRoomRecordDynamicSqlSupport.id, isIn(ids))
.build()
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/ExamAdminService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/ExamAdminService.java
index 51314f64..f1884dae 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/ExamAdminService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/ExamAdminService.java
@@ -16,6 +16,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringServi
public interface ExamAdminService {
+ /** Get the exam domain object for the exam identifier (PK).
+ *
+ * @param examId the exam identifier
+ * @return Result refer to the domain object or to an error when happened */
+ Result examForPK(Long examId);
+
/** Adds a default indicator that is defined by configuration to a given exam.
*
* @param exam The Exam to add the default indicator
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java
index 7c27aab8..88ec8c77 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java
@@ -106,6 +106,11 @@ public class ExamAdminServiceImpl implements ExamAdminService {
this.defaultIndicatorThresholds = defaultIndicatorThresholds;
}
+ @Override
+ public Result examForPK(final Long examId) {
+ return this.examDAO.byPK(examId);
+ }
+
@Override
public Result addDefaultIndicator(final Exam exam) {
return Result.tryCatch(() -> {
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ExamProctoringRoomServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ExamProctoringRoomServiceImpl.java
index 770e276f..90d2c1d0 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ExamProctoringRoomServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ExamProctoringRoomServiceImpl.java
@@ -21,12 +21,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
+import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
-import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
@@ -38,6 +38,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.RemoteProctoringRoomDAO;
+import ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl.ExamDeletionEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringRoomService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService;
@@ -137,16 +138,28 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
}
}
+ @EventListener(ExamDeletionEvent.class)
+ public void notifyExamDeletionEvent(final ExamDeletionEvent event) {
+ event.ids.forEach(examId -> {
+ try {
+
+ this.examAdminService.examForPK(examId)
+ .flatMap(this::disposeRoomsForExam)
+ .getOrThrow();
+
+ } catch (final Exception e) {
+ log.error("Failed to delete depending proctoring data for exam: {}", examId, e);
+ }
+ });
+ }
+
@Override
public Result disposeRoomsForExam(final Exam exam) {
- if (exam.status != ExamStatus.FINISHED) {
- log.warn("The exam has not been finished yet. No proctoring rooms will be deleted: {} / {}",
- exam.name,
- exam.externalId);
- }
return Result.tryCatch(() -> {
+ log.info("Dispose and deleting proctoring rooms for exam: {}", exam.externalId);
+
final ProctoringServiceSettings proctoringSettings = this.examAdminService
.getProctoringServiceSettings(exam.id)
.getOrThrow();
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java
index 836bcc91..e4157f39 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java
@@ -685,6 +685,7 @@ public class ZoomProctoringService implements ExamProctoringService {
private final static class ZoomRestTemplate {
+ private static final int LIZENSED_USER = 2;
private static final String API_TEST_ENDPOINT = "v2/users";
private static final String API_CREATE_USER_ENDPOINT = "v2/users";
private static final String API_DELETE_USER_ENDPOINT = "v2/users/{userid}?action=delete";
@@ -749,7 +750,7 @@ public class ZoomProctoringService implements ExamProctoringService {
API_USER_CUST_CREATE,
new CreateUserRequest.UserInfo(
roomName + "@" + host,
- 1,
+ LIZENSED_USER,
roomName,
API_ZOOM_ROOM_USER));