fixed caching issue with Exam Config changes on running exams

This commit is contained in:
anhefti 2019-09-13 16:57:07 +02:00
parent 278bdf4673
commit 5aa3671608
13 changed files with 136 additions and 10 deletions

1
docker/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/test/

View file

@ -32,7 +32,7 @@ ENTRYPOINT exec java \
-Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9090 \ -Dcom.sun.management.jmxremote.port=9090 \
-Dcom.sun.management.jmxremote.rmi.port=9090 \ -Dcom.sun.management.jmxremote.rmi.port=9090 \
-Djava.rmi.server.hostname=0.0.0.0 \ -Djava.rmi.server.hostname=127.0.0.1 \
-Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.authenticate=false \
-jar seb-server-"${SEBSERVER_VERSION}"-SNAPSHOT.jar \ -jar seb-server-"${SEBSERVER_VERSION}"-SNAPSHOT.jar \

View file

@ -6,7 +6,7 @@ server.servlet.session.cookie.http-only=true
server.servlet.session.tracking-modes=cookie server.servlet.session.tracking-modes=cookie
# database server # database server
datastore.mariadb.server.address=test-mariadb datastore.mariadb.server.address=seb-server-mariadb
datastore.mariadb.server.port=3306 datastore.mariadb.server.port=3306
# data source configuration # data source configuration

View file

@ -8,6 +8,8 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao; package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.Collection;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
@ -21,14 +23,14 @@ public interface ExamConfigurationMapDAO extends
* @param examId The Exam mapping identifier * @param examId The Exam mapping identifier
* @param configurationNodeId the ConfigurationNode mapping identifier * @param configurationNodeId the ConfigurationNode mapping identifier
* @return Result refer to the ExamConfigurationMap with specified mapping or to an exception if happened */ * @return Result refer to the ExamConfigurationMap with specified mapping or to an exception if happened */
public Result<ExamConfigurationMap> byMapping(Long examId, Long configurationNodeId); Result<ExamConfigurationMap> byMapping(Long examId, Long configurationNodeId);
/** Get the password cipher of a specific ExamConfigurationMap by the mapping identifiers /** Get the password cipher of a specific ExamConfigurationMap by the mapping identifiers
* *
* @param examId The Exam mapping identifier * @param examId The Exam mapping identifier
* @param configurationNodeId the ConfigurationNode mapping identifier * @param configurationNodeId the ConfigurationNode mapping identifier
* @return Result refer to the password cipher of specified mapping or to an exception if happened */ * @return Result refer to the password cipher of specified mapping or to an exception if happened */
public Result<CharSequence> getConfigPasswortCipher(Long examId, Long configurationNodeId); Result<CharSequence> getConfigPasswortCipher(Long examId, Long configurationNodeId);
/** Get the ConfigurationNode identifier of the default Exam Configuration of /** Get the ConfigurationNode identifier of the default Exam Configuration of
* the Exam with specified identifier. * the Exam with specified identifier.
@ -36,7 +38,7 @@ public interface ExamConfigurationMapDAO extends
* @param examId The Exam identifier * @param examId The Exam identifier
* @return ConfigurationNode identifier of the default Exam Configuration of * @return ConfigurationNode identifier of the default Exam Configuration of
* the Exam with specified identifier */ * the Exam with specified identifier */
public Result<Long> getDefaultConfigurationForExam(Long examId); Result<Long> getDefaultConfigurationForExam(Long examId);
/** Get the ConfigurationNode identifier of the Exam Configuration of /** Get the ConfigurationNode identifier of the Exam Configuration of
* the Exam for a specified user identifier. * the Exam for a specified user identifier.
@ -45,6 +47,12 @@ public interface ExamConfigurationMapDAO extends
* @param userId the user identifier * @param userId the user identifier
* @return ConfigurationNode identifier of the Exam Configuration of * @return ConfigurationNode identifier of the Exam Configuration of
* the Exam for a specified user identifier */ * the Exam for a specified user identifier */
public Result<Long> getUserConfigurationIdForExam(final Long examId, final String userId); Result<Long> getUserConfigurationIdForExam(final Long examId, final String userId);
/** Get all id of Exams that has a relation to the given configuration id.
*
* @param configurationId
* @return */
Result<Collection<Long>> getExamIdsForConfigId(Long configurationId);
} }

View file

