Merge remote-tracking branch 'origin/dev-1.2' into development
Conflicts: src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java
This commit is contained in:
		
						commit
						9a00e9c1ab
					
				
					 8 changed files with 63 additions and 35 deletions
				
			
		| 
						 | 
					@ -28,6 +28,7 @@ public class GuiServiceInfo {
 | 
				
			||||||
    private final String contextPath;
 | 
					    private final String contextPath;
 | 
				
			||||||
    private final UriComponentsBuilder internalServerURIBuilder;
 | 
					    private final UriComponentsBuilder internalServerURIBuilder;
 | 
				
			||||||
    private final UriComponentsBuilder externalServerURIBuilder;
 | 
					    private final UriComponentsBuilder externalServerURIBuilder;
 | 
				
			||||||
 | 
					    private final boolean distributedSetup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public GuiServiceInfo(
 | 
					    public GuiServiceInfo(
 | 
				
			||||||
            @Value("${server.address}") final String internalServer,
 | 
					            @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.servername}") final String externalServer,
 | 
				
			||||||
            @Value("${sebserver.gui.http.external.port}") final String externalPort,
 | 
					            @Value("${sebserver.gui.http.external.port}") final String externalPort,
 | 
				
			||||||
            @Value("${sebserver.gui.entrypoint:/gui}") final String entryPoint,
 | 
					            @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)) {
 | 
					        if (StringUtils.isBlank(externalScheme)) {
 | 
				
			||||||
            throw new RuntimeException("Missing mandatory inital parameter sebserver.gui.http.external.servername");
 | 
					            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("/")) {
 | 
					        if (StringUtils.isNotBlank(contextPath) && !contextPath.equals("/")) {
 | 
				
			||||||
            this.externalServerURIBuilder.path(contextPath);
 | 
					            this.externalServerURIBuilder.path(contextPath);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.distributedSetup = distributedSetup;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getExternalScheme() {
 | 
					    public String getExternalScheme() {
 | 
				
			||||||
| 
						 | 
					@ -107,4 +111,8 @@ public class GuiServiceInfo {
 | 
				
			||||||
        return this.externalServerURIBuilder.cloneBuilder();
 | 
					        return this.externalServerURIBuilder.cloneBuilder();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isDistributedSetup() {
 | 
				
			||||||
 | 
					        return this.distributedSetup;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.gui.content.monitoring;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.function.Supplier;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.lang3.BooleanUtils;
 | 
					 | 
				
			||||||
import org.eclipse.swt.widgets.Composite;
 | 
					import org.eclipse.swt.widgets.Composite;
 | 
				
			||||||
import org.slf4j.Logger;
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
import org.slf4j.LoggerFactory;
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
| 
						 | 
					@ -195,10 +194,9 @@ public class MonitoringClientConnection implements TemplateComposer {
 | 
				
			||||||
                indicators);
 | 
					                indicators);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // NOTIFICATIONS
 | 
					        // NOTIFICATIONS
 | 
				
			||||||
        final boolean hasNotifications = BooleanUtils.isTrue(connectionData.pendingNotification());
 | 
					 | 
				
			||||||
        Supplier<EntityTable<ClientNotification>> _notificationTableSupplier = () -> null;
 | 
					        Supplier<EntityTable<ClientNotification>> _notificationTableSupplier = () -> null;
 | 
				
			||||||
        if (hasNotifications) {
 | 
					        if (connectionData.clientConnection.status.clientActiveStatus) {
 | 
				
			||||||
            final PageService.PageActionBuilder actionBuilder = this.pageService
 | 
					            final PageService.PageActionBuilder notificationActionBuilder = this.pageService
 | 
				
			||||||
                    .pageActionBuilder(
 | 
					                    .pageActionBuilder(
 | 
				
			||||||
                            pageContext
 | 
					                            pageContext
 | 
				
			||||||
                                    .clearAttributes()
 | 
					                                    .clearAttributes()
 | 
				
			||||||
| 
						 | 
					@ -240,7 +238,7 @@ public class MonitoringClientConnection implements TemplateComposer {
 | 
				
			||||||
                            this::getServerTime)
 | 
					                            this::getServerTime)
 | 
				
			||||||
                                    .sortable()
 | 
					                                    .sortable()
 | 
				
			||||||
                                    .widthProportion(1))
 | 
					                                    .widthProportion(1))
 | 
				
			||||||
                    .withDefaultAction(t -> actionBuilder
 | 
					                    .withDefaultAction(t -> notificationActionBuilder
 | 
				
			||||||
                            .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)
 | 
					                            .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)
 | 
				
			||||||
                            .withParentEntityKey(parentEntityKey)
 | 
					                            .withParentEntityKey(parentEntityKey)
 | 
				
			||||||
                            .withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
 | 
					                            .withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
 | 
				
			||||||
| 
						 | 
					@ -252,7 +250,7 @@ public class MonitoringClientConnection implements TemplateComposer {
 | 
				
			||||||
                            ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION))
 | 
					                            ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION))
 | 
				
			||||||
                    .compose(pageContext.copyOf(content));
 | 
					                    .compose(pageContext.copyOf(content));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            actionBuilder
 | 
					            notificationActionBuilder
 | 
				
			||||||
                    .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)
 | 
					                    .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)
 | 
				
			||||||
                    .withParentEntityKey(parentEntityKey)
 | 
					                    .withParentEntityKey(parentEntityKey)
 | 
				
			||||||
                    .withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
 | 
					                    .withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.profile.GuiProfile;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
 | 
					import ch.ethz.seb.sebserver.gbl.util.Tuple;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
					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.content.action.ActionDefinition;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
 | 
					import ch.ethz.seb.sebserver.gui.service.ResourceService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
				
			||||||
| 
						 | 
					@ -92,6 +93,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
				
			||||||
    private final InstructionProcessor instructionProcessor;
 | 
					    private final InstructionProcessor instructionProcessor;
 | 
				
			||||||
    private final MonitoringExamSearchPopup monitoringExamSearchPopup;
 | 
					    private final MonitoringExamSearchPopup monitoringExamSearchPopup;
 | 
				
			||||||
    private final MonitoringProctoringService monitoringProctoringService;
 | 
					    private final MonitoringProctoringService monitoringProctoringService;
 | 
				
			||||||
 | 
					    private final boolean distributedSetup;
 | 
				
			||||||
    private final long pollInterval;
 | 
					    private final long pollInterval;
 | 
				
			||||||
    private final long proctoringRoomUpdateInterval;
 | 
					    private final long proctoringRoomUpdateInterval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,6 +104,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
				
			||||||
            final InstructionProcessor instructionProcessor,
 | 
					            final InstructionProcessor instructionProcessor,
 | 
				
			||||||
            final MonitoringExamSearchPopup monitoringExamSearchPopup,
 | 
					            final MonitoringExamSearchPopup monitoringExamSearchPopup,
 | 
				
			||||||
            final MonitoringProctoringService monitoringProctoringService,
 | 
					            final MonitoringProctoringService monitoringProctoringService,
 | 
				
			||||||
 | 
					            final GuiServiceInfo guiServiceInfo,
 | 
				
			||||||
            @Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval,
 | 
					            @Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval,
 | 
				
			||||||
            @Value("${sebserver.gui.remote.proctoring.rooms.update.poll-interval:5000}") final long proctoringRoomUpdateInterval) {
 | 
					            @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.instructionProcessor = instructionProcessor;
 | 
				
			||||||
        this.monitoringProctoringService = monitoringProctoringService;
 | 
					        this.monitoringProctoringService = monitoringProctoringService;
 | 
				
			||||||
        this.pollInterval = pollInterval;
 | 
					        this.pollInterval = pollInterval;
 | 
				
			||||||
 | 
					        this.distributedSetup = guiServiceInfo.isDistributedSetup();
 | 
				
			||||||
        this.monitoringExamSearchPopup = monitoringExamSearchPopup;
 | 
					        this.monitoringExamSearchPopup = monitoringExamSearchPopup;
 | 
				
			||||||
        this.proctoringRoomUpdateInterval = proctoringRoomUpdateInterval;
 | 
					        this.proctoringRoomUpdateInterval = proctoringRoomUpdateInterval;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -164,7 +168,8 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
				
			||||||
                exam,
 | 
					                exam,
 | 
				
			||||||
                indicators,
 | 
					                indicators,
 | 
				
			||||||
                restCall,
 | 
					                restCall,
 | 
				
			||||||
                pushContext);
 | 
					                pushContext,
 | 
				
			||||||
 | 
					                this.distributedSetup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        clientTable
 | 
					        clientTable
 | 
				
			||||||
                .withDefaultAction(
 | 
					                .withDefaultAction(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,8 +83,8 @@ public class ServerPushService {
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (log.isInfoEnabled()) {
 | 
					            if (log.isDebugEnabled()) {
 | 
				
			||||||
                log.info("Stop Server Push Session on: {}", Thread.currentThread().getName());
 | 
					                log.debug("Stop Server Push Session on: {}", Thread.currentThread().getName());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            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.setDaemon(true);
 | 
				
			||||||
        bgThread.start();
 | 
					        bgThread.start();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.Exam;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
 | 
					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.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.ClientConnectionData;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
 | 
				
			||||||
| 
						 | 
					@ -69,6 +68,7 @@ public class ClientConnectionDetails {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ClientConnectionData connectionData = null;
 | 
					    private ClientConnectionData connectionData = null;
 | 
				
			||||||
    private boolean statusChanged = true;
 | 
					    private boolean statusChanged = true;
 | 
				
			||||||
 | 
					    private long startTime = -1;
 | 
				
			||||||
    private Consumer<ClientConnectionData> statusChangeListener = null;
 | 
					    private Consumer<ClientConnectionData> statusChangeListener = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ClientConnectionDetails(
 | 
					    public ClientConnectionDetails(
 | 
				
			||||||
| 
						 | 
					@ -147,13 +147,22 @@ public class ClientConnectionDetails {
 | 
				
			||||||
                                    .toBoolean(connectionData.missingPing);
 | 
					                                    .toBoolean(connectionData.missingPing);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.connectionData = connectionData;
 | 
					        this.connectionData = connectionData;
 | 
				
			||||||
 | 
					        if (this.startTime < 0) {
 | 
				
			||||||
 | 
					            this.startTime = System.currentTimeMillis();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void updateGUI(
 | 
					    public void updateGUI(
 | 
				
			||||||
            final Supplier<EntityTable<ClientNotification>> notificationTableSupplier,
 | 
					            final Supplier<EntityTable<ClientNotification>> notificationTableSupplier,
 | 
				
			||||||
            final PageContext pageContext) {
 | 
					            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) {
 | 
					        if (this.connectionData == null) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -214,18 +223,10 @@ public class ClientConnectionDetails {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // update notifications
 | 
					        // update notifications
 | 
				
			||||||
        final EntityTable<ClientNotification> notificationTable = notificationTableSupplier.get();
 | 
					        final EntityTable<ClientNotification> notificationTable = notificationTableSupplier.get();
 | 
				
			||||||
        if (notificationTable != null && this.connectionData.clientConnection.status == ConnectionStatus.CLOSED) {
 | 
					        if (notificationTable != null) {
 | 
				
			||||||
            reloadPage(pageContext);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            if (BooleanUtils.isTrue(this.connectionData.pendingNotification())) {
 | 
					 | 
				
			||||||
                if (notificationTable == null) {
 | 
					 | 
				
			||||||
                    reloadPage(pageContext);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
            notificationTable.refreshPageSize();
 | 
					            notificationTable.refreshPageSize();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void reloadPage(final PageContext pageContext) {
 | 
					    private void reloadPage(final PageContext pageContext) {
 | 
				
			||||||
        final PageAction pageReloadAction = this.pageService.pageActionBuilder(pageContext)
 | 
					        final PageAction pageReloadAction = this.pageService.pageActionBuilder(pageContext)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,6 +97,7 @@ public final class ClientConnectionTable {
 | 
				
			||||||
    private final Exam exam;
 | 
					    private final Exam exam;
 | 
				
			||||||
    private final RestCall<Collection<ClientConnectionData>>.RestCallBuilder restCallBuilder;
 | 
					    private final RestCall<Collection<ClientConnectionData>>.RestCallBuilder restCallBuilder;
 | 
				
			||||||
    private final ServerPushContext pushConext;
 | 
					    private final ServerPushContext pushConext;
 | 
				
			||||||
 | 
					    private final boolean distributedSetup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final Map<Long, IndicatorData> indicatorMapping;
 | 
					    private final Map<Long, IndicatorData> indicatorMapping;
 | 
				
			||||||
    private final Table table;
 | 
					    private final Table table;
 | 
				
			||||||
| 
						 | 
					@ -119,8 +120,6 @@ public final class ClientConnectionTable {
 | 
				
			||||||
    private boolean forceUpdateAll = false;
 | 
					    private boolean forceUpdateAll = false;
 | 
				
			||||||
    private boolean updateInProgress = false;
 | 
					    private boolean updateInProgress = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //private int updateErrors = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ClientConnectionTable(
 | 
					    public ClientConnectionTable(
 | 
				
			||||||
            final PageService pageService,
 | 
					            final PageService pageService,
 | 
				
			||||||
            final Composite tableRoot,
 | 
					            final Composite tableRoot,
 | 
				
			||||||
| 
						 | 
					@ -128,13 +127,15 @@ public final class ClientConnectionTable {
 | 
				
			||||||
            final Exam exam,
 | 
					            final Exam exam,
 | 
				
			||||||
            final Collection<Indicator> indicators,
 | 
					            final Collection<Indicator> indicators,
 | 
				
			||||||
            final RestCall<Collection<ClientConnectionData>>.RestCallBuilder restCallBuilder,
 | 
					            final RestCall<Collection<ClientConnectionData>>.RestCallBuilder restCallBuilder,
 | 
				
			||||||
            final ServerPushContext pushConext) {
 | 
					            final ServerPushContext pushConext,
 | 
				
			||||||
 | 
					            final boolean distributedSetup) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.pageService = pageService;
 | 
					        this.pageService = pageService;
 | 
				
			||||||
        this.asyncRunner = asyncRunner;
 | 
					        this.asyncRunner = asyncRunner;
 | 
				
			||||||
        this.exam = exam;
 | 
					        this.exam = exam;
 | 
				
			||||||
        this.restCallBuilder = restCallBuilder;
 | 
					        this.restCallBuilder = restCallBuilder;
 | 
				
			||||||
        this.pushConext = pushConext;
 | 
					        this.pushConext = pushConext;
 | 
				
			||||||
 | 
					        this.distributedSetup = distributedSetup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final WidgetFactory widgetFactory = pageService.getWidgetFactory();
 | 
					        final WidgetFactory widgetFactory = pageService.getWidgetFactory();
 | 
				
			||||||
        final ResourceService resourceService = pageService.getResourceService();
 | 
					        final ResourceService resourceService = pageService.getResourceService();
 | 
				
			||||||
| 
						 | 
					@ -332,9 +333,8 @@ public final class ClientConnectionTable {
 | 
				
			||||||
    private void updateValuesAsync(final boolean needsSync) {
 | 
					    private void updateValuesAsync(final boolean needsSync) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 | 
					            final boolean sync = this.statusFilterChanged || this.forceUpdateAll || needsSync || this.distributedSetup;
 | 
				
			||||||
            // TODO forceUpdateAll doeasn't work on distributed
 | 
					            if (sync) {
 | 
				
			||||||
            if (this.statusFilterChanged || this.forceUpdateAll || needsSync) {
 | 
					 | 
				
			||||||
                this.toDelete.clear();
 | 
					                this.toDelete.clear();
 | 
				
			||||||
                this.toDelete.addAll(this.tableMapping.keySet());
 | 
					                this.toDelete.addAll(this.tableMapping.keySet());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -351,7 +351,7 @@ public final class ClientConnectionTable {
 | 
				
			||||||
                                data.getConnectionId(),
 | 
					                                data.getConnectionId(),
 | 
				
			||||||
                                UpdatableTableItem::new);
 | 
					                                UpdatableTableItem::new);
 | 
				
			||||||
                        tableItem.push(data);
 | 
					                        tableItem.push(data);
 | 
				
			||||||
                        if (this.statusFilterChanged || this.forceUpdateAll || needsSync) {
 | 
					                        if (sync) {
 | 
				
			||||||
                            this.toDelete.remove(data.getConnectionId());
 | 
					                            this.toDelete.remove(data.getConnectionId());
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
| 
						 | 
					@ -680,8 +680,11 @@ public final class ClientConnectionTable {
 | 
				
			||||||
                    !this.connectionData.dataEquals(connectionData);
 | 
					                    !this.connectionData.dataEquals(connectionData);
 | 
				
			||||||
            final boolean statusChanged = this.connectionData == null ||
 | 
					            final boolean statusChanged = this.connectionData == null ||
 | 
				
			||||||
                    this.connectionData.clientConnection.status != connectionData.clientConnection.status;
 | 
					                    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;
 | 
					                ClientConnectionTable.this.needsSort = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,13 +22,13 @@ import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
					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;
 | 
				
			||||||
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.ClientEvent;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
 | 
					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.ClientInstruction.InstructionType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
					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.ClientConnectionDAO;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
 | 
				
			||||||
| 
						 | 
					@ -51,20 +51,25 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
 | 
				
			||||||
    private final Set<Long> examUpdate = new HashSet<>();
 | 
					    private final Set<Long> examUpdate = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private long lastUpdate = 0;
 | 
					    private long lastUpdate = 0;
 | 
				
			||||||
 | 
					    private long updateInterval = 5 * Constants.SECOND_IN_MILLIS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SEBClientNotificationServiceImpl(
 | 
					    public SEBClientNotificationServiceImpl(
 | 
				
			||||||
            final ClientEventDAO clientEventDAO,
 | 
					            final ClientEventDAO clientEventDAO,
 | 
				
			||||||
            final ClientConnectionDAO clientConnectionDAO,
 | 
					            final ClientConnectionDAO clientConnectionDAO,
 | 
				
			||||||
            final SEBClientInstructionService sebClientInstructionService) {
 | 
					            final SEBClientInstructionService sebClientInstructionService,
 | 
				
			||||||
 | 
					            final WebserviceInfo webserviceInfo) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.clientEventDAO = clientEventDAO;
 | 
					        this.clientEventDAO = clientEventDAO;
 | 
				
			||||||
        this.clientConnectionDAO = clientConnectionDAO;
 | 
					        this.clientConnectionDAO = clientConnectionDAO;
 | 
				
			||||||
        this.sebClientInstructionService = sebClientInstructionService;
 | 
					        this.sebClientInstructionService = sebClientInstructionService;
 | 
				
			||||||
 | 
					        if (webserviceInfo.isDistributed()) {
 | 
				
			||||||
 | 
					            this.updateInterval = Constants.SECOND_IN_MILLIS;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Boolean hasAnyPendingNotification(final ClientConnection clientConnection) {
 | 
					    public Boolean hasAnyPendingNotification(final ClientConnection clientConnection) {
 | 
				
			||||||
        if (clientConnection.status != ConnectionStatus.ACTIVE) {
 | 
					        if (!clientConnection.status.clientActiveStatus) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        updateCache(clientConnection.examId);
 | 
					        updateCache(clientConnection.examId);
 | 
				
			||||||
| 
						 | 
					@ -141,7 +146,7 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final void updateCache(final Long examId) {
 | 
					    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.examUpdate.clear();
 | 
				
			||||||
            this.pendingNotifications.clear();
 | 
					            this.pendingNotifications.clear();
 | 
				
			||||||
            this.lastUpdate = System.currentTimeMillis();
 | 
					            this.lastUpdate = System.currentTimeMillis();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,4 +42,10 @@ public class ReplTest {
 | 
				
			||||||
//        assertEquals(Constants.DAY_IN_MIN, interv.toDurationMillis() / Constants.MINUTE_IN_MILLIS);
 | 
					//        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));
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue