SEBSERV-419 implementation and local testing
This commit is contained in:
parent
16b2c8deb4
commit
fb8df62f59
11 changed files with 408 additions and 317 deletions
|
@ -86,6 +86,10 @@ public final class Exam implements GrantEntity {
|
||||||
ExamStatus.TEST_RUN.name(),
|
ExamStatus.TEST_RUN.name(),
|
||||||
ExamStatus.RUNNING.name());
|
ExamStatus.RUNNING.name());
|
||||||
|
|
||||||
|
public static final List<String> RUNNING_STATE_NAMES = Arrays.asList(
|
||||||
|
ExamStatus.TEST_RUN.name(),
|
||||||
|
ExamStatus.RUNNING.name());
|
||||||
|
|
||||||
@JsonProperty(EXAM.ATTR_ID)
|
@JsonProperty(EXAM.ATTR_ID)
|
||||||
public final Long id;
|
public final Long id;
|
||||||
|
|
||||||
|
|
|
@ -202,10 +202,10 @@ public class MonitoringProctoringService {
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
|
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
|
||||||
|
|
||||||
final TreeItem screeProcotringGroupAction = proctoringGUIService.getScreeProcotringGroupAction(group);
|
final TreeItem screeProctoringGroupAction = proctoringGUIService.getScreeProcotringGroupAction(group);
|
||||||
if (screeProcotringGroupAction != null) {
|
if (screeProctoringGroupAction != null) {
|
||||||
// update action
|
// update action
|
||||||
screeProcotringGroupAction.setText(i18nSupport.getText(new LocTextKey(
|
screeProctoringGroupAction.setText(i18nSupport.getText(new LocTextKey(
|
||||||
ActionDefinition.MONITOR_EXAM_VIEW_SCREEN_PROCTOR_GROUP.title.name,
|
ActionDefinition.MONITOR_EXAM_VIEW_SCREEN_PROCTOR_GROUP.title.name,
|
||||||
group.name,
|
group.name,
|
||||||
group.size)));
|
group.size)));
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
@ -124,6 +123,12 @@ public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSup
|
||||||
* @return Result refer to a collection of exams or to an error if happened */
|
* @return Result refer to a collection of exams or to an error if happened */
|
||||||
Result<Collection<Exam>> allThatNeedsStatusUpdate(long leadTime, long followupTime);
|
Result<Collection<Exam>> allThatNeedsStatusUpdate(long leadTime, long followupTime);
|
||||||
|
|
||||||
|
/** Quickly checks if an Exam is running or not (Sate RUNNING or TEST_RUN)
|
||||||
|
*
|
||||||
|
* @param examId The identifier of the exam to check
|
||||||
|
* @return true if the exam is in a running state */
|
||||||
|
boolean isRunning(Long examId);
|
||||||
|
|
||||||
/** Get a collection of all currently running exam identifiers
|
/** Get a collection of all currently running exam identifiers
|
||||||
*
|
*
|
||||||
* @return collection of all currently running exam identifiers */
|
* @return collection of all currently running exam identifiers */
|
||||||
|
|
|
@ -335,7 +335,7 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
isEqualTo(BooleanUtils.toInteger(true)))
|
isEqualTo(BooleanUtils.toInteger(true)))
|
||||||
.and(
|
.and(
|
||||||
ExamRecordDynamicSqlSupport.status,
|
ExamRecordDynamicSqlSupport.status,
|
||||||
isEqualTo(ExamStatus.RUNNING.name()))
|
isIn(Exam.RUNNING_STATE_NAMES))
|
||||||
.and(
|
.and(
|
||||||
ExamRecordDynamicSqlSupport.updating,
|
ExamRecordDynamicSqlSupport.updating,
|
||||||
isEqualTo(BooleanUtils.toInteger(false)))
|
isEqualTo(BooleanUtils.toInteger(false)))
|
||||||
|
@ -392,6 +392,27 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
.flatMap(this::toDomainModel);
|
.flatMap(this::toDomainModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public boolean isRunning(final Long examId) {
|
||||||
|
try {
|
||||||
|
final Long exists = this.examRecordMapper.countByExample()
|
||||||
|
.where(
|
||||||
|
id,
|
||||||
|
isEqualTo(examId))
|
||||||
|
.and(
|
||||||
|
status,
|
||||||
|
isIn(Exam.RUNNING_STATE_NAMES))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return exists >= 1;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Failed to check if exam is running: {} error: {}", examId, e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||||
public Result<Long> placeLock(final Long examId, final String updateId) {
|
public Result<Long> placeLock(final Long examId, final String updateId) {
|
||||||
|
@ -736,7 +757,7 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
||||||
.and(
|
.and(
|
||||||
ExamRecordDynamicSqlSupport.status,
|
ExamRecordDynamicSqlSupport.status,
|
||||||
isEqualTo(ExamStatus.RUNNING.name()))
|
isIn(Exam.RUNNING_STATE_NAMES))
|
||||||
.build()
|
.build()
|
||||||
.execute();
|
.execute();
|
||||||
});
|
});
|
||||||
|
@ -754,7 +775,7 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
||||||
.and(
|
.and(
|
||||||
ExamRecordDynamicSqlSupport.status,
|
ExamRecordDynamicSqlSupport.status,
|
||||||
isEqualTo(ExamStatus.RUNNING.name()))
|
isIn(Exam.RUNNING_STATE_NAMES))
|
||||||
.and(
|
.and(
|
||||||
ExamRecordDynamicSqlSupport.lmsAvailable,
|
ExamRecordDynamicSqlSupport.lmsAvailable,
|
||||||
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
||||||
|
|
|
@ -137,7 +137,8 @@ public class ExamSessionCacheService {
|
||||||
}
|
}
|
||||||
|
|
||||||
final ClientConnection clientConnection = getClientConnectionByToken(connectionToken);
|
final ClientConnection clientConnection = getClientConnectionByToken(connectionToken);
|
||||||
if (clientConnection == null) {
|
// TODO check running exam within cache instead of DB call
|
||||||
|
if (clientConnection == null || (clientConnection.examId != null && !examDAO.isRunning(clientConnection.examId))) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return this.internalClientConnectionDataFactory.createClientConnectionData(clientConnection);
|
return this.internalClientConnectionDataFactory.createClientConnectionData(clientConnection);
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class InternalClientConnectionDataFactory {
|
||||||
|
|
||||||
public ClientConnectionDataInternal createClientConnectionData(final ClientConnection clientConnection) {
|
public ClientConnectionDataInternal createClientConnectionData(final ClientConnection clientConnection) {
|
||||||
|
|
||||||
ClientConnectionDataInternal result;
|
final ClientConnectionDataInternal result;
|
||||||
if (clientConnection.status == ConnectionStatus.CLOSED
|
if (clientConnection.status == ConnectionStatus.CLOSED
|
||||||
|| clientConnection.status == ConnectionStatus.DISABLED) {
|
|| clientConnection.status == ConnectionStatus.DISABLED) {
|
||||||
|
|
||||||
|
|
|
@ -12,21 +12,18 @@ import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
|
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
@ -44,6 +41,7 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
|
|
||||||
private final ExamSessionCacheService examSessionCacheService;
|
private final ExamSessionCacheService examSessionCacheService;
|
||||||
private final SEBClientInstructionService sebClientInstructionService;
|
private final SEBClientInstructionService sebClientInstructionService;
|
||||||
|
private final ClientConnectionDAO clientConnectionDAO;
|
||||||
|
|
||||||
private final Set<String> pingKeys = new HashSet<>();
|
private final Set<String> pingKeys = new HashSet<>();
|
||||||
private final Map<String, String> pings = new ConcurrentHashMap<>();
|
private final Map<String, String> pings = new ConcurrentHashMap<>();
|
||||||
|
@ -51,10 +49,12 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
|
|
||||||
public SEBClientPingBatchService(
|
public SEBClientPingBatchService(
|
||||||
final ExamSessionCacheService examSessionCacheService,
|
final ExamSessionCacheService examSessionCacheService,
|
||||||
final SEBClientInstructionService sebClientInstructionService) {
|
final SEBClientInstructionService sebClientInstructionService,
|
||||||
|
final ClientConnectionDAO clientConnectionDAO) {
|
||||||
|
|
||||||
this.examSessionCacheService = examSessionCacheService;
|
this.examSessionCacheService = examSessionCacheService;
|
||||||
this.sebClientInstructionService = sebClientInstructionService;
|
this.sebClientInstructionService = sebClientInstructionService;
|
||||||
|
this.clientConnectionDAO = clientConnectionDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedDelayString = "${sebserver.webservice.api.exam.session.ping.batch.interval:500}")
|
@Scheduled(fixedDelayString = "${sebserver.webservice.api.exam.session.ping.batch.interval:500}")
|
||||||
|
@ -71,7 +71,7 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
try {
|
try {
|
||||||
this.pingKeys.clear();
|
this.pingKeys.clear();
|
||||||
this.pingKeys.addAll(this.pings.keySet());
|
this.pingKeys.addAll(this.pings.keySet());
|
||||||
this.pingKeys.stream().forEach(cid -> processPing(
|
this.pingKeys.forEach(cid -> processPing(
|
||||||
cid,
|
cid,
|
||||||
this.pings.remove(cid),
|
this.pings.remove(cid),
|
||||||
Utils.getMillisecondsNow()));
|
Utils.getMillisecondsNow()));
|
||||||
|
@ -94,10 +94,8 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
final String instruction = this.instructions.remove(connectionToken);
|
final String instruction = this.instructions.remove(connectionToken);
|
||||||
|
|
||||||
if (instructionConfirm != null) {
|
if (instructionConfirm != null) {
|
||||||
System.out.println("************ put instructionConfirm: " + instructionConfirm + " instructions: "
|
|
||||||
+ this.instructions);
|
|
||||||
this.pings.put(connectionToken, instructionConfirm);
|
this.pings.put(connectionToken, instructionConfirm);
|
||||||
// // TODO is this a good idea or is there another better way to deal with instruction confirm synchronization?
|
|
||||||
if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
|
if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -105,9 +103,6 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
this.pings.put(connectionToken, StringUtils.EMPTY);
|
this.pings.put(connectionToken, StringUtils.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// System.out.println(
|
|
||||||
// "**************** notifyPing instructionConfirm: " + instructionConfirm + " pings: " + this.pings);
|
|
||||||
|
|
||||||
return instruction;
|
return instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,19 +121,13 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
if (connectionData != null) {
|
if (connectionData != null) {
|
||||||
if (connectionData.clientConnection.status == ClientConnection.ConnectionStatus.DISABLED) {
|
if (connectionData.clientConnection.status == ClientConnection.ConnectionStatus.DISABLED) {
|
||||||
// SEBSERV-440 send quit instruction to SEB
|
// SEBSERV-440 send quit instruction to SEB
|
||||||
sebClientInstructionService.registerInstruction(
|
sendQuitInstruction(connectionToken, connectionData.clientConnection.examId);
|
||||||
connectionData.clientConnection.examId,
|
|
||||||
ClientInstruction.InstructionType.SEB_QUIT,
|
|
||||||
Collections.emptyMap(),
|
|
||||||
connectionData.clientConnection.connectionToken,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionData.notifyPing(timestamp);
|
connectionData.notifyPing(timestamp);
|
||||||
} else {
|
} else {
|
||||||
log.error("Failed to get ClientConnectionDataInternal for: {}", connectionToken);
|
log.warn("Failed to get ClientConnectionDataInternal probably due to finished Exam for: {}.", connectionToken);
|
||||||
|
sendQuitInstruction(connectionToken,null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(instructionConfirm)) {
|
if (StringUtils.isNotBlank(instructionConfirm)) {
|
||||||
|
@ -154,4 +143,38 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
this.instructions.put(connectionToken, instructionJSON);
|
this.instructions.put(connectionToken, instructionJSON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendQuitInstruction(final String connectionToken, final Long examId) {
|
||||||
|
|
||||||
|
Long _examId = examId;
|
||||||
|
if (examId == null) {
|
||||||
|
final Result<ClientConnection> clientConnectionResult = clientConnectionDAO
|
||||||
|
.byConnectionToken(connectionToken);
|
||||||
|
|
||||||
|
if (clientConnectionResult.hasError()) {
|
||||||
|
log.error(
|
||||||
|
"Failed to get examId for client connection token: {} error: {}",
|
||||||
|
connectionToken,
|
||||||
|
clientConnectionResult.getError().getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
_examId = clientConnectionResult.get().examId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_examId != null) {
|
||||||
|
|
||||||
|
log.info("Send automated quit instruction to SEB for connection token: {}", connectionToken);
|
||||||
|
|
||||||
|
// TODO add SEB event log that SEB Server has automatically send quit instruction to SEB
|
||||||
|
|
||||||
|
sebClientInstructionService.registerInstruction(
|
||||||
|
_examId,
|
||||||
|
ClientInstruction.InstructionType.SEB_QUIT,
|
||||||
|
Collections.emptyMap(),
|
||||||
|
connectionToken,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class RemoteProctoringRoomServiceImpl implements RemoteProctoringRoomServ
|
||||||
|
|
||||||
final Collection<String> currentlyInBreakoutRooms = this.remoteProctoringRoomDAO
|
final Collection<String> currentlyInBreakoutRooms = this.remoteProctoringRoomDAO
|
||||||
.getConnectionsInBreakoutRooms(examId)
|
.getConnectionsInBreakoutRooms(examId)
|
||||||
.getOrElse(() -> Collections.emptyList());
|
.getOrElse(Collections::emptyList);
|
||||||
|
|
||||||
if (currentlyInBreakoutRooms.isEmpty()) {
|
if (currentlyInBreakoutRooms.isEmpty()) {
|
||||||
return this.clientConnectionDAO
|
return this.clientConnectionDAO
|
||||||
|
@ -132,52 +132,58 @@ public class RemoteProctoringRoomServiceImpl implements RemoteProctoringRoomServ
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProctoringCollectingRooms() {
|
public void updateProctoringCollectingRooms() {
|
||||||
try {
|
|
||||||
|
|
||||||
// Applying to collecting room
|
// NOTE: Since life proctoring is not supported anymore, we disable automated updates here
|
||||||
this.clientConnectionDAO
|
|
||||||
.getAllForProctoringUpdateActive()
|
|
||||||
.getOrThrow()
|
|
||||||
.stream()
|
|
||||||
.forEach(this::assignToCollectingRoom);
|
|
||||||
|
|
||||||
// Dispose from collecting room
|
// try {
|
||||||
this.clientConnectionDAO
|
//
|
||||||
.getAllForProctoringUpdateInactive()
|
// // Applying to collecting room
|
||||||
.getOrThrow()
|
// this.clientConnectionDAO
|
||||||
.stream()
|
// .getAllForProctoringUpdateActive()
|
||||||
.forEach(this::removeFromRoom);
|
// .getOrThrow()
|
||||||
|
// .forEach(this::assignToCollectingRoom);
|
||||||
} catch (final Exception e) {
|
//
|
||||||
log.error("Unexpected error while trying to update proctoring collecting rooms: ", e);
|
// // Dispose from collecting room
|
||||||
}
|
// this.clientConnectionDAO
|
||||||
|
// .getAllForProctoringUpdateInactive()
|
||||||
|
// .getOrThrow()
|
||||||
|
// .forEach(this::removeFromRoom);
|
||||||
|
//
|
||||||
|
// } catch (final Exception e) {
|
||||||
|
// log.error("Unexpected error while trying to update proctoring collecting rooms: ", e);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener(ExamDeletionEvent.class)
|
@EventListener(ExamDeletionEvent.class)
|
||||||
public void notifyExamDeletionEvent(final ExamDeletionEvent event) {
|
public void notifyExamDeletionEvent(final ExamDeletionEvent event) {
|
||||||
event.ids.forEach(examId -> {
|
|
||||||
try {
|
|
||||||
|
|
||||||
this.examAdminService
|
// NOTE: Since life proctoring is not supported anymore, we disable automated updates here
|
||||||
.examForPK(examId)
|
|
||||||
.flatMap(this::disposeRoomsForExam)
|
|
||||||
.getOrThrow();
|
|
||||||
|
|
||||||
} catch (final Exception e) {
|
// event.ids.forEach(examId -> {
|
||||||
log.error("Failed to delete depending proctoring data for exam: {}", examId, e);
|
// 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);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener
|
@EventListener
|
||||||
public void notifyExamFinished(final ExamFinishedEvent event) {
|
public void notifyExamFinished(final ExamFinishedEvent event) {
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
// NOTE: Since life proctoring is not supported anymore, we disable automated updates here
|
||||||
log.debug("ExamFinishedEvent received, process disposeRoomsForExam...");
|
|
||||||
}
|
|
||||||
|
|
||||||
disposeRoomsForExam(event.exam)
|
// if (log.isDebugEnabled()) {
|
||||||
.onError(error -> log.error("Failed to dispose rooms for finished exam: {}", event.exam, error));
|
// log.debug("ExamFinishedEvent received, process disposeRoomsForExam...");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// disposeRoomsForExam(event.exam)
|
||||||
|
// .onError(error -> log.error("Failed to dispose rooms for finished exam: {}", event.exam, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -386,7 +386,7 @@ class ScreenProctoringAPIBinding {
|
||||||
|
|
||||||
void synchronizeUserAccounts(final Exam exam) {
|
void synchronizeUserAccounts(final Exam exam) {
|
||||||
try {
|
try {
|
||||||
|
final ScreenProctoringServiceOAuthTemplate apiTemplate = getAPITemplate(null);
|
||||||
exam.supporter.forEach(userUUID -> synchronizeUserAccount(userUUID, apiTemplate));
|
exam.supporter.forEach(userUUID -> synchronizeUserAccount(userUUID, apiTemplate));
|
||||||
if (exam.owner != null) {
|
if (exam.owner != null) {
|
||||||
synchronizeUserAccount(exam.owner, apiTemplate);
|
synchronizeUserAccount(exam.owner, apiTemplate);
|
||||||
|
@ -1156,12 +1156,24 @@ class ScreenProctoringAPIBinding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScreenProctoringServiceOAuthTemplate apiTemplate = null;
|
private ScreenProctoringServiceOAuthTemplate apiTemplateExam = null;
|
||||||
|
private ScreenProctoringServiceOAuthTemplate apiTemplateBundle = null;
|
||||||
private ScreenProctoringServiceOAuthTemplate getAPITemplate(final Long examId) {
|
private ScreenProctoringServiceOAuthTemplate getAPITemplate(final Long examId) {
|
||||||
if (this.apiTemplate == null || !this.apiTemplate.isValid(examId)) {
|
if (examId == null) {
|
||||||
if (examId != null) {
|
if (apiTemplateBundle == null) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Create new ScreenProctoringServiceOAuthTemplate for bundle");
|
||||||
|
}
|
||||||
|
|
||||||
|
final WebserviceInfo.ScreenProctoringServiceBundle bundle = this.webserviceInfo
|
||||||
|
.getScreenProctoringServiceBundle();
|
||||||
|
|
||||||
|
this.testConnection(bundle).getOrThrow();
|
||||||
|
this.apiTemplateBundle = new ScreenProctoringServiceOAuthTemplate(this, bundle);
|
||||||
|
}
|
||||||
|
return apiTemplateBundle;
|
||||||
|
} else {
|
||||||
|
if (this.apiTemplateExam == null || !this.apiTemplateExam.isValid(examId)) {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
||||||
}
|
}
|
||||||
|
@ -1170,27 +1182,44 @@ class ScreenProctoringAPIBinding {
|
||||||
.getScreenProctoringSettings(new EntityKey(examId, EntityType.EXAM))
|
.getScreenProctoringSettings(new EntityKey(examId, EntityType.EXAM))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
this.testConnection(settings).getOrThrow();
|
this.testConnection(settings).getOrThrow();
|
||||||
this.apiTemplate = new ScreenProctoringServiceOAuthTemplate(this, settings);
|
this.apiTemplateExam = new ScreenProctoringServiceOAuthTemplate(this, settings);
|
||||||
|
|
||||||
} else if (this.webserviceInfo.getScreenProctoringServiceBundle().bundled) {
|
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
|
||||||
}
|
|
||||||
|
|
||||||
final WebserviceInfo.ScreenProctoringServiceBundle bundle = this.webserviceInfo
|
|
||||||
.getScreenProctoringServiceBundle();
|
|
||||||
|
|
||||||
this.testConnection(bundle).getOrThrow();
|
|
||||||
this.apiTemplate = new ScreenProctoringServiceOAuthTemplate(this, bundle);
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("No SPS API access information found!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return apiTemplateExam;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.apiTemplate;
|
// if (this.apiTemplate == null || !this.apiTemplate.isValid(examId)) {
|
||||||
|
// if (examId != null) {
|
||||||
|
//
|
||||||
|
// if (log.isDebugEnabled()) {
|
||||||
|
// log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// final ScreenProctoringSettings settings = this.proctoringSettingsDAO
|
||||||
|
// .getScreenProctoringSettings(new EntityKey(examId, EntityType.EXAM))
|
||||||
|
// .getOrThrow();
|
||||||
|
// this.testConnection(settings).getOrThrow();
|
||||||
|
// this.apiTemplate = new ScreenProctoringServiceOAuthTemplate(this, settings);
|
||||||
|
//
|
||||||
|
// } else if (this.webserviceInfo.getScreenProctoringServiceBundle().bundled) {
|
||||||
|
//
|
||||||
|
// if (log.isDebugEnabled()) {
|
||||||
|
// log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// final WebserviceInfo.ScreenProctoringServiceBundle bundle = this.webserviceInfo
|
||||||
|
// .getScreenProctoringServiceBundle();
|
||||||
|
//
|
||||||
|
// this.testConnection(bundle).getOrThrow();
|
||||||
|
// this.apiTemplate = new ScreenProctoringServiceOAuthTemplate(this, bundle);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// throw new IllegalStateException("No SPS API access information found!");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return this.apiTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> getSupporterIds(final Exam exam) {
|
private static List<String> getSupporterIds(final Exam exam) {
|
||||||
|
|
|
@ -284,6 +284,7 @@ public class ExamMonitoringController {
|
||||||
.flatMap(authorization::checkModify)
|
.flatMap(authorization::checkModify)
|
||||||
.flatMap(examSessionService::toggleTestRun)
|
.flatMap(examSessionService::toggleTestRun)
|
||||||
.map(exam -> {
|
.map(exam -> {
|
||||||
|
examSessionService.flushCache(exam);
|
||||||
if (exam.status == Exam.ExamStatus.TEST_RUN) {
|
if (exam.status == Exam.ExamStatus.TEST_RUN) {
|
||||||
applicationEventPublisher.publishEvent(new ExamStartedEvent(exam));
|
applicationEventPublisher.publishEvent(new ExamStartedEvent(exam));
|
||||||
} else if (exam.status == Exam.ExamStatus.UP_COMING) {
|
} else if (exam.status == Exam.ExamStatus.UP_COMING) {
|
||||||
|
|
|
@ -3772,236 +3772,237 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClientConnectionDAO clientConnectionDAO;
|
private ClientConnectionDAO clientConnectionDAO;
|
||||||
|
|
||||||
@Test
|
// NOTE: Not supported anymore
|
||||||
@Order(28)
|
// @Test
|
||||||
// *************************************
|
// @Order(28)
|
||||||
// Use Case 28: Login as admin and connect with SEBs to running exam with procotring enabled
|
// // *************************************
|
||||||
// - Get Exam (running)
|
// // Use Case 28: Login as admin and connect with SEBs to running exam with procotring enabled
|
||||||
// - start some SEB clients connecting to running exam
|
// // - Get Exam (running)
|
||||||
// - Check collecting rooms created
|
// // - start some SEB clients connecting to running exam
|
||||||
public void testUsecase28_TestExamProctoring() throws IOException {
|
// // - Check collecting rooms created
|
||||||
|
// public void testUsecase28_TestExamProctoring() throws IOException {
|
||||||
final RestServiceImpl restService = createRestServiceForUser(
|
//
|
||||||
"admin",
|
// final RestServiceImpl restService = createRestServiceForUser(
|
||||||
"admin",
|
// "admin",
|
||||||
new GetExamPage(),
|
// "admin",
|
||||||
new GetExamProctoringSettings(),
|
// new GetExamPage(),
|
||||||
new SaveExamProctoringSettings(),
|
// new GetExamProctoringSettings(),
|
||||||
new IsTownhallRoomAvailable(),
|
// new SaveExamProctoringSettings(),
|
||||||
new GetCollectingRooms(),
|
// new IsTownhallRoomAvailable(),
|
||||||
new GetClientConfigPage(),
|
// new GetCollectingRooms(),
|
||||||
new ActivateClientConfig(),
|
// new GetClientConfigPage(),
|
||||||
new NewClientConfig(),
|
// new ActivateClientConfig(),
|
||||||
new GetClientConfig(),
|
// new NewClientConfig(),
|
||||||
new GetProctorRoomConnection(),
|
// new GetClientConfig(),
|
||||||
new GetCollectingRoomConnections(),
|
// new GetProctorRoomConnection(),
|
||||||
new NotifyProctoringRoomOpened(),
|
// new GetCollectingRoomConnections(),
|
||||||
new SendProctoringReconfigurationAttributes(),
|
// new NotifyProctoringRoomOpened(),
|
||||||
new GetTownhallRoom(),
|
// new SendProctoringReconfigurationAttributes(),
|
||||||
new OpenTownhallRoom(),
|
// new GetTownhallRoom(),
|
||||||
new CloseProctoringRoom());
|
// new OpenTownhallRoom(),
|
||||||
|
// new CloseProctoringRoom());
|
||||||
// get exam
|
//
|
||||||
final Result<Page<Exam>> exams = restService
|
// // get exam
|
||||||
.getBuilder(GetExamPage.class)
|
// final Result<Page<Exam>> exams = restService
|
||||||
.call();
|
// .getBuilder(GetExamPage.class)
|
||||||
|
// .call();
|
||||||
assertNotNull(exams);
|
//
|
||||||
assertFalse(exams.hasError());
|
// assertNotNull(exams);
|
||||||
final Page<Exam> examPage = exams.get();
|
// assertFalse(exams.hasError());
|
||||||
assertFalse(examPage.isEmpty());
|
// final Page<Exam> examPage = exams.get();
|
||||||
|
// assertFalse(examPage.isEmpty());
|
||||||
final Exam runningExam = examPage.content
|
//
|
||||||
.stream()
|
// final Exam runningExam = examPage.content
|
||||||
.filter(exam -> exam.status == ExamStatus.RUNNING)
|
// .stream()
|
||||||
.findFirst()
|
// .filter(exam -> exam.status == ExamStatus.RUNNING)
|
||||||
.orElse(null);
|
// .findFirst()
|
||||||
|
// .orElse(null);
|
||||||
assertNotNull(runningExam);
|
//
|
||||||
assertTrue(runningExam.status == ExamStatus.RUNNING);
|
// assertNotNull(runningExam);
|
||||||
|
// assertTrue(runningExam.status == ExamStatus.RUNNING);
|
||||||
final Result<ProctoringServiceSettings> pSettings = restService
|
//
|
||||||
.getBuilder(GetExamProctoringSettings.class)
|
// final Result<ProctoringServiceSettings> pSettings = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetExamProctoringSettings.class)
|
||||||
.call();
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
|
// .call();
|
||||||
assertNotNull(pSettings);
|
//
|
||||||
assertFalse(pSettings.hasError());
|
// assertNotNull(pSettings);
|
||||||
final ProctoringServiceSettings proctoringServiceSettings = pSettings.get();
|
// assertFalse(pSettings.hasError());
|
||||||
assertTrue(proctoringServiceSettings.enableProctoring);
|
// final ProctoringServiceSettings proctoringServiceSettings = pSettings.get();
|
||||||
assertEquals("https://test.proc/service", proctoringServiceSettings.serverURL);
|
// assertTrue(proctoringServiceSettings.enableProctoring);
|
||||||
|
// assertEquals("https://test.proc/service", proctoringServiceSettings.serverURL);
|
||||||
// start some SEB connections for this exam
|
//
|
||||||
|
// // start some SEB connections for this exam
|
||||||
// create SEB Client Config without password protection
|
//
|
||||||
Result<SEBClientConfig> newConfigResponse = restService
|
// // create SEB Client Config without password protection
|
||||||
.getBuilder(NewClientConfig.class)
|
// Result<SEBClientConfig> newConfigResponse = restService
|
||||||
.withFormParam(Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME, "No Password Protection")
|
// .getBuilder(NewClientConfig.class)
|
||||||
.withFormParam(SEBClientConfig.ATTR_FALLBACK, Constants.TRUE_STRING)
|
// .withFormParam(Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME, "No Password Protection")
|
||||||
.withFormParam(SEBClientConfig.ATTR_FALLBACK_START_URL, "http://fallback.com/fallback")
|
// .withFormParam(SEBClientConfig.ATTR_FALLBACK, Constants.TRUE_STRING)
|
||||||
.withFormParam(SEBClientConfig.ATTR_FALLBACK_TIMEOUT, "100")
|
// .withFormParam(SEBClientConfig.ATTR_FALLBACK_START_URL, "http://fallback.com/fallback")
|
||||||
.withFormParam(SEBClientConfig.ATTR_FALLBACK_ATTEMPTS, "5")
|
// .withFormParam(SEBClientConfig.ATTR_FALLBACK_TIMEOUT, "100")
|
||||||
.withFormParam(SEBClientConfig.ATTR_FALLBACK_ATTEMPT_INTERVAL, "5")
|
// .withFormParam(SEBClientConfig.ATTR_FALLBACK_ATTEMPTS, "5")
|
||||||
.withFormParam(SEBClientConfig.ATTR_CONFIG_PURPOSE, SEBClientConfig.ConfigPurpose.START_EXAM.name())
|
// .withFormParam(SEBClientConfig.ATTR_FALLBACK_ATTEMPT_INTERVAL, "5")
|
||||||
.call();
|
// .withFormParam(SEBClientConfig.ATTR_CONFIG_PURPOSE, SEBClientConfig.ConfigPurpose.START_EXAM.name())
|
||||||
|
// .call();
|
||||||
assertNotNull(newConfigResponse);
|
//
|
||||||
assertFalse(newConfigResponse.hasError());
|
// assertNotNull(newConfigResponse);
|
||||||
final SEBClientConfig sebClientConfig = newConfigResponse.get();
|
// assertFalse(newConfigResponse.hasError());
|
||||||
assertEquals("No Password Protection", sebClientConfig.name);
|
// final SEBClientConfig sebClientConfig = newConfigResponse.get();
|
||||||
assertFalse(sebClientConfig.isActive());
|
// assertEquals("No Password Protection", sebClientConfig.name);
|
||||||
assertEquals("http://fallback.com/fallback", sebClientConfig.fallbackStartURL);
|
// assertFalse(sebClientConfig.isActive());
|
||||||
|
// assertEquals("http://fallback.com/fallback", sebClientConfig.fallbackStartURL);
|
||||||
// activate the new Client Configuration
|
//
|
||||||
restService
|
// // activate the new Client Configuration
|
||||||
.getBuilder(ActivateClientConfig.class)
|
// restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, sebClientConfig.getModelId())
|
// .getBuilder(ActivateClientConfig.class)
|
||||||
.call();
|
// .withURIVariable(API.PARAM_MODEL_ID, sebClientConfig.getModelId())
|
||||||
|
// .call();
|
||||||
newConfigResponse = restService.getBuilder(GetClientConfig.class)
|
//
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, sebClientConfig.getModelId())
|
// newConfigResponse = restService.getBuilder(GetClientConfig.class)
|
||||||
.call();
|
// .withURIVariable(API.PARAM_MODEL_ID, sebClientConfig.getModelId())
|
||||||
|
// .call();
|
||||||
final SEBClientConfig clientConfig = newConfigResponse.get();
|
//
|
||||||
assertTrue(clientConfig.isActive());
|
// final SEBClientConfig clientConfig = newConfigResponse.get();
|
||||||
final ClientCredentials credentials = this.sebClientConfigDAO
|
// assertTrue(clientConfig.isActive());
|
||||||
.getSEBClientCredentials(clientConfig.getModelId())
|
// final ClientCredentials credentials = this.sebClientConfigDAO
|
||||||
.getOrThrow();
|
// .getSEBClientCredentials(clientConfig.getModelId())
|
||||||
|
// .getOrThrow();
|
||||||
assertTrue(clientConfig.isActive());
|
//
|
||||||
|
// assertTrue(clientConfig.isActive());
|
||||||
// simulate a SEB connection...
|
//
|
||||||
try {
|
// // simulate a SEB connection...
|
||||||
new SEBClientBot(
|
// try {
|
||||||
credentials.clientIdAsString(),
|
// new SEBClientBot(
|
||||||
this.cryptor.decrypt(credentials.secret).getOrThrow().toString(),
|
// credentials.clientIdAsString(),
|
||||||
runningExam.getModelId(),
|
// this.cryptor.decrypt(credentials.secret).getOrThrow().toString(),
|
||||||
String.valueOf(runningExam.institutionId),
|
// runningExam.getModelId(),
|
||||||
false);
|
// String.valueOf(runningExam.institutionId),
|
||||||
|
// false);
|
||||||
Thread.sleep(1000);
|
//
|
||||||
|
// Thread.sleep(1000);
|
||||||
this.examProcotringRoomService.updateProctoringCollectingRooms();
|
//
|
||||||
|
// this.examProcotringRoomService.updateProctoringCollectingRooms();
|
||||||
// check collecting room was created
|
//
|
||||||
final Collection<RemoteProctoringRoom> collectingRooms = restService
|
// // check collecting room was created
|
||||||
.getBuilder(GetCollectingRooms.class)
|
// final Collection<RemoteProctoringRoom> collectingRooms = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetCollectingRooms.class)
|
||||||
.call()
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
assertNotNull(collectingRooms);
|
//
|
||||||
assertFalse(collectingRooms.isEmpty());
|
// assertNotNull(collectingRooms);
|
||||||
// Two rooms a two people for four connections
|
// assertFalse(collectingRooms.isEmpty());
|
||||||
assertEquals(2, collectingRooms.size());
|
// // Two rooms a two people for four connections
|
||||||
final RemoteProctoringRoom room1 = collectingRooms.iterator().next();
|
// assertEquals(2, collectingRooms.size());
|
||||||
assertEquals(2, room1.roomSize.intValue());
|
// final RemoteProctoringRoom room1 = collectingRooms.iterator().next();
|
||||||
assertFalse(room1.townhallRoom);
|
// assertEquals(2, room1.roomSize.intValue());
|
||||||
|
// assertFalse(room1.townhallRoom);
|
||||||
final ProctoringRoomConnection proctoringRoomConnection = restService
|
//
|
||||||
.getBuilder(GetProctorRoomConnection.class)
|
// final ProctoringRoomConnection proctoringRoomConnection = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetProctorRoomConnection.class)
|
||||||
.withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room1.name)
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.call()
|
// .withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room1.name)
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
assertNotNull(proctoringRoomConnection);
|
//
|
||||||
assertEquals(room1.name, proctoringRoomConnection.roomName);
|
// assertNotNull(proctoringRoomConnection);
|
||||||
assertNotNull(proctoringRoomConnection.accessToken);
|
// assertEquals(room1.name, proctoringRoomConnection.roomName);
|
||||||
|
// assertNotNull(proctoringRoomConnection.accessToken);
|
||||||
// notify room open
|
//
|
||||||
restService
|
// // notify room open
|
||||||
.getBuilder(NotifyProctoringRoomOpened.class)
|
// restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(NotifyProctoringRoomOpened.class)
|
||||||
.withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room1.name)
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.call()
|
// .withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room1.name)
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
// reconfigure clients in room
|
//
|
||||||
restService
|
// // reconfigure clients in room
|
||||||
.getBuilder(SendProctoringReconfigurationAttributes.class)
|
// restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(SendProctoringReconfigurationAttributes.class)
|
||||||
.withQueryParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, room1.name)
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.withQueryParam(API.EXAM_PROCTORING_ATTR_RECEIVE_AUDIO, "true")
|
// .withQueryParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, room1.name)
|
||||||
.withQueryParam(API.EXAM_PROCTORING_ATTR_RECEIVE_VIDEO, "true")
|
// .withQueryParam(API.EXAM_PROCTORING_ATTR_RECEIVE_AUDIO, "true")
|
||||||
.withQueryParam(API.EXAM_PROCTORING_ATTR_ALLOW_CHAT, "true")
|
// .withQueryParam(API.EXAM_PROCTORING_ATTR_RECEIVE_VIDEO, "true")
|
||||||
.call()
|
// .withQueryParam(API.EXAM_PROCTORING_ATTR_ALLOW_CHAT, "true")
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
final Collection<ClientConnection> collection = restService
|
//
|
||||||
.getBuilder(GetCollectingRoomConnections.class)
|
// final Collection<ClientConnection> collection = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetCollectingRoomConnections.class)
|
||||||
.withQueryParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, room1.name)
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.call()
|
// .withQueryParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, room1.name)
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
assertNotNull(collection);
|
//
|
||||||
assertFalse(collection.isEmpty());
|
// assertNotNull(collection);
|
||||||
assertEquals(2, collection.size());
|
// assertFalse(collection.isEmpty());
|
||||||
final ClientConnection connection = collection.iterator().next();
|
// assertEquals(2, collection.size());
|
||||||
assertEquals(runningExam.id, connection.examId);
|
// final ClientConnection connection = collection.iterator().next();
|
||||||
// this is because the Json model do not contian certain attributes due to performance
|
// assertEquals(runningExam.id, connection.examId);
|
||||||
assertNull(connection.remoteProctoringRoomId);
|
// // this is because the Json model do not contian certain attributes due to performance
|
||||||
// we can geht the room number by getting it directyl from the record
|
// assertNull(connection.remoteProctoringRoomId);
|
||||||
final ClientConnection clientConnection = this.clientConnectionDAO.byPK(connection.id).get();
|
// // we can geht the room number by getting it directyl from the record
|
||||||
assertNotNull(clientConnection.remoteProctoringRoomId);
|
// final ClientConnection clientConnection = this.clientConnectionDAO.byPK(connection.id).get();
|
||||||
|
// assertNotNull(clientConnection.remoteProctoringRoomId);
|
||||||
// get and open townhall
|
//
|
||||||
final String townhallActive = restService
|
// // get and open townhall
|
||||||
.getBuilder(IsTownhallRoomAvailable.class)
|
// final String townhallActive = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(IsTownhallRoomAvailable.class)
|
||||||
.call()
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
assertEquals("true", townhallActive);
|
//
|
||||||
|
// assertEquals("true", townhallActive);
|
||||||
// check no Townhallroom yet
|
//
|
||||||
RemoteProctoringRoom townhallRoom = restService
|
// // check no Townhallroom yet
|
||||||
.getBuilder(GetTownhallRoom.class)
|
// RemoteProctoringRoom townhallRoom = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetTownhallRoom.class)
|
||||||
.call()
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.get();
|
// .call()
|
||||||
assertEquals(RemoteProctoringRoom.NULL_ROOM, townhallRoom);
|
// .get();
|
||||||
|
// assertEquals(RemoteProctoringRoom.NULL_ROOM, townhallRoom);
|
||||||
// open townhall room
|
//
|
||||||
final ProctoringRoomConnection townhallRoomConntection = restService
|
// // open townhall room
|
||||||
.getBuilder(OpenTownhallRoom.class)
|
// final ProctoringRoomConnection townhallRoomConntection = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(OpenTownhallRoom.class)
|
||||||
.call()
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
assertNotNull(townhallRoomConntection);
|
//
|
||||||
|
// assertNotNull(townhallRoomConntection);
|
||||||
// check Townhallroom is available yet
|
//
|
||||||
townhallRoom = restService
|
// // check Townhallroom is available yet
|
||||||
.getBuilder(GetTownhallRoom.class)
|
// townhallRoom = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetTownhallRoom.class)
|
||||||
.call()
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.get();
|
// .call()
|
||||||
assertTrue(townhallRoom.townhallRoom);
|
// .get();
|
||||||
assertEquals(townhallRoom.name, townhallRoomConntection.roomName);
|
// assertTrue(townhallRoom.townhallRoom);
|
||||||
|
// assertEquals(townhallRoom.name, townhallRoomConntection.roomName);
|
||||||
// close townhall room
|
//
|
||||||
restService
|
// // close townhall room
|
||||||
.getBuilder(CloseProctoringRoom.class)
|
// restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(CloseProctoringRoom.class)
|
||||||
.withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, townhallRoom.name)
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.call()
|
// .withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, townhallRoom.name)
|
||||||
.get();
|
// .call()
|
||||||
|
// .get();
|
||||||
townhallRoom = restService
|
//
|
||||||
.getBuilder(GetTownhallRoom.class)
|
// townhallRoom = restService
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
// .getBuilder(GetTownhallRoom.class)
|
||||||
.call()
|
// .withURIVariable(API.PARAM_MODEL_ID, runningExam.getModelId())
|
||||||
.get();
|
// .call()
|
||||||
assertEquals(RemoteProctoringRoom.NULL_ROOM, townhallRoom);
|
// .get();
|
||||||
|
// assertEquals(RemoteProctoringRoom.NULL_ROOM, townhallRoom);
|
||||||
Thread.sleep(5000);
|
//
|
||||||
|
// Thread.sleep(5000);
|
||||||
} catch (final Exception e) {
|
//
|
||||||
fail(e.getMessage());
|
// } catch (final Exception e) {
|
||||||
}
|
// fail(e.getMessage());
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(29)
|
@Order(29)
|
||||||
|
|
Loading…
Reference in a new issue