@ -22,12 +22,17 @@ public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSup
Result<Collection<Long>> allIdsOfInstituion(Long institutionId); Result<Collection<Long>> allIdsOfInstituion(Long institutionId);
/** Saves the Exam and updates the running exam cache. */
@Override @Override
@CacheEvict( @CacheEvict(
cacheNames = ExamSessionCacheService.CACHE_NAME_RUNNING_EXAM, cacheNames = ExamSessionCacheService.CACHE_NAME_RUNNING_EXAM,
key = "#exam.id") key = "#exam.id")
Result<Exam> save(Exam exam); Result<Exam> save(Exam exam);
/** Get an Exam by a given ClientConnection id.
*
* @param connectionId
* @return a Result containing the Exam by a given ClientConnection id or refer to an error if happened */
Result<Exam> byClientConnection(Long connectionId); Result<Exam> byClientConnection(Long connectionId);
} }

View file

@ -35,7 +35,9 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.Configuration
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.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamConfigurationMapRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamConfigurationMapRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamConfigurationMapRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamConfigurationMapRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport;
@ -285,6 +287,35 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
return getDependencies(bulkAction, selectionFunction); return getDependencies(bulkAction, selectionFunction);
} }
@Override
@Transactional(readOnly = true)
public Result<Collection<Long>> getExamIdsForConfigId(final Long configurationId) {
return Result.tryCatch(() -> {
final Long configNodeId = this.configurationNodeRecordMapper.selectIdsByExample()
.leftJoin(ConfigurationRecordDynamicSqlSupport.configurationRecord)
.on(
ConfigurationRecordDynamicSqlSupport.configurationNodeId,
equalTo(ConfigurationNodeRecordDynamicSqlSupport.id))
.where(
ConfigurationRecordDynamicSqlSupport.id,
isEqualTo(configurationId))
.build()
.execute()
.stream()
.collect(Utils.toSingleton());
return this.examConfigurationMapRecordMapper.selectByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.configurationNodeId,
isEqualTo(configNodeId))
.build()
.execute()
.stream()
.map(record -> record.getExamId())
.collect(Collectors.toList());
});
}
private Result<ExamConfigurationMapRecord> recordById(final Long id) { private Result<ExamConfigurationMapRecord> recordById(final Long id) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
final ExamConfigurationMapRecord record = this.examConfigurationMapRecordMapper final ExamConfigurationMapRecord record = this.examConfigurationMapRecordMapper

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig;
public class ConfigurationChangedEvent {
public final Long configurationId;
public ConfigurationChangedEvent(final Long configurationId) {
this.configurationId = configurationId;
}
}

View file

@ -12,11 +12,14 @@ import java.io.OutputStream;
import java.util.Collection; import java.util.Collection;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.springframework.context.event.EventListener;
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.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationChangedEvent;
/** A Service to handle running exam sessions */ /** A Service to handle running exam sessions */
public interface ExamSessionService { public interface ExamSessionService {
@ -84,4 +87,7 @@ public interface ExamSessionService {
* of a running exam */ * of a running exam */
Result<Collection<ClientConnectionData>> getConnectionData(Long examId); Result<Collection<ClientConnectionData>> getConnectionData(Long examId);
@EventListener(ConfigurationChangedEvent.class)
void updateExamConfigCache(ConfigurationChangedEvent configChanged);
} }

View file

@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -30,8 +31,10 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
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.servicelayer.dao.ClientConnectionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationChangedEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
@Lazy @Lazy
@ -44,16 +47,19 @@ public class ExamSessionServiceImpl implements ExamSessionService {
private final ClientConnectionDAO clientConnectionDAO; private final ClientConnectionDAO clientConnectionDAO;
private final ExamSessionCacheService examSessionCacheService; private final ExamSessionCacheService examSessionCacheService;
private final ExamDAO examDAO; private final ExamDAO examDAO;
private final ExamConfigurationMapDAO examConfigurationMapDAO;
private final CacheManager cacheManager; private final CacheManager cacheManager;
protected ExamSessionServiceImpl( protected ExamSessionServiceImpl(
final ExamSessionCacheService examSessionCacheService, final ExamSessionCacheService examSessionCacheService,
final ExamDAO examDAO, final ExamDAO examDAO,
final ExamConfigurationMapDAO examConfigurationMapDAO,
final ClientConnectionDAO clientConnectionDAO, final ClientConnectionDAO clientConnectionDAO,
final CacheManager cacheManager) { final CacheManager cacheManager) {
this.examSessionCacheService = examSessionCacheService; this.examSessionCacheService = examSessionCacheService;
this.examDAO = examDAO; this.examDAO = examDAO;
this.examConfigurationMapDAO = examConfigurationMapDAO;
this.clientConnectionDAO = clientConnectionDAO; this.clientConnectionDAO = clientConnectionDAO;
this.cacheManager = cacheManager; this.cacheManager = cacheManager;
} }
@ -191,6 +197,20 @@ public class ExamSessionServiceImpl implements ExamSessionService {
}); });
} }
@Override
@EventListener(ConfigurationChangedEvent.class)
public void updateExamConfigCache(final ConfigurationChangedEvent configChanged) {
if (log.isDebugEnabled()) {
log.debug("Flush exam config cache for configuration: {}", configChanged.configurationId);
}
this.examConfigurationMapDAO
.getExamIdsForConfigId(configChanged.configurationId)
.getOrElse(() -> Collections.emptyList())
.forEach(this.examSessionCacheService::evictDefaultSebConfig);
}
private void flushCache(final Exam exam) { private void flushCache(final Exam exam) {
try { try {
this.examSessionCacheService.evict(exam); this.examSessionCacheService.evict(exam);

View file

@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Collection; import java.util.Collection;
import org.mybatis.dynamic.sql.SqlTable; import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -23,12 +24,14 @@ import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
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.webservice.datalayer.batis.mapper.ConfigurationRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; 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.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationChangedEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@WebServiceProfile @WebServiceProfile
@ -37,6 +40,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
public class ConfigurationController extends ReadonlyEntityController<Configuration, Configuration> { public class ConfigurationController extends ReadonlyEntityController<Configuration, Configuration> {
private final ConfigurationDAO configurationDAO; private final ConfigurationDAO configurationDAO;
private final ApplicationEventPublisher applicationEventPublisher;
protected ConfigurationController( protected ConfigurationController(
final AuthorizationService authorization, final AuthorizationService authorization,
@ -44,7 +48,8 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
final ConfigurationDAO entityDAO, final ConfigurationDAO entityDAO,
final UserActivityLogDAO userActivityLogDAO, final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService, final PaginationService paginationService,
final BeanValidationService beanValidationService) { final BeanValidationService beanValidationService,
final ApplicationEventPublisher applicationEventPublisher) {
super(authorization, super(authorization,
bulkActionService, bulkActionService,
@ -54,6 +59,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
beanValidationService); beanValidationService);
this.configurationDAO = entityDAO; this.configurationDAO = entityDAO;
this.applicationEventPublisher = applicationEventPublisher;
} }
@RequestMapping( @RequestMapping(
@ -67,6 +73,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
.flatMap(this.authorization::checkModify) .flatMap(this.authorization::checkModify)
.flatMap(config -> this.configurationDAO.saveToHistory(config.configurationNodeId)) .flatMap(config -> this.configurationDAO.saveToHistory(config.configurationNodeId))
.flatMap(this.userActivityLogDAO::logSaveToHistory) .flatMap(this.userActivityLogDAO::logSaveToHistory)
.flatMap(this::publishConfigChanged)
.getOrThrow(); .getOrThrow();
} }
@ -81,6 +88,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
.flatMap(this.authorization::checkModify) .flatMap(this.authorization::checkModify)
.flatMap(config -> this.configurationDAO.undo(config.configurationNodeId)) .flatMap(config -> this.configurationDAO.undo(config.configurationNodeId))
.flatMap(this.userActivityLogDAO::logUndo) .flatMap(this.userActivityLogDAO::logUndo)
.flatMap(this::publishConfigChanged)
.getOrThrow(); .getOrThrow();
} }
@ -96,6 +104,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
return this.entityDAO.byModelId(modelId) return this.entityDAO.byModelId(modelId)
.flatMap(this.authorization::checkModify) .flatMap(this.authorization::checkModify)
.flatMap(config -> this.configurationDAO.restoreToVersion(configurationNodeId, config.getId())) .flatMap(config -> this.configurationDAO.restoreToVersion(configurationNodeId, config.getId()))
.flatMap(this::publishConfigChanged)
.getOrThrow(); .getOrThrow();
} }
@ -109,4 +118,9 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
return ConfigurationRecordDynamicSqlSupport.configurationRecord; return ConfigurationRecordDynamicSqlSupport.configurationRecord;
} }
private Result<Configuration> publishConfigChanged(final Configuration config) {
this.applicationEventPublisher.publishEvent(new ConfigurationChangedEvent(config.id));
return Result.of(config);
}
} }

