GitLab wurde aktualisiert. Dank regelmäßiger Updates bleibt das THM GitLab sicher und Sie profitieren von den neuesten Funktionen. Vielen Dank für Ihre Geduld.

Commit 0ae62670 authored by Daniel Gerhardt's avatar Daniel Gerhardt
Browse files

Merge branch 'db-ektorp' into 'master'

Migration to Ektorp and refactoring of the database layer

A summary of the changes:
* CouchDB4J has been replaced by Ektorp.
* CouchDBDao has been split up into multiple repositories: One for each
  entity.
* Jackson is used instead of JSON-lib for POJO <-> JSON
  (de)serialization.
    * Jackson's `@JsonView`'s are used to mark which properties are
      (de)serialized for the API and/or CouchDB
    * A lot of persistence code could be simplified since serialization
      is handled automatically by the `ObjectMapper`.
* Entities and related Classes have been renamed:
    * `Content` <- `Question` / `SkillQuestion` / `LecturerQuestion`
    * `Comment` <- `FeedbackQuestion` / `AudienceQuestion`
* CouchDB design docs can now be automatically created by the backend if
  necessary. They are included as JavaScript code which is parsed and
  transformed to JSON at startup using Java's `ScriptEngine`.
* `MediaType`s for API versioning have been introduced:
    * `vnd.de.thm.arsnova.v2+json`: the format as used in ARSnova 2.x
    * `vnd.de.thm.arsnova.v3+json`:
        * ISO 8601 dates instead of timestamps
        * `id` instead of `_id`, `revision` instead of `_rev`
* `api.indent-response-body` can be set in configuration for pretty
  responses for API debugging.
* Empty (e.g. `null`) entity properties are ignored for serialization

