diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java index 083cd248..aa529b4f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java @@ -213,6 +213,7 @@ public final class API { public static final String EXAM_PROCTORING_ATTR_ALLOW_CHAT = "allow_chat"; public static final String SEB_CLIENT_CONNECTION_ENDPOINT = "/seb-client-connection"; + public static final String SEB_CLIENT_CONNECTION_DATA_ENDPOINT = "/data"; public static final String SEB_CLIENT_EVENT_ENDPOINT = "/seb-client-event"; public static final String SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT = "/search"; diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java index ddab83a6..9fa6a567 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java @@ -17,10 +17,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.GrantEntity; import ch.ethz.seb.sebserver.gbl.util.Utils; @JsonIgnoreProperties(ignoreUnknown = true) -public class ClientConnectionData { +public class ClientConnectionData implements GrantEntity { public static final String ATTR_CLIENT_CONNECTION = "cData"; public static final String ATTR_INDICATOR_VALUE = "iValues"; @@ -48,7 +50,7 @@ public class ClientConnectionData { this.indicatorValues = Utils.immutableListOf(indicatorValues); } - protected ClientConnectionData( + public ClientConnectionData( final ClientConnection clientConnection, final List indicatorValues) { @@ -58,6 +60,26 @@ public class ClientConnectionData { this.indicatorValues = Utils.immutableListOf(indicatorValues); } + @Override + public EntityType entityType() { + return this.clientConnection.entityType(); + } + + @Override + public String getName() { + return this.clientConnection.getName(); + } + + @Override + public String getModelId() { + return this.clientConnection.getModelId(); + } + + @Override + public Long getInstitutionId() { + return this.clientConnection.getInstitutionId(); + } + @JsonProperty(ATTR_MISSING_PING) public Boolean getMissingPing() { return this.missingPing; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/FinishedExam.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/FinishedExam.java index f611d80c..e1b40515 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/FinishedExam.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/FinishedExam.java @@ -9,15 +9,20 @@ package ch.ethz.seb.sebserver.gui.content.monitoring; import java.util.Collection; +import java.util.function.Function; +import org.eclipse.swt.widgets.Composite; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; +import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.service.ResourceService; @@ -29,7 +34,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; import ch.ethz.seb.sebserver.gui.service.push.ServerPushService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicators; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionPage; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetFinishedExamClientConnectionPage; import ch.ethz.seb.sebserver.gui.table.ColumnDefinition; import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute; import ch.ethz.seb.sebserver.gui.table.TableBuilder; @@ -91,29 +96,33 @@ public class FinishedExam implements TemplateComposer { .call() .getOrThrow(); - final TableBuilder tableBuilder = - this.pageService.entityTableBuilder(restService.getRestCall(GetClientConnectionPage.class)) + final Composite content = this.pageService.getWidgetFactory().defaultPageLayout( + pageContext.getParent(), + TITLE_TEXT_KEY); + + final TableBuilder tableBuilder = + this.pageService.entityTableBuilder(restService.getRestCall(GetFinishedExamClientConnectionPage.class)) .withEmptyMessage(EMPTY_LIST_TEXT_KEY) - .withPaging(10) + .withPaging(this.pageSize) .withStaticFilter(ClientConnection.FILTER_ATTR_EXAM_ID, examKey.modelId) - .withColumn(new ColumnDefinition<>( + .withColumn(new ColumnDefinition( Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID, TABLE_COLUMN_NAME, - ClientConnection::getUserSessionId) + c -> c.clientConnection.getUserSessionId()) .withFilter(this.nameFilter)) - .withColumn(new ColumnDefinition<>( + .withColumn(new ColumnDefinition( ClientConnection.ATTR_INFO, TABLE_COLUMN_INFO, - ClientConnection::getInfo) + c -> c.clientConnection.getInfo()) .withFilter(this.infoFilter)) - .withColumn(new ColumnDefinition( + .withColumn(new ColumnDefinition( Domain.CLIENT_CONNECTION.ATTR_STATUS, TABLE_COLUMN_STATUS, row -> this.pageService.getResourceService() - .localizedClientConnectionStatusName(row.getStatus())) + .localizedClientConnectionStatusName(row.clientConnection.getStatus())) .withFilter(this.statusFilter)) .withDefaultAction(t -> actionBuilder @@ -121,7 +130,25 @@ public class FinishedExam implements TemplateComposer { .withParentEntityKey(examKey) .create()); - tableBuilder.compose(pageContext); + indicators.stream().forEach(indicator -> { + tableBuilder.withColumn(new ColumnDefinition<>( + indicator.name, + new LocTextKey(indicator.name), + indicatorValueFunction(indicator))); + }); + + tableBuilder.compose(pageContext.copyOf(content)); + } + + private Function indicatorValueFunction(final Indicator indicator) { + return clientConnectionData -> { + return clientConnectionData.indicatorValues + .stream() + .filter(indicatorValue -> indicatorValue.getIndicatorId().equals(indicator.id)) + .findFirst() + .map(iv -> IndicatorValue.getDisplayValue(iv, indicator.type)) + .orElse(Constants.EMPTY_NOTE); + }; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetFinishedExamClientConnection.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetFinishedExamClientConnection.java new file mode 100644 index 00000000..bcf12c43 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetFinishedExamClientConnection.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session; + +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.type.TypeReference; + +import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class GetFinishedExamClientConnection extends RestCall { + + public GetFinishedExamClientConnection() { + super(new TypeKey<>( + CallType.GET_SINGLE, + EntityType.CLIENT_CONNECTION, + new TypeReference() { + }), + HttpMethod.GET, + MediaType.APPLICATION_FORM_URLENCODED, + API.SEB_CLIENT_CONNECTION_ENDPOINT + + API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT + + API.MODEL_ID_VAR_PATH_SEGMENT); + } +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetFinishedExamClientConnectionPage.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetFinishedExamClientConnectionPage.java new file mode 100644 index 00000000..8d46b940 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetFinishedExamClientConnectionPage.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session; + +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.type.TypeReference; + +import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.Page; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class GetFinishedExamClientConnectionPage extends RestCall> { + + public GetFinishedExamClientConnectionPage() { + super(new TypeKey<>( + CallType.GET_PAGE, + EntityType.CLIENT_CONNECTION, + new TypeReference>() { + }), + HttpMethod.GET, + MediaType.APPLICATION_FORM_URLENCODED, + API.SEB_CLIENT_CONNECTION_ENDPOINT + API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/SEBClientConnectionService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/SEBClientConnectionService.java index f03105c0..c8e3d960 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/SEBClientConnectionService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/SEBClientConnectionService.java @@ -13,6 +13,7 @@ import java.util.Collection; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -184,4 +185,11 @@ public interface SEBClientConnectionService { * @param instructionConfirm the instruction confirm identifier */ void confirmInstructionDone(String connectionToken, String instructionConfirm); + /** Use this to get the get the specific indicator values for a given client connection. + * + * @param clientConnection The client connection values + * @return Result refer to ClientConnectionData instance containing the given clientConnection plus the indicator + * values or to an error when happened */ + Result getIndicatorValues(final ClientConnection clientConnection); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientIndicatorFactory.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientIndicatorFactory.java index 5be1a549..39102fc7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientIndicatorFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientIndicatorFactory.java @@ -54,8 +54,14 @@ public class ClientIndicatorFactory { } public List createFor(final ClientConnection clientConnection) { - final List result = new ArrayList<>(); + return createFor(clientConnection, false); + } + public List createFor( + final ClientConnection clientConnection, + final boolean enableCachingOverride) { + + final List result = new ArrayList<>(); if (clientConnection.examId == null) { return result; } @@ -82,7 +88,7 @@ public class ClientIndicatorFactory { indicatorDef, clientConnection.id, clientConnection.status.clientActiveStatus, - this.enableCaching); + this.enableCaching || enableCachingOverride); result.add(indicator); } catch (final Exception e) { @@ -111,7 +117,7 @@ public class ClientIndicatorFactory { indicator, clientConnection.id, clientConnection.status.clientActiveStatus, - this.enableCaching); + this.enableCaching || enableCachingOverride); result.add(pingIndicator); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java index 29f68b4b..4af7ab47 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java @@ -74,6 +74,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic private final SEBClientConfigDAO sebClientConfigDAO; private final SEBClientInstructionService sebInstructionService; private final ExamAdminService examAdminService; + private final ClientIndicatorFactory clientIndicatorFactory; // TODO get rid of this dependency and use application events for signaling client connection state changes private final DistributedIndicatorValueService distributedPingCache; private final boolean isDistributedSetup; @@ -84,6 +85,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic final SEBClientConfigDAO sebClientConfigDAO, final SEBClientInstructionService sebInstructionService, final ExamAdminService examAdminService, + final ClientIndicatorFactory clientIndicatorFactory, final DistributedIndicatorValueService distributedPingCache) { this.examSessionService = examSessionService; @@ -94,6 +96,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic this.sebClientConfigDAO = sebClientConfigDAO; this.sebInstructionService = sebInstructionService; this.examAdminService = examAdminService; + this.clientIndicatorFactory = clientIndicatorFactory; this.distributedPingCache = distributedPingCache; this.isDistributedSetup = sebInstructionService.getWebserviceInfo().isDistributed(); } @@ -702,6 +705,13 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic this.sebInstructionService.confirmInstructionDone(connectionToken, instructionConfirm); } + @Override + public Result getIndicatorValues(final ClientConnection clientConnection) { + return Result.tryCatch(() -> new ClientConnectionData( + clientConnection, + this.clientIndicatorFactory.createFor(clientConnection, true))); + } + private void checkExamRunning(final Long examId) { if (examId != null && !this.examSessionService.isExamRunning(examId)) { examNotRunningException(examId); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java index 06656d71..1ba12865 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java @@ -21,7 +21,7 @@ public abstract class AbstractClientIndicator implements ClientIndicator { private static final Logger log = LoggerFactory.getLogger(AbstractClientIndicator.class); - protected final DistributedIndicatorValueService distributedPingCache; + protected final DistributedIndicatorValueService distributedIndicatorValueService; protected Long indicatorId = -1L; protected Long examId = -1L; @@ -38,9 +38,9 @@ public abstract class AbstractClientIndicator implements ClientIndicator { protected long lastUpdate = 0; - public AbstractClientIndicator(final DistributedIndicatorValueService distributedPingCache) { + public AbstractClientIndicator(final DistributedIndicatorValueService distributedIndicatorValueService) { super(); - this.distributedPingCache = distributedPingCache; + this.distributedIndicatorValueService = distributedIndicatorValueService; } @Override @@ -70,10 +70,11 @@ public abstract class AbstractClientIndicator implements ClientIndicator { if (!this.cachingEnabled && this.active) { try { - this.ditributedIndicatorValueRecordId = this.distributedPingCache.initIndicatorForConnection( - connectionId, - getType(), - initValue()); + this.ditributedIndicatorValueRecordId = + this.distributedIndicatorValueService.initIndicatorForConnection( + connectionId, + getType(), + initValue()); } catch (final Exception e) { tryRecoverIndicatorRecord(); } @@ -94,7 +95,7 @@ public abstract class AbstractClientIndicator implements ClientIndicator { } try { - this.ditributedIndicatorValueRecordId = this.distributedPingCache.initIndicatorForConnection( + this.ditributedIndicatorValueRecordId = this.distributedIndicatorValueService.initIndicatorForConnection( this.connectionId, getType(), initValue()); @@ -126,18 +127,18 @@ public abstract class AbstractClientIndicator implements ClientIndicator { public double getValue() { if (this.initialized && !this.cachingEnabled && this.active - && this.lastUpdate != this.distributedPingCache.lastUpdate()) { + && this.lastUpdate != this.distributedIndicatorValueService.lastUpdate()) { if (this.ditributedIndicatorValueRecordId == null) { this.tryRecoverIndicatorRecord(); } - final Long indicatorValue = this.distributedPingCache + final Long indicatorValue = this.distributedIndicatorValueService .getIndicatorValue(this.ditributedIndicatorValueRecordId); if (indicatorValue != null) { this.currentValue = indicatorValue.doubleValue(); } - this.lastUpdate = this.distributedPingCache.lastUpdate(); + this.lastUpdate = this.distributedIndicatorValueService.lastUpdate(); } return this.currentValue; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java index ce89c669..55461a1f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java @@ -75,7 +75,7 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato // update active indicator value record on persistent when caching is not enabled if (this.active && this.ditributedIndicatorValueRecordId != null) { - this.distributedPingCache.updateIndicatorValue( + this.distributedIndicatorValueService.updateIndicatorValue( this.ditributedIndicatorValueRecordId, numberOfLogs.longValue()); } @@ -115,7 +115,7 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato private void valueChanged(final String eventText) { if (this.tags == null || this.tags.length == 0 || hasTag(eventText)) { if (super.ditributedIndicatorValueRecordId != null) { - this.distributedPingCache.incrementIndicatorValue(super.ditributedIndicatorValueRecordId); + this.distributedIndicatorValueService.incrementIndicatorValue(super.ditributedIndicatorValueRecordId); } this.currentValue = getValue() + 1d; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogNumberIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogNumberIndicator.java index af05e7e5..994c307f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogNumberIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogNumberIndicator.java @@ -56,7 +56,7 @@ public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator { private void valueChanged(final String text, final double value) { if (this.tags == null || this.tags.length == 0 || hasTag(text)) { if (super.ditributedIndicatorValueRecordId != null) { - if (!this.distributedPingCache.updateIndicatorValueAsync( + if (!this.distributedIndicatorValueService.updateIndicatorValueAsync( this.ditributedIndicatorValueRecordId, Double.valueOf(value).longValue())) { @@ -100,7 +100,7 @@ public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator { // update active indicator value record on persistent when caching is not enabled if (this.active && this.ditributedIndicatorValueRecordId != null) { - this.distributedPingCache.updateIndicatorValue( + this.distributedIndicatorValueService.updateIndicatorValue( this.ditributedIndicatorValueRecordId, numericValue.longValue()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java index 4987c509..98127736 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java @@ -12,7 +12,6 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Set; -import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType; public abstract class AbstractPingIndicator extends AbstractClientIndicator { @@ -23,16 +22,6 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator { super(distributedPingCache); } - @Override - public void init( - final Indicator indicatorDefinition, - final Long connectionId, - final boolean active, - final boolean cachingEnabled) { - - super.init(indicatorDefinition, connectionId, active, cachingEnabled); - } - @Override public Set observedEvents() { return this.EMPTY_SET; @@ -50,7 +39,7 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator { } } - this.distributedPingCache.updatePingAsync(this.ditributedIndicatorValueRecordId); + this.distributedIndicatorValueService.updatePingAsync(this.ditributedIndicatorValueRecordId); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java index ba933dd9..a197e0ac 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java @@ -35,8 +35,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator { private boolean hidden = false; - public PingIntervalClientIndicator(final DistributedIndicatorValueService distributedPingCache) { - super(distributedPingCache); + public PingIntervalClientIndicator(final DistributedIndicatorValueService distributedIndicatorValueService) { + super(distributedIndicatorValueService); this.cachingEnabled = true; } @@ -83,7 +83,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator { } if (this.initialized && !this.cachingEnabled && this.active - && this.lastUpdate != this.distributedPingCache.lastUpdate()) { + && this.lastUpdate != this.distributedIndicatorValueService.lastUpdate()) { final long currentTimeMillis = DateTimeUtils.currentTimeMillis(); this.currentValue = computeValueAt(currentTimeMillis); @@ -110,7 +110,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator { public final double computeValueAt(final long timestamp) { if (super.ditributedIndicatorValueRecordId != null) { - final Long lastPing = this.distributedPingCache + final Long lastPing = this.distributedIndicatorValueService .getIndicatorValue(super.ditributedIndicatorValueRecordId); return (lastPing != null) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientConnectionController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientConnectionController.java index 3362518c..3bd7ec26 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientConnectionController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientConnectionController.java @@ -12,26 +12,37 @@ import java.util.Collection; import java.util.List; import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; + import org.apache.commons.lang3.StringUtils; import org.mybatis.dynamic.sql.SqlTable; +import org.springframework.http.MediaType; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityDependency; +import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; +import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; @WebServiceProfile @@ -39,13 +50,16 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe @RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_CONNECTION_ENDPOINT) public class ClientConnectionController extends ReadonlyEntityController { + private final SEBClientConnectionService sebClientConnectionService; + protected ClientConnectionController( final AuthorizationService authorization, final BulkActionService bulkActionService, final ClientConnectionDAO clientConnectionDAO, final UserActivityLogDAO userActivityLogDAO, final PaginationService paginationService, - final BeanValidationService beanValidationService) { + final BeanValidationService beanValidationService, + final SEBClientConnectionService sebClientConnectionService) { super(authorization, bulkActionService, @@ -53,6 +67,60 @@ public class ClientConnectionController extends ReadonlyEntityController getClientConnectionDataPage( + @RequestParam( + name = API.PARAM_INSTITUTION_ID, + required = true, + defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, + @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber, + @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize, + @RequestParam(name = Page.ATTR_SORT, required = false) final String sort, + @RequestParam final MultiValueMap allRequestParams, + final HttpServletRequest request) { + + // at least current user must have read access for specified entity type within its own institution + checkReadPrivilege(institutionId); + + final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString()); + populateFilterMap(filterMap, institutionId, sort); + + final Page page = this.paginationService.getPage( + pageNumber, + pageSize, + sort, + getSQLTableOfEntity().name(), + () -> getAllData(filterMap)) + .getOrThrow(); + + return page; + } + + @RequestMapping( + path = API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT, + method = RequestMethod.GET, + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ClientConnectionData getClientConnectionDataBy(@PathVariable final String modelId) { + return this.sebClientConnectionService + .getIndicatorValues(super.getBy(modelId)) + .getOrThrow(); + } + + private Result> getAllData(final FilterMap filterMap) { + return getAll(filterMap) + .map(connection -> connection.stream() + .map(this.sebClientConnectionService::getIndicatorValues) + .flatMap(Result::onErrorLogAndSkip) + .collect(Collectors.toList())); } @Override diff --git a/src/main/resources/config/application-dev-ws.properties b/src/main/resources/config/application-dev-ws.properties index 1ba4288f..a5671ccc 100644 --- a/src/main/resources/config/application-dev-ws.properties +++ b/src/main/resources/config/application-dev-ws.properties @@ -25,7 +25,7 @@ sebserver.webservice.clean-db-on-startup=false # webservice configuration sebserver.init.adminaccount.gen-on-init=false -sebserver.webservice.distributed=false +sebserver.webservice.distributed=true #sebserver.webservice.master.delay.threshold=10000 sebserver.webservice.http.external.scheme=http sebserver.webservice.http.external.servername=localhost