View file

@ -13,6 +13,7 @@ import java.util.Objects;
import javax.validation.Valid; import javax.validation.Valid;
import org.mybatis.dynamic.sql.SqlTable; import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -35,6 +36,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationChangedEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigService;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@ -46,6 +48,7 @@ public class ConfigurationValueController extends EntityController<Configuration
private final ConfigurationDAO configurationDAO; private final ConfigurationDAO configurationDAO;
private final ConfigurationValueDAO configurationValueDAO; private final ConfigurationValueDAO configurationValueDAO;
private final SebExamConfigService sebExamConfigService; private final SebExamConfigService sebExamConfigService;
private final ApplicationEventPublisher applicationEventPublisher;
protected ConfigurationValueController( protected ConfigurationValueController(
final AuthorizationService authorization, final AuthorizationService authorization,
@ -55,7 +58,8 @@ public class ConfigurationValueController extends EntityController<Configuration
final PaginationService paginationService, final PaginationService paginationService,
final BeanValidationService beanValidationService, final BeanValidationService beanValidationService,
final ConfigurationDAO configurationDAO, final ConfigurationDAO configurationDAO,
final SebExamConfigService sebExamConfigService) { final SebExamConfigService sebExamConfigService,
final ApplicationEventPublisher applicationEventPublisher) {
super(authorization, super(authorization,
bulkActionService, bulkActionService,
@ -67,6 +71,19 @@ public class ConfigurationValueController extends EntityController<Configuration
this.configurationDAO = configurationDAO; this.configurationDAO = configurationDAO;
this.configurationValueDAO = entityDAO; this.configurationValueDAO = entityDAO;
this.sebExamConfigService = sebExamConfigService; this.sebExamConfigService = sebExamConfigService;
this.applicationEventPublisher = applicationEventPublisher;
}
@Override
protected Result<ConfigurationValue> notifySaved(final ConfigurationValue entity) {
if (entity == null) {
return super.notifySaved(entity);
}
this.applicationEventPublisher.publishEvent(
new ConfigurationChangedEvent(entity.configurationId));
return super.notifySaved(entity);
} }
@Override @Override
@ -124,6 +141,11 @@ public class ConfigurationValueController extends EntityController<Configuration
return this.configurationDAO.byPK(tableValue.configurationId) return this.configurationDAO.byPK(tableValue.configurationId)
.flatMap(this.authorization::checkModify) .flatMap(this.authorization::checkModify)
.flatMap(config -> this.configurationValueDAO.saveTableValues(tableValue)) .flatMap(config -> this.configurationValueDAO.saveTableValues(tableValue))
.map(config -> {
this.applicationEventPublisher.publishEvent(
new ConfigurationChangedEvent(config.configurationId));
return config;
})
.getOrThrow(); .getOrThrow();
} }