See merge request !68
parents d47c41ff d54b3263
...@@ -121,6 +121,12 @@ ...@@ -121,6 +121,12 @@
<groupId>commons-lang</groupId> <groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
</dependency> </dependency>
<!-- While commons-logging is not a required dependency, AJC fails without it. -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring --> <!-- Spring -->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
...@@ -186,9 +192,14 @@ ...@@ -186,9 +192,14 @@
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>de.thm.couchdb4j</groupId> <groupId>org.ektorp</groupId>
<artifactId>couchdb4j</artifactId> <artifactId>org.ektorp</artifactId>
<version>0.8-SNAPSHOT</version> <version>1.4.4</version>
</dependency>
<dependency>
<groupId>org.ektorp</groupId>
<artifactId>org.ektorp.spring</artifactId>
<version>1.4.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
......
...@@ -30,11 +30,11 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor { ...@@ -30,11 +30,11 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor {
@CacheEvict(value = "statistics", allEntries = true) @CacheEvict(value = "statistics", allEntries = true)
@Override @Override
public void visit(NewInterposedQuestionEvent event) { } public void visit(NewCommentEvent event) { }
@CacheEvict(value = "statistics", allEntries = true) @CacheEvict(value = "statistics", allEntries = true)
@Override @Override
public void visit(DeleteInterposedQuestionEvent event) { } public void visit(DeleteCommentEvent event) { }
@Override @Override
public void visit(NewQuestionEvent event) { } public void visit(NewQuestionEvent event) { }
...@@ -51,7 +51,7 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor { ...@@ -51,7 +51,7 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor {
@Override @Override
public void visit(LockQuestionsEvent lockQuestionsEvent) { } public void visit(LockQuestionsEvent lockQuestionsEvent) { }
@CacheEvict(value = "answers", key = "#event.Question") @CacheEvict(value = "answers", key = "#event.content")
@Override @Override
public void visit(NewAnswerEvent event) { } public void visit(NewAnswerEvent event) { }
......
...@@ -18,16 +18,27 @@ ...@@ -18,16 +18,27 @@
package de.thm.arsnova.config; package de.thm.arsnova.config;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import de.thm.arsnova.ImageUtils; import de.thm.arsnova.ImageUtils;
import de.thm.arsnova.connector.client.ConnectorClient; import de.thm.arsnova.connector.client.ConnectorClient;
import de.thm.arsnova.connector.client.ConnectorClientImpl; import de.thm.arsnova.connector.client.ConnectorClientImpl;
import de.thm.arsnova.entities.*;
import de.thm.arsnova.entities.serialization.CouchDbDocumentModule;
import de.thm.arsnova.entities.serialization.CouchDbObjectMapperFactory;
import de.thm.arsnova.entities.serialization.View;
import de.thm.arsnova.persistance.*;
import de.thm.arsnova.persistance.couchdb.*;
import de.thm.arsnova.persistance.couchdb.InitializingCouchDbConnector;
import de.thm.arsnova.socket.ARSnovaSocket; import de.thm.arsnova.socket.ARSnovaSocket;
import de.thm.arsnova.socket.ARSnovaSocketIOServer; import de.thm.arsnova.socket.ARSnovaSocketIOServer;
import de.thm.arsnova.web.CacheControlInterceptorHandler; import de.thm.arsnova.web.CacheControlInterceptorHandler;
import de.thm.arsnova.web.CorsFilter; import de.thm.arsnova.web.CorsFilter;
import de.thm.arsnova.web.DeprecatedApiInterceptorHandler; import de.thm.arsnova.web.DeprecatedApiInterceptorHandler;
import de.thm.arsnova.web.ResponseInterceptorHandler; import de.thm.arsnova.web.ResponseInterceptorHandler;
import org.ektorp.CouchDbConnector;
import org.ektorp.impl.StdCouchDbInstance;
import org.ektorp.spring.HttpClientFactoryBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.beans.factory.config.PropertiesFactoryBean;
...@@ -60,6 +71,7 @@ import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; ...@@ -60,6 +71,7 @@ import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -114,8 +126,8 @@ public class AppConfig extends WebMvcConfigurerAdapter { ...@@ -114,8 +126,8 @@ public class AppConfig extends WebMvcConfigurerAdapter {
@Override @Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(stringMessageConverter()); converters.add(stringMessageConverter());
converters.add(defaultJsonMessageConverter());
converters.add(apiV2JsonMessageConverter()); converters.add(apiV2JsonMessageConverter());
converters.add(defaultJsonMessageConverter());
//converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); //converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
} }
...@@ -163,6 +175,8 @@ public class AppConfig extends WebMvcConfigurerAdapter { ...@@ -163,6 +175,8 @@ public class AppConfig extends WebMvcConfigurerAdapter {
@Bean @Bean
public StringHttpMessageConverter stringMessageConverter() { public StringHttpMessageConverter stringMessageConverter() {
StringHttpMessageConverter messageConverter = new StringHttpMessageConverter(); StringHttpMessageConverter messageConverter = new StringHttpMessageConverter();
messageConverter.setDefaultCharset(Charset.forName("UTF-8"));
messageConverter.setWriteAcceptCharset(false);
List<MediaType> mediaTypes = new ArrayList<>(); List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.TEXT_PLAIN); mediaTypes.add(MediaType.TEXT_PLAIN);
messageConverter.setSupportedMediaTypes(mediaTypes); messageConverter.setSupportedMediaTypes(mediaTypes);
...@@ -178,7 +192,9 @@ public class AppConfig extends WebMvcConfigurerAdapter { ...@@ -178,7 +192,9 @@ public class AppConfig extends WebMvcConfigurerAdapter {
.defaultViewInclusion(false) .defaultViewInclusion(false)
.indentOutput(apiIndent) .indentOutput(apiIndent)
.simpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); .simpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(builder.build()); ObjectMapper mapper = builder.build();
mapper.setConfig(mapper.getSerializationConfig().withView(View.Public.class));
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
List<MediaType> mediaTypes = new ArrayList<>(); List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(API_V3_MEDIA_TYPE); mediaTypes.add(API_V3_MEDIA_TYPE);
mediaTypes.add(MediaType.APPLICATION_JSON_UTF8); mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
...@@ -195,8 +211,11 @@ public class AppConfig extends WebMvcConfigurerAdapter { ...@@ -195,8 +211,11 @@ public class AppConfig extends WebMvcConfigurerAdapter {
.defaultViewInclusion(false) .defaultViewInclusion(false)
.indentOutput(apiIndent) .indentOutput(apiIndent)
.featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.featuresToEnable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS); .featuresToEnable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(builder.build()); .modules(new CouchDbDocumentModule());
ObjectMapper mapper = builder.build();
mapper.setConfig(mapper.getSerializationConfig().withView(View.Public.class));
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
List<MediaType> mediaTypes = new ArrayList<>(); List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(API_V2_MEDIA_TYPE); mediaTypes.add(API_V2_MEDIA_TYPE);
mediaTypes.add(MediaType.APPLICATION_JSON_UTF8); mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
......
package de.thm.arsnova.config;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.Comment;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.entities.LogEntry;
import de.thm.arsnova.entities.Motd;
import de.thm.arsnova.entities.MotdList;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.VisitedSession;
import de.thm.arsnova.entities.serialization.CouchDbObjectMapperFactory;
import de.thm.arsnova.persistance.*;
import de.thm.arsnova.persistance.couchdb.*;
import org.ektorp.CouchDbConnector;
import org.ektorp.impl.StdCouchDbInstance;
import org.ektorp.spring.HttpClientFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("!test")
public class PersistanceConfig {
@Value("${couchdb.name}") private String couchDbName;
@Value("${couchdb.host}") private String couchDbHost;
@Value("${couchdb.port}") private int couchDbPort;
@Bean
public CouchDbConnector couchDbConnector() throws Exception {
return new InitializingCouchDbConnector(couchDbName, couchDbInstance(), new CouchDbObjectMapperFactory());
}
@Bean
public StdCouchDbInstance couchDbInstance() throws Exception {
return new StdCouchDbInstance(couchDbHttpClientFactory().getObject());
}
@Bean
public HttpClientFactoryBean couchDbHttpClientFactory() throws Exception {
final HttpClientFactoryBean factory = new HttpClientFactoryBean();
factory.setHost(couchDbHost);
factory.setPort(couchDbPort);
return factory;
}
@Bean
public LogEntryRepository logEntryRepository() throws Exception {
return new CouchDbLogEntryRepository(LogEntry.class, couchDbConnector(), false);
}
@Bean
public UserRepository userRepository() throws Exception {
return new CouchDbUserRepository(DbUser.class, couchDbConnector(), false);
}
@Bean
public SessionRepository sessionRepository() throws Exception {
return new CouchDbSessionRepository(Session.class, couchDbConnector(), false);
}
@Bean
public CommentRepository commentRepository() throws Exception {
return new CouchDbCommentRepository(Comment.class, couchDbConnector(), false);
}
@Bean
public ContentRepository contentRepository() throws Exception {
return new CouchDbContentRepository(Content.class, couchDbConnector(), false);
}
@Bean
public AnswerRepository answerRepository() throws Exception {
return new CouchDbAnswerRepository(Answer.class, couchDbConnector(), false);
}
@Bean
public MotdRepository motdRepository() throws Exception {
return new CouchDbMotdRepository(Motd.class, couchDbConnector(), false);
}
@Bean
public MotdListRepository motdListRepository() throws Exception {
return new CouchDbMotdListRepository(MotdList.class, couchDbConnector(), false);
}
@Bean
public VisitedSessionRepository visitedSessionRepository() throws Exception {
return new CouchDbVisitedSessionRepository(VisitedSession.class, couchDbConnector(), false);
}
@Bean
public StatisticsRepository statisticsRepository() throws Exception {
return new CouchDbStatisticsRepository(Object.class, couchDbConnector(), false);
}
@Bean
public SessionStatisticsRepository sessionStatisticsRepository() throws Exception {
return new CouchDbSessionStatisticsRepository(Object.class, couchDbConnector(), false);
}
}
...@@ -17,10 +17,10 @@ ...@@ -17,10 +17,10 @@
*/ */
package de.thm.arsnova.controller; package de.thm.arsnova.controller;
import de.thm.arsnova.entities.InterposedReadingCount; import de.thm.arsnova.entities.CommentReadingCount;
import de.thm.arsnova.entities.transport.InterposedQuestion; import de.thm.arsnova.entities.transport.Comment;
import de.thm.arsnova.exceptions.BadRequestException; import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.services.IQuestionService; import de.thm.arsnova.services.IContentService;
import de.thm.arsnova.web.DeprecatedApi; import de.thm.arsnova.web.DeprecatedApi;
import de.thm.arsnova.web.Pagination; import de.thm.arsnova.web.Pagination;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
...@@ -41,50 +41,50 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -41,50 +41,50 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
/** /**
* Handles requests related to audience questions, which are also called interposed or feedback questions. * Handles requests related to comments.
*/ */
@RestController @RestController
@RequestMapping("/audiencequestion") @RequestMapping("/audiencequestion")
@Api(value = "/audiencequestion", description = "the Audience Question API") @Api(value = "/audiencequestion", description = "the Audience Content API")
public class AudienceQuestionController extends PaginationController { public class CommentController extends PaginationController {
@Autowired @Autowired
private IQuestionService questionService; private IContentService contentService;
@ApiOperation(value = "Count all the questions in current session", @ApiOperation(value = "Count all the comments in current session",
nickname = "getAudienceQuestionCount") nickname = "getAudienceQuestionCount")
@RequestMapping(value = "/count", method = RequestMethod.GET) @RequestMapping(value = "/count", method = RequestMethod.GET)
@DeprecatedApi @DeprecatedApi
@Deprecated @Deprecated
public int getInterposedCount(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey) { public int getInterposedCount(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey) {
return questionService.getInterposedCount(sessionkey); return contentService.getInterposedCount(sessionkey);
} }
@ApiOperation(value = "count all unread interposed questions", @ApiOperation(value = "count all unread comments",
nickname = "getUnreadInterposedCount") nickname = "getUnreadInterposedCount")
@RequestMapping(value = "/readcount", method = RequestMethod.GET) @RequestMapping(value = "/readcount", method = RequestMethod.GET)
@DeprecatedApi @DeprecatedApi
@Deprecated @Deprecated
public InterposedReadingCount getUnreadInterposedCount(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam("sessionkey") final String sessionkey, String user) { public CommentReadingCount getUnreadInterposedCount(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam("sessionkey") final String sessionkey, String user) {
return questionService.getInterposedReadingCount(sessionkey, user); return contentService.getInterposedReadingCount(sessionkey, user);
} }
@ApiOperation(value = "Retrieves all Interposed Questions for a Session", @ApiOperation(value = "Retrieves all Comments for a Session",
nickname = "getInterposedQuestions") nickname = "getInterposedQuestions")
@RequestMapping(value = "/", method = RequestMethod.GET) @RequestMapping(value = "/", method = RequestMethod.GET)
@Pagination @Pagination
public List<InterposedQuestion> getInterposedQuestions(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey) { public List<Comment> getInterposedQuestions(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey) {
return InterposedQuestion.fromList(questionService.getInterposedQuestions(sessionkey, offset, limit)); return Comment.fromList(contentService.getInterposedQuestions(sessionkey, offset, limit));
} }
@ApiOperation(value = "Retrieves an InterposedQuestion", @ApiOperation(value = "Retrieves an Comment",
nickname = "getInterposedQuestion") nickname = "getInterposedQuestion")
@RequestMapping(value = "/{questionId}", method = RequestMethod.GET) @RequestMapping(value = "/{questionId}", method = RequestMethod.GET)
public InterposedQuestion getInterposedQuestion(@ApiParam(value = "ID of the question that needs to be deleted", required = true) @PathVariable final String questionId) { public Comment getInterposedQuestion(@ApiParam(value = "ID of the Comment that needs to be deleted", required = true) @PathVariable final String questionId) {
return new InterposedQuestion(questionService.readInterposedQuestion(questionId)); return new Comment(contentService.readInterposedQuestion(questionId));
} }
@ApiOperation(value = "Creates a new Interposed Question for a Session and returns the InterposedQuestion's data", @ApiOperation(value = "Creates a new Comment for a Session and returns the Comment's data",
nickname = "postInterposedQuestion") nickname = "postInterposedQuestion")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(code = 400, message = HTML_STATUS_400) @ApiResponse(code = 400, message = HTML_STATUS_400)
...@@ -93,19 +93,19 @@ public class AudienceQuestionController extends PaginationController { ...@@ -93,19 +93,19 @@ public class AudienceQuestionController extends PaginationController {
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
public void postInterposedQuestion( public void postInterposedQuestion(
@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey, @ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey,
@ApiParam(value = "the body from the new question", required = true) @RequestBody final de.thm.arsnova.entities.InterposedQuestion question @ApiParam(value = "the body from the new comment", required = true) @RequestBody final de.thm.arsnova.entities.Comment comment
) { ) {
if (questionService.saveQuestion(question)) { if (contentService.saveQuestion(comment)) {
return; return;
} }
throw new BadRequestException(); throw new BadRequestException();
} }
@ApiOperation(value = "Deletes an InterposedQuestion", @ApiOperation(value = "Deletes a Comment",
nickname = "deleteInterposedQuestion") nickname = "deleteInterposedQuestion")
@RequestMapping(value = "/{questionId}", method = RequestMethod.DELETE) @RequestMapping(value = "/{questionId}", method = RequestMethod.DELETE)
public void deleteInterposedQuestion(@ApiParam(value = "ID of the question that needs to be deleted", required = true) @PathVariable final String questionId) { public void deleteInterposedQuestion(@ApiParam(value = "ID of the comment that needs to be deleted", required = true) @PathVariable final String questionId) {
questionService.deleteInterposedQuestion(questionId); contentService.deleteInterposedQuestion(questionId);
} }
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
*/ */
package de.thm.arsnova.controller; package de.thm.arsnova.controller;
import de.thm.arsnova.services.IQuestionService; import de.thm.arsnova.services.IContentService;
import de.thm.arsnova.web.DeprecatedApi; import de.thm.arsnova.web.DeprecatedApi;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
...@@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.ResponseBody; ...@@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
public class LegacyController extends AbstractController { public class LegacyController extends AbstractController {
@Autowired @Autowired
private IQuestionService questionService; private IContentService contentService;
/* specific routes */ /* specific routes */
...@@ -95,7 +95,7 @@ public class LegacyController extends AbstractController { ...@@ -95,7 +95,7 @@ public class LegacyController extends AbstractController {
@RequestMapping(value = "/session/{sessionKey}/interposed", method = RequestMethod.DELETE) @RequestMapping(value = "/session/{sessionKey}/interposed", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
public void deleteAllInterposedQuestions(@PathVariable final String sessionKey) { public void deleteAllInterposedQuestions(@PathVariable final String sessionKey) {
questionService.deleteAllInterposedQuestions(sessionKey); contentService.deleteAllInterposedQuestions(sessionKey);
} }
@DeprecatedApi @DeprecatedApi
......
...@@ -298,7 +298,7 @@ public class SessionController extends PaginationController { ...@@ -298,7 +298,7 @@ public class SessionController extends PaginationController {
public List<ImportExportSession> getExport( public List<ImportExportSession> getExport(
@ApiParam(value = "sessionkey", required = true) @RequestParam(value = "sessionkey", defaultValue = "") final List<String> sessionkey, @ApiParam(value = "sessionkey", required = true) @RequestParam(value = "sessionkey", defaultValue = "") final List<String> sessionkey,
@ApiParam(value = "wether statistics shall be exported", required = true) @RequestParam(value = "withAnswerStatistics", defaultValue = "false") final Boolean withAnswerStatistics, @ApiParam(value = "wether statistics shall be exported", required = true) @RequestParam(value = "withAnswerStatistics", defaultValue = "false") final Boolean withAnswerStatistics,
@ApiParam(value = "wether interposed questions shall be exported", required = true) @RequestParam(value = "withFeedbackQuestions", defaultValue = "false") final Boolean withFeedbackQuestions, @ApiParam(value = "wether comments shall be exported", required = true) @RequestParam(value = "withFeedbackQuestions", defaultValue = "false") final Boolean withFeedbackQuestions,
final HttpServletResponse response final HttpServletResponse response
) { ) {
List<ImportExportSession> sessions = new ArrayList<>(); List<ImportExportSession> sessions = new ArrayList<>();
......
This diff is collapsed.
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2017 The ARSnova Team
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.dao;
import com.fourspaces.couchdb.View;
import de.thm.arsnova.connector.model.Course;
import de.thm.arsnova.domain.CourseScore;
import de.thm.arsnova.entities.*;
import de.thm.arsnova.entities.transport.ImportExportSession;
import java.util.List;
import java.util.Map;
/**
* All methods the database must support.
*/
public interface IDatabaseDao {
/**
* Logs an event to the database. Arbitrary data can be attached as payload. Database logging should only be used
* if the logged data is later analyzed by the backend itself. Otherwise use the default logging mechanisms.
*
* @param event type of the event
* @param payload arbitrary logging data
* @param level severity of the event
*/
void log(String event, Map<String, Object> payload, LogEntry.LogLevel level);
/**
* Logs an event of informational severity to the database. Arbitrary data can be attached as payload. Database
* logging should only be used if the logged data is later analyzed by the backend itself. Otherwise use the default
* logging mechanisms.
*
* @param event type of the event
* @param payload arbitrary logging data
*/
void log(String event, Map<String, Object> payload);
/**
* Logs an event to the database. Arbitrary data can be attached as payload. Database logging should only be used
* if the logged data is later analyzed by the backend itself. Otherwise use the default logging mechanisms.
*