From 7d647cc9c21dc8ea8e45c9368002c203e52155b5 Mon Sep 17 00:00:00 2001 From: anhefti Date: Mon, 20 Sep 2021 15:46:20 +0200 Subject: [PATCH] fixed notification changes in GUI --- .../seb/sebserver/gui/GuiServiceInfo.java | 10 +++++++- .../content/MonitoringClientConnection.java | 10 +++----- .../gui/content/MonitoringRunningExam.java | 7 +++++- .../gui/service/push/ServerPushService.java | 8 +++--- .../session/ClientConnectionDetails.java | 25 ++++++++++--------- .../session/ClientConnectionTable.java | 19 ++++++++------ .../SEBClientNotificationServiceImpl.java | 13 +++++++--- .../ethz/seb/sebserver/gbl/util/ReplTest.java | 6 +++++ 8 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/GuiServiceInfo.java b/src/main/java/ch/ethz/seb/sebserver/gui/GuiServiceInfo.java index 3402fe8c..b45c66c5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/GuiServiceInfo.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/GuiServiceInfo.java @@ -28,6 +28,7 @@ public class GuiServiceInfo { private final String contextPath; private final UriComponentsBuilder internalServerURIBuilder; private final UriComponentsBuilder externalServerURIBuilder; + private final boolean distributedSetup; public GuiServiceInfo( @Value("${server.address}") final String internalServer, @@ -36,7 +37,8 @@ public class GuiServiceInfo { @Value("${sebserver.gui.http.external.servername}") final String externalServer, @Value("${sebserver.gui.http.external.port}") final String externalPort, @Value("${sebserver.gui.entrypoint:/gui}") final String entryPoint, - @Value("${server.servlet.context-path:/}") final String contextPath) { + @Value("${server.servlet.context-path:/}") final String contextPath, + @Value("${sebserver.webservice.distributed:false}") final boolean distributedSetup) { if (StringUtils.isBlank(externalScheme)) { throw new RuntimeException("Missing mandatory inital parameter sebserver.gui.http.external.servername"); @@ -69,6 +71,8 @@ public class GuiServiceInfo { if (StringUtils.isNotBlank(contextPath) && !contextPath.equals("/")) { this.externalServerURIBuilder.path(contextPath); } + + this.distributedSetup = distributedSetup; } public String getExternalScheme() { @@ -107,4 +111,8 @@ public class GuiServiceInfo { return this.externalServerURIBuilder.cloneBuilder(); } + public boolean isDistributedSetup() { + return this.distributedSetup; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java index 36fec927..b5932dd3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java @@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.gui.content; import java.util.Collection; import java.util.function.Supplier; -import org.apache.commons.lang3.BooleanUtils; import org.eclipse.swt.widgets.Composite; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -195,10 +194,9 @@ public class MonitoringClientConnection implements TemplateComposer { indicators); // NOTIFICATIONS - final boolean hasNotifications = BooleanUtils.isTrue(connectionData.pendingNotification()); Supplier> _notificationTableSupplier = () -> null; - if (hasNotifications) { - final PageService.PageActionBuilder actionBuilder = this.pageService + if (connectionData.clientConnection.status.clientActiveStatus) { + final PageService.PageActionBuilder notificationActionBuilder = this.pageService .pageActionBuilder( pageContext .clearAttributes() @@ -240,7 +238,7 @@ public class MonitoringClientConnection implements TemplateComposer { this::getServerTime) .sortable() .widthProportion(1)) - .withDefaultAction(t -> actionBuilder + .withDefaultAction(t -> notificationActionBuilder .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION) .withParentEntityKey(parentEntityKey) .withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY) @@ -252,7 +250,7 @@ public class MonitoringClientConnection implements TemplateComposer { ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)) .compose(pageContext.copyOf(content)); - actionBuilder + notificationActionBuilder .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION) .withParentEntityKey(parentEntityKey) .withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java index 0156dc47..f194f983 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java @@ -41,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.util.Tuple; import ch.ethz.seb.sebserver.gbl.util.Utils; +import ch.ethz.seb.sebserver.gui.GuiServiceInfo; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.service.ResourceService; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; @@ -92,6 +93,7 @@ public class MonitoringRunningExam implements TemplateComposer { private final InstructionProcessor instructionProcessor; private final MonitoringExamSearchPopup monitoringExamSearchPopup; private final MonitoringProctoringService monitoringProctoringService; + private final boolean distributedSetup; private final long pollInterval; private final long proctoringRoomUpdateInterval; @@ -102,6 +104,7 @@ public class MonitoringRunningExam implements TemplateComposer { final InstructionProcessor instructionProcessor, final MonitoringExamSearchPopup monitoringExamSearchPopup, final MonitoringProctoringService monitoringProctoringService, + final GuiServiceInfo guiServiceInfo, @Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval, @Value("${sebserver.gui.remote.proctoring.rooms.update.poll-interval:5000}") final long proctoringRoomUpdateInterval) { @@ -113,6 +116,7 @@ public class MonitoringRunningExam implements TemplateComposer { this.instructionProcessor = instructionProcessor; this.monitoringProctoringService = monitoringProctoringService; this.pollInterval = pollInterval; + this.distributedSetup = guiServiceInfo.isDistributedSetup(); this.monitoringExamSearchPopup = monitoringExamSearchPopup; this.proctoringRoomUpdateInterval = proctoringRoomUpdateInterval; } @@ -164,7 +168,8 @@ public class MonitoringRunningExam implements TemplateComposer { exam, indicators, restCall, - pushContext); + pushContext, + this.distributedSetup); clientTable .withDefaultAction( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/push/ServerPushService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/push/ServerPushService.java index 5f4ce873..85662589 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/push/ServerPushService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/push/ServerPushService.java @@ -83,8 +83,8 @@ public class ServerPushService { }); } - if (log.isInfoEnabled()) { - log.info("Stop Server Push Session on: {}", Thread.currentThread().getName()); + if (log.isDebugEnabled()) { + log.debug("Stop Server Push Session on: {}", Thread.currentThread().getName()); } try { @@ -100,7 +100,9 @@ public class ServerPushService { }); - log.info("Start new Server Push Session on: {}", bgThread.getName()); + if (log.isDebugEnabled()) { + log.debug("Start new Server Push Session on: {}", bgThread.getName()); + } bgThread.setDaemon(true); bgThread.start(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java index 601dffab..ffd1975e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java @@ -25,7 +25,6 @@ import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; -import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification; import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue; @@ -69,6 +68,7 @@ public class ClientConnectionDetails { private ClientConnectionData connectionData = null; private boolean statusChanged = true; + private long startTime = -1; private Consumer statusChangeListener = null; public ClientConnectionDetails( @@ -147,13 +147,22 @@ public class ClientConnectionDetails { .toBoolean(connectionData.missingPing); } this.connectionData = connectionData; - + if (this.startTime < 0) { + this.startTime = System.currentTimeMillis(); + } } public void updateGUI( final Supplier> notificationTableSupplier, final PageContext pageContext) { + // Note: This is to update the whole page (by reload) only when the status has changed + // while this page was open. This prevent constant page reloads. + if (this.statusChanged && System.currentTimeMillis() - this.startTime > Constants.SECOND_IN_MILLIS) { + reloadPage(pageContext); + return; + } + if (this.connectionData == null) { return; } @@ -214,16 +223,8 @@ public class ClientConnectionDetails { // update notifications final EntityTable notificationTable = notificationTableSupplier.get(); - if (notificationTable != null && this.connectionData.clientConnection.status == ConnectionStatus.CLOSED) { - reloadPage(pageContext); - } else { - if (BooleanUtils.isTrue(this.connectionData.pendingNotification())) { - if (notificationTable == null) { - reloadPage(pageContext); - } else { - notificationTable.refreshPageSize(); - } - } + if (notificationTable != null) { + notificationTable.refreshPageSize(); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java index 82ba20d9..2e61b70a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java @@ -97,6 +97,7 @@ public final class ClientConnectionTable { private final Exam exam; private final RestCall>.RestCallBuilder restCallBuilder; private final ServerPushContext pushConext; + private final boolean distributedSetup; private final Map indicatorMapping; private final Table table; @@ -119,8 +120,6 @@ public final class ClientConnectionTable { private boolean forceUpdateAll = false; private boolean updateInProgress = false; - //private int updateErrors = 0; - public ClientConnectionTable( final PageService pageService, final Composite tableRoot, @@ -128,13 +127,15 @@ public final class ClientConnectionTable { final Exam exam, final Collection indicators, final RestCall>.RestCallBuilder restCallBuilder, - final ServerPushContext pushConext) { + final ServerPushContext pushConext, + final boolean distributedSetup) { this.pageService = pageService; this.asyncRunner = asyncRunner; this.exam = exam; this.restCallBuilder = restCallBuilder; this.pushConext = pushConext; + this.distributedSetup = distributedSetup; final WidgetFactory widgetFactory = pageService.getWidgetFactory(); final ResourceService resourceService = pageService.getResourceService(); @@ -332,9 +333,8 @@ public final class ClientConnectionTable { private void updateValuesAsync(final boolean needsSync) { try { - - // TODO forceUpdateAll doeasn't work on distributed - if (this.statusFilterChanged || this.forceUpdateAll || needsSync) { + final boolean sync = this.statusFilterChanged || this.forceUpdateAll || needsSync || this.distributedSetup; + if (sync) { this.toDelete.clear(); this.toDelete.addAll(this.tableMapping.keySet()); } @@ -351,7 +351,7 @@ public final class ClientConnectionTable { data.getConnectionId(), UpdatableTableItem::new); tableItem.push(data); - if (this.statusFilterChanged || this.forceUpdateAll || needsSync) { + if (sync) { this.toDelete.remove(data.getConnectionId()); } }); @@ -680,8 +680,11 @@ public final class ClientConnectionTable { !this.connectionData.dataEquals(connectionData); final boolean statusChanged = this.connectionData == null || this.connectionData.clientConnection.status != connectionData.clientConnection.status; + final boolean notificationChanged = this.connectionData == null || + BooleanUtils.toBoolean(this.connectionData.pendingNotification) != BooleanUtils + .toBoolean(connectionData.pendingNotification); - if (statusChanged) { + if (statusChanged || notificationChanged) { ClientConnectionTable.this.needsSort = true; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java index b69146fe..44a4d819 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java @@ -22,13 +22,13 @@ import org.springframework.stereotype.Service; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; -import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType; import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.WebserviceInfo; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService; @@ -51,20 +51,25 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe private final Set examUpdate = new HashSet<>(); private long lastUpdate = 0; + private long updateInterval = 5 * Constants.SECOND_IN_MILLIS; public SEBClientNotificationServiceImpl( final ClientEventDAO clientEventDAO, final ClientConnectionDAO clientConnectionDAO, - final SEBClientInstructionService sebClientInstructionService) { + final SEBClientInstructionService sebClientInstructionService, + final WebserviceInfo webserviceInfo) { this.clientEventDAO = clientEventDAO; this.clientConnectionDAO = clientConnectionDAO; this.sebClientInstructionService = sebClientInstructionService; + if (webserviceInfo.isDistributed()) { + this.updateInterval = Constants.SECOND_IN_MILLIS; + } } @Override public Boolean hasAnyPendingNotification(final ClientConnection clientConnection) { - if (clientConnection.status != ConnectionStatus.ACTIVE) { + if (!clientConnection.status.clientActiveStatus) { return false; } updateCache(clientConnection.examId); @@ -141,7 +146,7 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe } private final void updateCache(final Long examId) { - if (System.currentTimeMillis() - this.lastUpdate > 5 * Constants.SECOND_IN_MILLIS) { + if (System.currentTimeMillis() - this.lastUpdate > this.updateInterval) { this.examUpdate.clear(); this.pendingNotifications.clear(); this.lastUpdate = System.currentTimeMillis(); diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/util/ReplTest.java b/src/test/java/ch/ethz/seb/sebserver/gbl/util/ReplTest.java index 049c20d5..bd19fe5a 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gbl/util/ReplTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/util/ReplTest.java @@ -42,4 +42,10 @@ public class ReplTest { // assertEquals(Constants.DAY_IN_MIN, interv.toDurationMillis() / Constants.MINUTE_IN_MILLIS); // } +// @Test +// public void testBooleanMatch() { +// assertTrue(Boolean.valueOf(false) == Boolean.valueOf(false)); +// assertTrue(new Boolean(false) == new Boolean(false)); +// } + }