View file

@ -88,7 +88,7 @@ public class HTTPClientBot {
this.apiVersion = args.getOrDefault("apiVersion", "v1"); this.apiVersion = args.getOrDefault("apiVersion", "v1");
this.examId = args.getOrDefault("examId", "2"); this.examId = args.getOrDefault("examId", "2");
this.institutionId = args.getOrDefault("institutionId", "1"); this.institutionId = args.getOrDefault("institutionId", "1");
this.numberOfConnections = Integer.parseInt(args.getOrDefault("numberOfConnections", "4")); this.numberOfConnections = Integer.parseInt(args.getOrDefault("numberOfConnections", "1"));
this.pingInterval = Long.parseLong(args.getOrDefault("pingInterval", "200")); this.pingInterval = Long.parseLong(args.getOrDefault("pingInterval", "200"));
this.errorInterval = Long.parseLong(args.getOrDefault("errorInterval", String.valueOf(TEN_SECONDS))); this.errorInterval = Long.parseLong(args.getOrDefault("errorInterval", String.valueOf(TEN_SECONDS)));
this.runtime = Long.parseLong(args.getOrDefault("runtime", String.valueOf(ONE_MINUTE))); this.runtime = Long.parseLong(args.getOrDefault("runtime", String.valueOf(ONE_MINUTE)));

View file

@ -6,7 +6,7 @@
</encoder> </encoder>
</appender> </appender>
<Logger name="org.eth.demo.sebserver" level="TRACE" additivity="true" /> <Logger name="ch.ethz.seb.sebserver.HTTPClientBot" level="TRACE" additivity="true" />
<root level="INFO" additivity="true"> <root level="INFO" additivity="true">
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />