diff --git a/README.md b/README.md
index 87be8ef895ca6ea300339e02cf23da113873cf49..9646c934fbbae587ac3ddae0cc74befa3357a465 100644
--- a/README.md
+++ b/README.md
@@ -4,18 +4,67 @@ ARSnova is a modern approach to Audience Response Systems (ARS). It is released
 
 ![ARSnova](src/site/resources/showcase.png)
 
-ARSnova consists of two projects: the mobile client and the server. This repository contains the server code. You will find the client at thm-projects/arsnova-st2-js. However, you do not need to download both respositories in order to get started.
+ARSnova consists of two projects: the mobile client and the server. This repository contains the server code. You will find the client at thm-projects/arsnova-mobile. However, you do not need to download both repositories in order to get started.
 
 ## Getting Started
 
-This is the main repository. Almost all dependencies (including the mobile client) are managed for you by Maven.  The mobile client is served via `index.html`, and optionally via `developer.html`. 
+This is the main repository. Almost all dependencies (including the mobile client) are managed for you by Maven.
 
-## Configuration
+### Download
 
-You will need to do some configuration work upfront.
+If you have no intention in contributing, you might want to consider downloading one of our pre-built WAR archives. You will find them in our [Maven repository](https://maven.mni.thm.de/content/repositories/snapshots/de/thm/arsnova/arsnova-war/2.0.0-SNAPSHOT/), but please do note that we are not officially offering these archives.
 
- * Add a new directory "arsnova" in `/etc`, and create a copy of arsnova.properties.example named arsnova.properties in this directory.
- * Change settings to match your environment
+### Building
+
+ARSnova consists of two main projects: arsnova-war (this repository) and arsnova-mobile. By building arsnova-war, you will automatically download the mobile client. If you do not plan to work on the client, you won't need to build it separately.
+
+Because all dependencies are handled by Maven, a complete build is done with:
+
+	mvn install
+
+### Development
+
+You need three things to get started developing ARSnova:
+
+1. the configuration file,
+2. a CouchDB database including several view documents,
+3. and a development server.
+
+We will cover all three in the following sections.
+
+#### Configuration
+
+You will need to do some configuration work upfront: add a new directory "arsnova" in `/etc`, and create a copy of [arsnova.properties.example](src/main/webapp/arsnova.properties.example) named `arsnova.properties` in this directory. Then change the settings to match your environment, e.g. you might want to change the URLs.
+
+Also, don't forget to change all properties starting with `couchdb`, if you do not want to use our defaults. The properties are used in the next section.
+
+*A note to Windows users*: our settings are based on Linux and Mac environments. We do not officially support Windows, so you have to do some extra steps. The property file's path is hard coded in [spring-main.xml](src/main/webapp/WEB-INF/spring/spring-main.xml) and in the "Setup Tool" (see next section). You want to change the paths to make them match your environment. 
+
+#### Database
+
+We provide a Python script that will set up all database essentials. This "Setup Tool" is located at [thm-projects/setuptool](https://github.com/thm-projects/setuptool). Make sure you have configured your database credentials inside the ARSnova configuration file (see previous section): you will need to have the entries `couchdb.username` and `couchdb.password`.
+
+To set up the database, run:
+	
+	python tool.py
+
+This will create the database along with all required view documents. Note that this script requires Python 2 and will not run with Python 3.
+
+#### Developer Mode
+
+The easiest way to deploy ARSnova is via Jetty:
+
+	mvn jetty:run -Dmobile.path=
+	
+This will work out of the box. ARSnova will be located at <http://localhost:8080/>. 
+
+If you're wondering what that `-Dmobile.path=` thing is doing, this is a special override property for Jetty. By default, this property points to a local version of ARSnova mobile located at `../arsnova-mobile` &mdash; relative to the location of this project. If you happen to have downloaded ARSnova mobile to this location, you may skip the override, and just use:
+	
+	mvn jetty:run
+
+## Production Use
+
+If you intend to use ARSnova in productive environments, you will have to do some additional configuration work.
 
 ### Server
 
@@ -42,14 +91,6 @@ To enable the required Apache Webserver modules simply type:
 
 The configuration is ready for development usage. Finally, you should (re)start all services. ARSnova is now listening on HTTP port 80.
 
-### Database
-
-We provide a script that will set up all database essentials. This "Setup Tool" is located at <https://github.com/thm-projects/setuptool>. Make sure you have configured your database credentials inside the ARSnova configuration file: you will need to have the entries `couchdb.username` and `couchdb.password`.
-
-## Production Use
-
-If you intend to use ARSnova in productive environments, you will have to do some additional configuration work.
-
 ### Session Persistence
 
 Look for your Tomcat configuration directory and change the file "context.xml" to match this example:
diff --git a/pom.xml b/pom.xml
index 613f49cf50d69dcfc361cd0546d8ce242910fdb1..dfb42a89fa9ddaf573fe48dcc6265e5b616ab1c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,6 +11,7 @@
 		<org.springframework.security-version>3.2.0.RELEASE</org.springframework.security-version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.url>https://scm.thm.de/arsnova</project.url>
+		<mobile.path>../arsnova-mobile/src/main/webapp/build/production/ARSnova</mobile.path>
 	</properties>
 
 	<developers>
@@ -327,7 +328,7 @@
 		<dependency>
 			<groupId>de.thm.arsnova.connector</groupId>
 			<artifactId>connector-client</artifactId>
-			<version>0.14.0-SNAPSHOT</version>
+			<version>0.40.1-SNAPSHOT</version>
 		</dependency>
 	</dependencies>
 	<build>
@@ -351,7 +352,7 @@
 					<webApp> 
 						<contextPath>/</contextPath>
 						<baseResource implementation="org.eclipse.jetty.util.resource.ResourceCollection">
-							<resourcesAsCSV>src/main/webapp,../arsnova-mobile/src/main/webapp</resourcesAsCSV> 
+							<resourcesAsCSV>src/main/webapp,${mobile.path}</resourcesAsCSV> 
 						</baseResource>
 						<overrideDescriptor>src/main/webapp/WEB-INF/web-dev.xml</overrideDescriptor>
 					</webApp>
@@ -360,7 +361,7 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-site-plugin</artifactId>
-				<version>3.1</version>
+				<version>3.3</version>
 				<configuration>
 					<locales>en</locales>
 				</configuration>
diff --git a/src/main/java/de/thm/arsnova/FeedbackStorage.java b/src/main/java/de/thm/arsnova/FeedbackStorage.java
index 7f62d24c32e3f87709eca27b7332603b0edb4b94..dcdd11b845d1301489dee7d6f08e4e47baeaddf1 100644
--- a/src/main/java/de/thm/arsnova/FeedbackStorage.java
+++ b/src/main/java/de/thm/arsnova/FeedbackStorage.java
@@ -1,7 +1,6 @@
 package de.thm.arsnova;
 
 import java.util.Date;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -41,7 +40,7 @@ public class FeedbackStorage {
 	private IDatabaseDao dao;
 	
 	public FeedbackStorage(IDatabaseDao newDao) {
-		this.data = new ConcurrentHashMap<String, Map<String,FeedbackStorageObject>>();
+		this.data = new ConcurrentHashMap<String, Map<String, FeedbackStorageObject>>();
 		this.dao = newDao;
 	}
 
@@ -104,8 +103,6 @@ public class FeedbackStorage {
 			data.put(keyword, new ConcurrentHashMap<String, FeedbackStorageObject>());
 		}
 		
-		System.out.println(user.getUsername());
-		
 		data.get(keyword).put(user.getUsername(), new FeedbackStorageObject(value, user));
 		return true;
 	}
diff --git a/src/main/java/de/thm/arsnova/ImageUtils.java b/src/main/java/de/thm/arsnova/ImageUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..0af116547c229c335ee88ca292528365c927cf7c
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/ImageUtils.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2014 THM webMedia
+ *
+ * This file is part of ARSnova.
+ *
+ * ARSnova 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 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;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.imageio.ImageIO;
+
+import org.apache.commons.codec.binary.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util class for image operations.
+ * 
+ * @author Daniel Vogel (daniel.vogel@mni.thm.de)
+ *
+ */
+public class ImageUtils {
+	public static final Logger LOGGER = LoggerFactory.getLogger(ImageUtils.class);
+
+	/**
+	 * Converts an image to an Base64 String.
+	 * 
+	 * @param  imageUrl The image url as a {@link String}
+	 * @return The Base64 {@link String} of the image on success, otherwise <code>null</code>.
+	 */
+	public static String encodeImageToString(String imageUrl) {
+		
+		String[]      urlParts = imageUrl.split("\\.");
+		StringBuilder result   = new StringBuilder();
+		
+		// get format
+	    //
+	    // The format is read dynamically. We have to take control
+	    // in the frontend that no unsupported formats are transmitted!
+	    if ( urlParts.length > 0 ) {
+
+			String extension = urlParts[urlParts.length-1];
+
+	    	result.append("data:image/" + extension + ";base64,");
+	    	result.append(Base64.encodeBase64String(convertFileToByteArray(imageUrl)));
+	    	
+			return result.toString();
+	    }
+	    
+		return null;
+	}
+	
+	/**
+	 * Gets the bytestream of an image url.
+	 * s
+	 * @param  imageUrl The image url as a {@link String}
+	 * @return The <code>byte[]</code> of the image on success, otherwise <code>null</code>.
+	 */
+	public static byte[] convertImageToByteArray(String imageUrl, String extension) {
+
+		try {
+			URL 				  url   = new URL(imageUrl);
+			BufferedImage 		  image = ImageIO.read(url);
+		    ByteArrayOutputStream baos  = new ByteArrayOutputStream();
+
+		    ImageIO.write(image, extension, baos);
+		    
+		    baos.flush();
+		    baos.close();
+		    return baos.toByteArray();
+		    
+		} catch (MalformedURLException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		} catch (IOException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		}
+
+	    return null;
+	}
+	
+	/**
+	 * Gets the bytestream of an image url.
+	 * s
+	 * @param  imageUrl The image url as a {@link String}
+	 * @return The <code>byte[]</code> of the image on success, otherwise <code>null</code>.
+	 */
+	public static byte[] convertFileToByteArray(String imageUrl) {
+
+		try {
+			URL 				  url   = new URL(imageUrl);
+		    ByteArrayOutputStream baos  = new ByteArrayOutputStream();
+		    
+		    InputStream is = url.openStream();
+		    byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
+		    int n;
+
+		    while ( (n = is.read(byteChunk)) > 0 ) {
+		    	baos.write(byteChunk, 0, n);
+		    }
+
+		    baos.flush();
+		    baos.close();
+		    
+		    return baos.toByteArray();
+		    
+		} catch (MalformedURLException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		} catch (IOException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		}
+
+	    return null;
+	}
+}
+
diff --git a/src/main/java/de/thm/arsnova/aop/UserSessionAspect.java b/src/main/java/de/thm/arsnova/aop/UserSessionAspect.java
index 56f1158cd966511b8efb2b74a0b0cb3163ef079d..690fdd241bf238dfcb89f3009e9af7d4976f1c11 100644
--- a/src/main/java/de/thm/arsnova/aop/UserSessionAspect.java
+++ b/src/main/java/de/thm/arsnova/aop/UserSessionAspect.java
@@ -1,7 +1,5 @@
 package de.thm.arsnova.aop;
 
-import java.util.UUID;
-
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.AfterReturning;
 import org.aspectj.lang.annotation.Aspect;
@@ -16,35 +14,17 @@ public class UserSessionAspect {
 	@Autowired
 	private UserSessionService userSessionService;
 
-	/** Sets current user and ARSnova session in session scoped UserSessionService 
-	 * 
+	/** Sets current user and ARSnova session in session scoped UserSessionService
+	 *
 	 * @param jp
 	 * @param keyword
 	 * @param session
 	 */
 	@AfterReturning(
-		pointcut="execution(public * de.thm.arsnova.services.SessionService.joinSession(..)) && args(keyword)",
-		returning="session"
-	)
+			pointcut="execution(public * de.thm.arsnova.services.SessionService.joinSession(..)) && args(keyword)",
+			returning="session"
+			)
 	public final void joinSessionAdvice(final JoinPoint jp, final String keyword, final Session session) {
 		userSessionService.setSession(session);
 	}
-
-	/** Sets current user, ARSnova session and websocket session ID in session scoped UserSessionService 
-	 * 
-	 * @param jp
-	 * @param keyword
-	 * @param socketId
-	 * @param session
-	 */
-	/* FIXME This is not working because of scoping problems
-	@AfterReturning(
-		pointcut="execution(public * de.thm.arsnova.services.SessionService.joinSession(..)) && args(keyword, socketId)",
-		returning="session"
-	)
-	public final void joinSessionAdviceWithWebsocket(final JoinPoint jp, final String keyword, final UUID socketId, final Session session) {
-		userSessionService.setSession(session);
-		userSessionService.setSocketId(socketId);
-	}
-	*/
 }
diff --git a/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java b/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java
index d390d7a5f05a172e78c944e1b9c63acc792f5537..5b606d54e098552f0e566e5bedc5de74d62c6aaa 100644
--- a/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java
+++ b/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java
@@ -117,4 +117,5 @@ public class AudienceQuestionController extends AbstractController {
 	) {
 		questionService.deleteInterposedQuestion(questionId);
 	}
+
 }
diff --git a/src/main/java/de/thm/arsnova/controller/LecturerQuestionController.java b/src/main/java/de/thm/arsnova/controller/LecturerQuestionController.java
index fec00c97a4bb5dbe430e1b7a7b96179d81c1fdfd..a26dc791ca87297e75f9efee72864026337f4e84 100644
--- a/src/main/java/de/thm/arsnova/controller/LecturerQuestionController.java
+++ b/src/main/java/de/thm/arsnova/controller/LecturerQuestionController.java
@@ -99,6 +99,20 @@ public class LecturerQuestionController extends AbstractController {
 		}
 		this.questionService.update(question);
 	}
+	
+	@RequestMapping(value = "/publish", method = RequestMethod.POST)
+	@ResponseBody
+	public final void publishAllQuestions(
+			@RequestParam final String sessionkey,
+			@RequestParam(required = false) final Boolean publish,
+			final HttpServletResponse response
+	) {
+		boolean p = true;
+		if (publish != null) {
+			p = publish;
+		}
+		this.questionService.publishAll(sessionkey, p);
+	}
 
 	@RequestMapping(value = "/{questionId}/publishstatistics", method = RequestMethod.POST)
 	@ResponseBody
@@ -128,19 +142,27 @@ public class LecturerQuestionController extends AbstractController {
 		this.questionService.update(question);
 	}
 
-	@RequestMapping(
-			value = { "/" },
-			method = RequestMethod.GET
-	)
+	@RequestMapping(value = "/", method = RequestMethod.GET)
 	@ResponseBody
 	public final List<Question> getSkillQuestions(
 			@RequestParam final String sessionkey,
+			@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
+			@RequestParam(value = "flashcardsonly", defaultValue = "false") final boolean flashcardsOnly,
+			@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
 			final HttpServletResponse response
 	) {
-		List<Question> questions = questionService.getSkillQuestions(sessionkey);
+		List<Question> questions;
+		if (lectureQuestionsOnly) {
+			questions = questionService.getLectureQuestions(sessionkey);
+		} else if (flashcardsOnly) {
+			questions = questionService.getFlashcards(sessionkey);
+		} else if (preparationQuestionsOnly) {
+			questions = questionService.getPreparationQuestions(sessionkey);
+		} else {
+			questions = questionService.getSkillQuestions(sessionkey);
+		}
 		if (questions == null || questions.isEmpty()) {
 			response.setStatus(HttpStatus.NO_CONTENT.value());
-
 			return null;
 		}
 		return questions;
@@ -148,16 +170,43 @@ public class LecturerQuestionController extends AbstractController {
 
 	@RequestMapping(value = { "/" }, method = RequestMethod.DELETE)
 	@ResponseBody
-	public final void deleteSkillQuestions(@RequestParam final String sessionkey, final HttpServletResponse response) {
-		this.questionService.deleteAllQuestions(sessionkey);
+	public final void deleteSkillQuestions(
+			@RequestParam final String sessionkey,
+			@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
+			@RequestParam(value = "flashcardsonly", defaultValue = "false") final boolean flashcardsOnly,
+			@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
+			final HttpServletResponse response
+	) {
+		if (lectureQuestionsOnly) {
+			this.questionService.deleteLectureQuestions(sessionkey);
+		} else if (flashcardsOnly) {
+			this.questionService.deleteFlashcards(sessionkey);
+		} else if (preparationQuestionsOnly) {
+			this.questionService.deletePreparationQuestions(sessionkey);
+		} else {
+			this.questionService.deleteAllQuestions(sessionkey);
+		}
 	}
 
 	@RequestMapping(value = "/count", method = RequestMethod.GET)
 	@ResponseBody
-	public final int getSkillQuestionCount(@RequestParam final String sessionkey, final HttpServletResponse response) {
+	public final int getSkillQuestionCount(
+			@RequestParam final String sessionkey,
+			@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
+			@RequestParam(value = "flashcardsonly", defaultValue = "false") final boolean flashcardsOnly,
+			@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
+			final HttpServletResponse response) {
 		response.addHeader("X-Deprecated-API", "1");
 
-		return questionService.getSkillQuestionCount(sessionkey);
+		if (lectureQuestionsOnly) {
+			return questionService.getLectureQuestionCount(sessionkey);
+		} else if (flashcardsOnly) {
+			return questionService.getFlashcardCount(sessionkey);
+		} else if (preparationQuestionsOnly) {
+			return questionService.getPreparationQuestionCount(sessionkey);
+		} else {
+			return questionService.getSkillQuestionCount(sessionkey);
+		}
 	}
 
 	@RequestMapping(value = "/{questionId}", method = RequestMethod.DELETE)
@@ -173,9 +222,18 @@ public class LecturerQuestionController extends AbstractController {
 	@ResponseBody
 	public final List<String> getUnAnsweredSkillQuestionIds(
 			@RequestParam final String sessionkey,
+			@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
+			@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
 			final HttpServletResponse response
 	) {
-		List<String> answers = questionService.getUnAnsweredQuestionIds(sessionkey);
+		List<String> answers;
+		if (lectureQuestionsOnly) {
+			answers = questionService.getUnAnsweredLectureQuestionIds(sessionkey);
+		} else if (preparationQuestionsOnly) {
+			answers = questionService.getUnAnsweredPreparationQuestionIds(sessionkey);
+		} else {
+			answers = questionService.getUnAnsweredQuestionIds(sessionkey);
+		}
 		if (answers == null || answers.isEmpty()) {
 			throw new NoContentException();
 		}
@@ -297,6 +355,15 @@ public class LecturerQuestionController extends AbstractController {
 		questionService.deleteAnswers(questionId);
 	}
 
+	@RequestMapping(value = "/answers", method = RequestMethod.DELETE)
+	@ResponseBody
+	public final void deleteAllQuestionsAnswers(
+			@RequestParam final String sessionkey,
+			final HttpServletResponse response
+	) {
+		questionService.deleteAllQuestionsAnswers(sessionkey);
+	}
+
 	/**
 	 *
 	 * @param sessionKey
@@ -345,11 +412,19 @@ public class LecturerQuestionController extends AbstractController {
 	@ResponseBody
 	public final int getTotalAnswerCount(
 			@RequestParam final String sessionkey,
+			@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
+			@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
 			final HttpServletResponse response
 	) {
 		response.addHeader("X-Deprecated-API", "1");
 
-		return questionService.getTotalAnswerCount(sessionkey);
+		if (lectureQuestionsOnly) {
+			return questionService.countLectureQuestionAnswers(sessionkey);
+		} else if (preparationQuestionsOnly) {
+			return questionService.countPreparationQuestionAnswers(sessionkey);
+		} else {
+			return questionService.getTotalAnswerCount(sessionkey);
+		}
 	}
 
 }
diff --git a/src/main/java/de/thm/arsnova/controller/LegacyController.java b/src/main/java/de/thm/arsnova/controller/LegacyController.java
index 8f2c5b7a0774467e35830a32f96d2f870e9faeee..83c049daddd8b5df8e8e246a291148a0c066fcab 100644
--- a/src/main/java/de/thm/arsnova/controller/LegacyController.java
+++ b/src/main/java/de/thm/arsnova/controller/LegacyController.java
@@ -22,16 +22,23 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 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.ResponseBody;
+
+import de.thm.arsnova.services.IQuestionService;
 
 @Controller
 public class LegacyController extends AbstractController {
 
 	public static final Logger LOGGER = LoggerFactory.getLogger(LegacyController.class);
 
+	@Autowired
+	private IQuestionService questionService;
+
 	/* specific routes */
 
 	@RequestMapping(value = "/session/mysessions", method = RequestMethod.GET)
@@ -115,6 +122,15 @@ public class LegacyController extends AbstractController {
 		return String.format("forward:/audiencequestion/?sessionkey=%s", sessionKey);
 	}
 
+	@RequestMapping(value = "/session/{sessionKey}/interposed", method = RequestMethod.DELETE)
+	@ResponseBody
+	public final void deleteAllInterposedQuestions(
+			@PathVariable final String sessionKey,
+			final HttpServletResponse response
+	) {
+		questionService.deleteAllInterposedQuestions(sessionKey);
+	}
+
 	@RequestMapping(value = "/session/{sessionKey}/interposedcount", method = RequestMethod.GET)
 	public final String redirectQuestionByAudienceCount(
 			@PathVariable final String sessionKey,
diff --git a/src/main/java/de/thm/arsnova/controller/LoginController.java b/src/main/java/de/thm/arsnova/controller/LoginController.java
index 37a47167a39b5877aa33d110afc69f13c65a7b19..a1fee3a1fda43f452836a96f9e3bffc093c3cfda 100644
--- a/src/main/java/de/thm/arsnova/controller/LoginController.java
+++ b/src/main/java/de/thm/arsnova/controller/LoginController.java
@@ -93,9 +93,9 @@ public class LoginController extends AbstractController {
 			@RequestParam(value = "role", required = false) UserSessionService.Role role,
 			final HttpServletRequest request,
 			final HttpServletResponse response
-	) throws IOException, ServletException {
+			) throws IOException, ServletException {
 		userSessionService.setRole(role);
-		
+
 		String referer = request.getHeader("referer");
 		if (null != forcedReferer && null != referer && !UrlUtils.isAbsoluteUrl(referer)) {
 			/* Use a url from a request parameter as referer as long as the url is not absolute (to prevent
@@ -107,14 +107,14 @@ public class LoginController extends AbstractController {
 		}
 
 		request.getSession().setAttribute("ars-login-success-url",
-			null == successUrl ? referer + "#auth/checkLogin" : successUrl
-		);
+				null == successUrl ? referer + "#auth/checkLogin" : successUrl
+				);
 		request.getSession().setAttribute("ars-login-failure-url",
-			null == failureUrl ? referer : failureUrl
-		);
+				null == failureUrl ? referer : failureUrl
+				);
 
 		View result = null;
-		
+
 		if ("cas".equals(type)) {
 			casEntryPoint.commence(request, response, null);
 		} else if ("twitter".equals(type)) {
@@ -133,12 +133,14 @@ public class LoginController extends AbstractController {
 			if (guestName != null && guestName.startsWith("Guest") && guestName.length() == MAX_USERNAME_LENGTH) {
 				username = guestName;
 			} else {
-				username = "Guest" + Sha512DigestUtils.shaHex(request.getSession().getId()).substring(0, MAX_GUESTHASH_LENGTH);
+				username = "Guest" + Sha512DigestUtils.shaHex(
+						request.getSession().getId()
+						).substring(0, MAX_GUESTHASH_LENGTH);
 			}
 			org.springframework.security.core.userdetails.User user =
 					new org.springframework.security.core.userdetails.User(
 							username, "", true, true, true, true, authorities
-					);
+							);
 			Authentication token = new UsernamePasswordAuthenticationToken(user, null, authorities);
 
 			SecurityContextHolder.getContext().setAuthentication(token);
@@ -146,14 +148,14 @@ public class LoginController extends AbstractController {
 					SecurityContextHolder.getContext());
 			result = new RedirectView(null == successUrl ? referer + "#auth/checkLogin" : successUrl);
 		}
-				
+
 		return result;
 	}
 
 	@RequestMapping(value = { "/auth/", "/whoami" }, method = RequestMethod.GET)
 	@ResponseBody
 	public final User whoami() {
-		userSessionService.setUser(userService.getCurrentUser());		
+		userSessionService.setUser(userService.getCurrentUser());
 		return userService.getCurrentUser();
 	}
 
diff --git a/src/main/java/de/thm/arsnova/controller/SessionController.java b/src/main/java/de/thm/arsnova/controller/SessionController.java
index 525bd65ddea5469aed9cca1da4301d66c3749d3a..27e5c8e1f38dabdbb88147978284ad532e10451b 100644
--- a/src/main/java/de/thm/arsnova/controller/SessionController.java
+++ b/src/main/java/de/thm/arsnova/controller/SessionController.java
@@ -61,8 +61,7 @@ public class SessionController extends AbstractController {
 	@RequestMapping(value = "/{sessionkey}", method = RequestMethod.GET)
 	@ResponseBody
 	public final Session joinSession(@PathVariable final String sessionkey) {
-		Session session = sessionService.joinSession(sessionkey);
-		return session;
+		return sessionService.joinSession(sessionkey);
 	}
 
 	@RequestMapping(value = "/{sessionkey}", method = RequestMethod.DELETE)
@@ -78,7 +77,7 @@ public class SessionController extends AbstractController {
 	public final LoggedIn registerAsOnlineUser(
 			@PathVariable final String sessionkey,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Deprecated-API", "1");
 
 		User user = userService.getCurrentUser();
@@ -95,7 +94,7 @@ public class SessionController extends AbstractController {
 	public final int countActiveUsers(
 			@PathVariable final String sessionkey,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Deprecated-API", "1");
 
 		return userService.getUsersInSessionCount(sessionkey);
@@ -132,7 +131,7 @@ public class SessionController extends AbstractController {
 	public final Session updateSession(
 			@PathVariable final String sessionkey,
 			@RequestBody final Session session
-	) {
+			) {
 		return sessionService.updateSession(sessionkey, session);
 	}
 
@@ -143,7 +142,7 @@ public class SessionController extends AbstractController {
 			@RequestParam(value = "visitedonly", defaultValue = "false") final boolean visitedOnly,
 			@RequestParam(value = "sortby", defaultValue = "name") final String sortby,
 			final HttpServletResponse response
-	) {
+			) {
 		User user = userService.getCurrentUser();
 		List<Session> sessions = null;
 
@@ -183,7 +182,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String sessionkey,
 			@RequestParam(required = false) final Boolean lock,
 			final HttpServletResponse response
-	) {
+			) {
 		if (lock != null) {
 			return this.sessionService.setActive(sessionkey, lock);
 		}
@@ -191,13 +190,31 @@ public class SessionController extends AbstractController {
 		return null;
 	}
 
+	@RequestMapping(value = "/{sessionkey}/learningprogress", method = RequestMethod.GET)
+	@ResponseBody
+	public final int learningProgress(
+			@PathVariable final String sessionkey,
+			final HttpServletResponse response
+			) {
+		return sessionService.getLearningProgress(sessionkey);
+	}
+
+	@RequestMapping(value = "/{sessionkey}/mylearningprogress", method = RequestMethod.GET)
+	@ResponseBody
+	public final int myLearningProgress(
+			@PathVariable final String sessionkey,
+			final HttpServletResponse response
+			) {
+		return sessionService.getMyLearningProgress(sessionkey);
+	}
+
 	/* internal redirections */
 
 	@RequestMapping(value = "/{sessionKey}/lecturerquestion")
 	public final String redirectLecturerQuestion(
 			@PathVariable final String sessionKey,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/lecturerquestion/?sessionkey=%s", sessionKey);
@@ -208,7 +225,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String sessionKey,
 			@PathVariable final String arg1,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/lecturerquestion/%s/?sessionkey=%s", arg1, sessionKey);
@@ -220,7 +237,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String arg1,
 			@PathVariable final String arg2,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/lecturerquestion/%s/%s/?sessionkey=%s", arg1, arg2, sessionKey);
@@ -233,7 +250,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String arg2,
 			@PathVariable final String arg3,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/lecturerquestion/%s/%s/%s/?sessionkey=%s", arg1, arg2, arg3, sessionKey);
@@ -243,7 +260,7 @@ public class SessionController extends AbstractController {
 	public final String redirectAudienceQuestion(
 			@PathVariable final String sessionKey,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/audiencequestion/?sessionkey=%s", sessionKey);
@@ -254,7 +271,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String sessionKey,
 			@PathVariable final String arg1,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/audiencequestion/%s/?sessionkey=%s", arg1, sessionKey);
@@ -266,7 +283,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String arg1,
 			@PathVariable final String arg2,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/audiencequestion/%s/%s/?sessionkey=%s", arg1, arg2, sessionKey);
@@ -279,7 +296,7 @@ public class SessionController extends AbstractController {
 			@PathVariable final String arg2,
 			@PathVariable final String arg3,
 			final HttpServletResponse response
-	) {
+			) {
 		response.addHeader("X-Forwarded", "1");
 
 		return String.format("forward:/audiencequestion/%s/%s/%s/?sessionkey=%s", arg1, arg2, arg3, sessionKey);
diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 9df14c78594113c4f3c146c08496101441a786ce..5262cbe9a227ace7d31624f88ecda45514353b55 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -62,7 +62,6 @@ import de.thm.arsnova.entities.VisitedSession;
 import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
-import de.thm.arsnova.services.IFeedbackService;
 import de.thm.arsnova.services.ISessionService;
 import de.thm.arsnova.services.IUserService;
 
@@ -71,9 +70,6 @@ public class CouchDBDao implements IDatabaseDao {
 	@Autowired
 	private IUserService userService;
 
-	@Autowired
-	private IFeedbackService feedbackService;
-
 	@Autowired
 	private ISessionService sessionService;
 
@@ -133,7 +129,7 @@ public class CouchDBDao implements IDatabaseDao {
 			Session session = (Session) JSONObject.toBean(
 					d.getJSONObject().getJSONObject("value"),
 					Session.class
-			);
+					);
 			session.setCreator(d.getJSONObject().getJSONArray("key").getString(0));
 			session.setName(d.getJSONObject().getJSONArray("key").getString(1));
 			session.set_id(d.getId());
@@ -143,75 +139,23 @@ public class CouchDBDao implements IDatabaseDao {
 	}
 
 	@Override
-	public final List<Question> getSkillQuestions(final String sessionKeyword) {
-		Session session = this.getSessionFromKeyword(sessionKeyword);
-		if (session == null) {
-			throw new NotFoundException();
-		}
-
-		User user = this.userService.getCurrentUser();
-		NovaView view = null;
-
-		try {
-			String viewName;
-			if (session.getCreator().equals(user.getUsername())) {
-				viewName = "skill_question/by_session_sorted_by_subject_and_text";
+	public final List<Question> getSkillQuestions(User user, Session session) {
+		String viewName;
+		if (session.getCreator().equals(user.getUsername())) {
+			viewName = "skill_question/by_session_sorted_by_subject_and_text";
+		} else {
+			if (user.getType().equals(User.THM)) {
+				viewName = "skill_question/by_session_for_thm_full";
 			} else {
-				if (user.getType().equals(User.THM)) {
-					viewName = "skill_question/by_session_for_thm_full";
-				} else {
-					viewName = "skill_question/by_session_for_all_full";
-				}
+				viewName = "skill_question/by_session_for_all_full";
 			}
-			view = new NovaView(viewName);
-			view.setStartKeyArray(session.get_id());
-			view.setEndKeyArray(session.get_id(), "{}");
-
-			ViewResults questions = this.getDatabase().view(view);
-			if (questions == null || questions.isEmpty()) {
-				return null;
-			}
-			List<Question> result = new ArrayList<Question>();
-
-			MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry();
-			Morpher dynaMorpher = new BeanMorpher(PossibleAnswer.class, morpherRegistry);
-			morpherRegistry.registerMorpher(dynaMorpher);
-			for (Document document : questions.getResults()) {
-				Question question = (Question) JSONObject.toBean(
-						document.getJSONObject().getJSONObject("value"),
-						Question.class
-				);
-				Collection<PossibleAnswer> answers = JSONArray.toCollection(
-						document.getJSONObject().getJSONObject("value")
-							.getJSONArray("possibleAnswers"),
-						PossibleAnswer.class
-				);
-				question.setPossibleAnswers(new ArrayList<PossibleAnswer>(answers));
-				question.setSessionKeyword(this.getSessionKeyword(question.getSessionId()));
-				if (!"freetext".equals(question.getQuestionType()) && 0 == question.getPiRound()) {
-					/* needed for legacy questions whose piRound property has not been set */
-					question.setPiRound(1);
-				}
-				result.add(question);
-			}
-
-			return result;
-		} catch (IOException e) {
-			return null;
 		}
+		return getQuestions(new NovaView(viewName), session);
 	}
 
 	@Override
 	public final int getSkillQuestionCount(final Session session) {
-		NovaView view = new NovaView("skill_question/count_by_session");
-		view.setKey(session.get_id());
-		ViewResults results = this.getDatabase().view(view);
-
-		if (results.getJSONArray("rows").optJSONObject(0) == null) {
-			return 0;
-		}
-
-		return results.getJSONArray("rows").optJSONObject(0).optInt("value");
+		return getQuestionCount(new NovaView("skill_question/count_by_session"), session);
 	}
 
 	@Override
@@ -226,7 +170,7 @@ public class CouchDBDao implements IDatabaseDao {
 		return (Session) JSONObject.toBean(
 				results.getJSONArray("rows").optJSONObject(0).optJSONObject("value"),
 				Session.class
-		);
+				);
 	}
 
 	@Override
@@ -241,7 +185,7 @@ public class CouchDBDao implements IDatabaseDao {
 		return (Session) JSONObject.toBean(
 				results.getJSONArray("rows").optJSONObject(0).optJSONObject("value"),
 				Session.class
-		);
+				);
 	}
 
 	@Override
@@ -295,14 +239,14 @@ public class CouchDBDao implements IDatabaseDao {
 				com.fourspaces.couchdb.Session session = new com.fourspaces.couchdb.Session(
 						databaseHost,
 						databasePort
-				);
+						);
 				database = session.getDatabase(databaseName);
 			} catch (Exception e) {
 				LOGGER.error(
 						"Cannot connect to CouchDB database '" + databaseName
 						+ "' on host '" + databaseHost
 						+ "' using port " + databasePort
-				);
+						);
 			}
 		}
 
@@ -311,9 +255,23 @@ public class CouchDBDao implements IDatabaseDao {
 
 	@Override
 	public final Question saveQuestion(final Session session, final Question question) {
+		Document q = toQuestionDocument(session, question);
+		try {
+			database.saveDocument(q);
+			question.set_id(q.getId());
+			question.set_rev(q.getRev());
+			return question;
+		} catch (IOException e) {
+			LOGGER.error("Could not save question {}", question);
+		}
+		return null;
+	}
+
+	private Document toQuestionDocument(final Session session, final Question question) {
 		Document q = new Document();
 		q.put("type", "skill_question");
 		q.put("questionType", question.getQuestionType());
+		q.put("questionVariant", question.getQuestionVariant());
 		q.put("sessionId", session.get_id());
 		q.put("subject", question.getSubject());
 		q.put("text", question.getText());
@@ -326,15 +284,13 @@ public class CouchDBDao implements IDatabaseDao {
 		q.put("showStatistic", question.isShowStatistic());
 		q.put("showAnswer", question.isShowAnswer());
 		q.put("abstention", question.isAbstention());
-		try {
-			database.saveDocument(q);
-			question.set_id(q.getId());
-			question.set_rev(q.getRev());
-			return question;
-		} catch (IOException e) {
-			LOGGER.error("Could not save question {}", question);
-		}
-		return null;
+		q.put("image", question.getImage());
+		q.put("gridSize", question.getGridSize());
+		q.put("offsetX", question.getOffsetX());
+		q.put("offsetY", question.getOffsetY());
+		q.put("zoomLvl", question.getZoomLvl());
+
+		return q;
 	}
 
 	@Override
@@ -351,6 +307,11 @@ public class CouchDBDao implements IDatabaseDao {
 			q.put("showStatistic", question.isShowStatistic());
 			q.put("showAnswer", question.isShowAnswer());
 			q.put("abstention", question.isAbstention());
+			q.put("image", question.getImage());
+			q.put("gridSize", question.getGridSize());
+			q.put("offsetX", question.getOffsetX());
+			q.put("offsetY", question.getOffsetY());
+			q.put("zoomLvl", question.getZoomLvl());
 			this.database.saveDocument(q);
 			question.set_rev(q.getRev());
 
@@ -398,13 +359,14 @@ public class CouchDBDao implements IDatabaseDao {
 			Question q = (Question) JSONObject.toBean(
 					results.getJSONArray("rows").optJSONObject(0).optJSONObject("value"),
 					Question.class
-			);
-			JSONArray possibleAnswers = results.getJSONArray("rows").optJSONObject(0).optJSONObject("value")
+					);
+			JSONArray possibleAnswers = new JSONArray();
+			possibleAnswers = results.getJSONArray("rows").optJSONObject(0).optJSONObject("value")
 					.getJSONArray("possibleAnswers");
 			Collection<PossibleAnswer> answers = JSONArray.toCollection(
 					possibleAnswers,
 					PossibleAnswer.class
-			);
+					);
 			q.setPossibleAnswers(new ArrayList<PossibleAnswer>(answers));
 			q.setSessionKeyword(this.getSessionKeyword(q.getSessionId()));
 			return q;
@@ -482,18 +444,8 @@ public class CouchDBDao implements IDatabaseDao {
 		} else {
 			view = new NovaView("skill_question/by_session_only_id_for_all");
 		}
-
 		view.setKey(session.get_id());
-		ViewResults results = this.getDatabase().view(view);
-		if (results.getResults().size() == 0) {
-			return new ArrayList<String>();
-		}
-
-		List<String> ids = new ArrayList<String>();
-		for (Document d : results.getResults()) {
-			ids.add(d.getId());
-		}
-		return ids;
+		return collectQuestionIds(view);
 	}
 
 	@Override
@@ -505,14 +457,18 @@ public class CouchDBDao implements IDatabaseDao {
 			LOGGER.error("IOException: Could not delete question {}", question.get_id());
 		}
 	}
-	
+
 	@Override
 	public final void deleteAllQuestionsWithAnswers(Session session) {
 		NovaView view = new NovaView("skill_question/by_session");
+		deleteAllQuestionDocumentsWithAnswers(session, view);
+	}
+
+	private void deleteAllQuestionDocumentsWithAnswers(Session session, NovaView view) {
 		view.setStartKeyArray(session.get_id());
 		view.setEndKey(session.get_id(), "{}");
 		ViewResults results = this.getDatabase().view(view);
-		
+
 		for (Document d : results.getResults()) {
 			Question q = new Question();
 			q.set_id(d.getId());
@@ -544,21 +500,7 @@ public class CouchDBDao implements IDatabaseDao {
 	public final List<String> getUnAnsweredQuestionIds(final Session session, final User user) {
 		NovaView view = new NovaView("answer/by_user");
 		view.setKey(user.getUsername(), session.get_id());
-		ViewResults anseweredQuestions = this.getDatabase().view(view);
-
-		List<String> answered = new ArrayList<String>();
-		for (Document d : anseweredQuestions.getResults()) {
-			answered.add(d.getString("value"));
-		}
-
-		List<String> questions = this.getQuestionIds(session, user);
-		List<String> unanswered = new ArrayList<String>();
-		for (String questionId : questions) {
-			if (!answered.contains(questionId)) {
-				unanswered.add(questionId);
-			}
-		}
-		return unanswered;
+		return collectUnansweredQuestionIds(session, user, this.getQuestionIds(session, user), view);
 	}
 
 	@Override
@@ -583,7 +525,7 @@ public class CouchDBDao implements IDatabaseDao {
 		return (Answer) JSONObject.toBean(
 				results.getJSONArray("rows").optJSONObject(0).optJSONObject("value"),
 				Answer.class
-		);
+				);
 	}
 
 	@Override
@@ -608,7 +550,7 @@ public class CouchDBDao implements IDatabaseDao {
 			a.setQuestionId(d.getJSONObject().getJSONArray("key").getString(0));
 			a.setPiRound(piRound);
 			String answerText = d.getJSONObject().getJSONArray("key").getString(2);
-			a.setAnswerText(answerText == "null" ? null : answerText);
+			a.setAnswerText("null".equals(answerText) ? null : answerText);
 			answers.add(a);
 		}
 		return answers;
@@ -626,10 +568,11 @@ public class CouchDBDao implements IDatabaseDao {
 	}
 
 	@Override
-	public final int getAnswerCount(final String questionId) {
-		NovaView view = new NovaView("skill_question/count_answers_by_question");
-		view.setKey(questionId);
+	public final int getAnswerCount(final Question question, final int piRound) {
+		NovaView view = new NovaView("skill_question/count_total_answers_by_question_and_piround");
 		view.setGroup(true);
+		view.setStartKey(question.get_id(), String.valueOf(piRound));
+		view.setEndKey(question.get_id(), String.valueOf(piRound), "{}");
 		ViewResults results = this.getDatabase().view(view);
 		if (results.getResults().size() == 0) {
 			return 0;
@@ -653,19 +596,6 @@ public class CouchDBDao implements IDatabaseDao {
 		return 0;
 	}
 
-	@Override
-	public final int countActiveUsers(Session session, long since) {
-		if (session == null) throw new NotFoundException();
-		NovaView view = new NovaView("logged_in/count");
-		view.setStartKey(session.get_id(), String.valueOf(since));
-		view.setEndKey(session.get_id(), "{}");
-		ViewResults results = this.getDatabase().view(view);
-		if (isEmptyResults(results)) {
-			return 0;
-		}
-		return results.getJSONArray("rows").optJSONObject(0).getInt("value");
-	}
-
 	private boolean isEmptyResults(ViewResults results) {
 		return results == null || results.getResults().isEmpty() || results.getJSONArray("rows").size() == 0;
 	}
@@ -787,7 +717,7 @@ public class CouchDBDao implements IDatabaseDao {
 			InterposedQuestion question = (InterposedQuestion) JSONObject.toBean(
 					document.getJSONObject().getJSONObject("value"),
 					InterposedQuestion.class
-			);
+					);
 			question.setSessionId(sessionKey);
 			question.set_id(document.getId());
 			result.add(question);
@@ -916,8 +846,8 @@ public class CouchDBDao implements IDatabaseDao {
 			for (int i = 0; i < rows.size(); i++) {
 				JSONObject row = rows.getJSONObject(i);
 				if (
-					row.getString("key").equals(key)
-				) {
+						row.getString("key").equals(key)
+						) {
 					result += row.getInt("value");
 				}
 			}
@@ -965,9 +895,9 @@ public class CouchDBDao implements IDatabaseDao {
 			if (d.getJSONObject().optJSONArray("value") != null) {
 				@SuppressWarnings("unchecked")
 				Collection<Session> visitedSessions =  JSONArray.toCollection(
-					d.getJSONObject().getJSONArray("value"),
-					Session.class
-				);
+						d.getJSONObject().getJSONArray("value"),
+						Session.class
+						);
 				allSessions.addAll(visitedSessions);
 			}
 		}
@@ -990,6 +920,8 @@ public class CouchDBDao implements IDatabaseDao {
 			a.put("sessionId", answer.getSessionId());
 			a.put("questionId", answer.getQuestionId());
 			a.put("answerSubject", answer.getAnswerSubject());
+			a.put("questionVariant", answer.getQuestionVariant());
+			a.put("questionValue", answer.getQuestionValue());
 			a.put("answerText", answer.getAnswerText());
 			a.put("timestamp", answer.getTimestamp());
 			a.put("user", user.getUsername());
@@ -1013,6 +945,7 @@ public class CouchDBDao implements IDatabaseDao {
 			a.put("answerText", answer.getAnswerText());
 			a.put("timestamp", answer.getTimestamp());
 			a.put("abstention", answer.isAbstention());
+			a.put("questionValue", answer.getQuestionValue());
 			this.database.saveDocument(a);
 			answer.set_rev(a.getRev());
 			return answer;
@@ -1052,7 +985,7 @@ public class CouchDBDao implements IDatabaseDao {
 			Session session = (Session) JSONObject.toBean(
 					d.getJSONObject().getJSONObject("value"),
 					Session.class
-			);
+					);
 			result.add(session);
 		}
 		return result;
@@ -1100,12 +1033,12 @@ public class CouchDBDao implements IDatabaseDao {
 			sb.append("]");
 			try {
 				this.setKeys(URLEncoder.encode(sb.toString(), "UTF-8"));
-			}
-			catch (UnsupportedEncodingException e) {
+			} catch (UnsupportedEncodingException e) {
 				LOGGER.error("Error while encoding course ID keys", e);
 			}
 		}
 
+		@Override
 		public String getQueryString() {
 			StringBuilder query = new StringBuilder();
 			if (super.getQueryString() != null) {
@@ -1119,7 +1052,9 @@ public class CouchDBDao implements IDatabaseDao {
 				query.append("keys=" + this.keys);
 			}
 
-			if (query.toString().isEmpty()) return null;
+			if (query.toString().isEmpty()) {
+				return null;
+			}
 			return query.toString();
 		}
 	}
@@ -1164,4 +1099,292 @@ public class CouchDBDao implements IDatabaseDao {
 			LOGGER.error("Could not delete session {}", session);
 		}
 	}
+
+	@Override
+	public List<Question> getLectureQuestions(User user, Session session) {
+		String viewName;
+		if (session.isCreator(user)) {
+			viewName = "skill_question/lecture_question_by_session";
+		} else {
+			if (user.getType().equals(User.THM)) {
+				viewName = "skill_question/lecture_question_by_session_for_thm";
+			} else {
+				viewName = "skill_question/lecture_question_by_session_for_all";
+			}
+		}
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	@Override
+	public List<Question> getFlashcards(User user, Session session) {
+		String viewName;
+		if (session.isCreator(user)) {
+			viewName = "skill_question/flashcard_by_session";
+		} else {
+			if (user.getType().equals(User.THM)) {
+				viewName = "skill_question/flashcard_by_session_for_thm";
+			} else {
+				viewName = "skill_question/flashcard_by_session_for_all";
+			}
+		}
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	@Override
+	public List<Question> getPreparationQuestions(User user, Session session) {
+		String viewName;
+		if (session.isCreator(user)) {
+			viewName = "skill_question/preparation_question_by_session";
+		} else {
+			if (user.getType().equals(User.THM)) {
+				viewName = "skill_question/preparation_question_by_session_for_thm";
+			} else {
+				viewName = "skill_question/preparation_question_by_session_for_all";
+			}
+		}
+		return getQuestions(new NovaView(viewName), session);
+
+	}
+
+	private List<Question> getQuestions(NovaView view, Session session) {
+		view.setStartKeyArray(session.get_id());
+		view.setEndKeyArray(session.get_id(), "{}");
+		ViewResults questions = this.getDatabase().view(view);
+		if (questions == null || questions.isEmpty()) {
+			return null;
+		}
+		List<Question> result = new ArrayList<Question>();
+
+		MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry();
+		Morpher dynaMorpher = new BeanMorpher(PossibleAnswer.class, morpherRegistry);
+		morpherRegistry.registerMorpher(dynaMorpher);
+		for (Document document : questions.getResults()) {
+			Question question = (Question) JSONObject.toBean(
+					document.getJSONObject().getJSONObject("value"),
+					Question.class
+					);
+			@SuppressWarnings("unchecked")
+			Collection<PossibleAnswer> answers = JSONArray.toCollection(
+					document.getJSONObject().getJSONObject("value").getJSONArray("possibleAnswers"),
+					PossibleAnswer.class
+					);
+			question.setPossibleAnswers(new ArrayList<PossibleAnswer>(answers));
+			question.setSessionKeyword(session.getKeyword());
+			if (!"freetext".equals(question.getQuestionType()) && 0 == question.getPiRound()) {
+				/* needed for legacy questions whose piRound property has not been set */
+				question.setPiRound(1);
+			}
+			result.add(question);
+		}
+		return result;
+	}
+
+	@Override
+	public int getLectureQuestionCount(Session session) {
+		return getQuestionCount(new NovaView("skill_question/lecture_question_count_by_session"), session);
+	}
+
+	@Override
+	public int getFlashcardCount(Session session) {
+		return getQuestionCount(new NovaView("skill_question/flashcard_count_by_session"), session);
+	}
+
+	@Override
+	public int getPreparationQuestionCount(Session session) {
+		return getQuestionCount(new NovaView("skill_question/preparation_question_count_by_session"), session);
+	}
+
+	private int getQuestionCount(NovaView view, Session session) {
+		view.setKey(session.get_id());
+		ViewResults results = this.getDatabase().view(view);
+		if (results.getJSONArray("rows").optJSONObject(0) == null) {
+			return 0;
+		}
+		return results.getJSONArray("rows").optJSONObject(0).optInt("value");
+	}
+
+	@Override
+	public int countLectureQuestionAnswers(Session session) {
+		return countQuestionVariantAnswers(session, "lecture");
+	}
+
+	@Override
+	public int countPreparationQuestionAnswers(Session session) {
+		return countQuestionVariantAnswers(session, "preparation");
+	}
+
+	private int countQuestionVariantAnswers(Session session, String variant) {
+		NovaView view = new NovaView("skill_question/count_answers_by_session_and_question_variant");
+		view.setKey(session.get_id(), variant);
+		ViewResults results = this.getDatabase().view(view);
+		if (results.getResults().size() == 0) {
+			return 0;
+		}
+		return results.getJSONArray("rows").optJSONObject(0).optInt("value");
+	}
+
+	@Override
+	public void deleteAllLectureQuestionsWithAnswers(Session session) {
+		NovaView view = new NovaView("skill_question/lecture_question_by_session");
+		deleteAllQuestionDocumentsWithAnswers(session, view);
+	}
+
+	@Override
+	public void deleteAllFlashcardsWithAnswers(Session session) {
+		NovaView view = new NovaView("skill_question/flashcard_by_session");
+		deleteAllQuestionDocumentsWithAnswers(session, view);
+	}
+
+	@Override
+	public void deleteAllPreparationQuestionsWithAnswers(Session session) {
+		NovaView view = new NovaView("skill_question/preparation_question_by_session");
+		deleteAllQuestionDocumentsWithAnswers(session, view);
+	}
+
+	@Override
+	public List<String> getUnAnsweredLectureQuestionIds(Session session, User user) {
+		NovaView view = new NovaView("answer/variant_by_user");
+		view.setKey(user.getUsername(), session.get_id(), "lecture");
+		return collectUnansweredQuestionIds(session, user, this.getLectureQuestionIds(session, user), view);
+	}
+
+	private List<String> getLectureQuestionIds(Session session, User user) {
+		NovaView view;
+		if (user.getType().equals("thm")) {
+			view = new NovaView("skill_question/lecture_question_by_session_for_thm");
+		} else {
+			view = new NovaView("skill_question/lecture_question_by_session_for_all");
+		}
+		view.setStartKeyArray(session.get_id());
+		view.setEndKeyArray(session.get_id(), "{}");
+		return collectQuestionIds(view);
+	}
+
+	@Override
+	public List<String> getUnAnsweredPreparationQuestionIds(Session session, User user) {
+		NovaView view = new NovaView("answer/variant_by_user");
+		view.setKey(user.getUsername(), session.get_id(), "preparation");
+		return collectUnansweredQuestionIds(session, user, this.getPreparationQuestionIds(session, user), view);
+	}
+
+	private List<String> getPreparationQuestionIds(Session session, User user) {
+		NovaView view;
+		if (user.getType().equals("thm")) {
+			view = new NovaView("skill_question/preparation_question_by_session_for_thm");
+		} else {
+			view = new NovaView("skill_question/preparation_question_by_session_for_all");
+		}
+		view.setStartKeyArray(session.get_id());
+		view.setEndKeyArray(session.get_id(), "{}");
+		return collectQuestionIds(view);
+	}
+
+	private List<String> collectUnansweredQuestionIds(Session session, User user, List<String> questions, NovaView view) {
+		ViewResults answeredQuestions = this.getDatabase().view(view);
+
+		List<String> answered = new ArrayList<String>();
+		for (Document d : answeredQuestions.getResults()) {
+			answered.add(d.getString("value"));
+		}
+
+		List<String> unanswered = new ArrayList<String>();
+		for (String questionId : questions) {
+			if (!answered.contains(questionId)) {
+				unanswered.add(questionId);
+			}
+		}
+		return unanswered;
+	}
+
+	private List<String> collectQuestionIds(NovaView view) {
+		ViewResults results = this.getDatabase().view(view);
+		if (results.getResults().size() == 0) {
+			return new ArrayList<String>();
+		}
+		List<String> ids = new ArrayList<String>();
+		for (Document d : results.getResults()) {
+			ids.add(d.getId());
+		}
+		return ids;
+	}
+
+	@Override
+	public void deleteAllInterposedQuestions(Session session) {
+		NovaView view = new NovaView("interposed_question/by_session");
+		view.setKey(session.get_id());
+		ViewResults questions = this.getDatabase().view(view);
+		if (questions == null || questions.isEmpty()) {
+			return;
+		}
+		for (Document document : questions.getResults()) {
+			try {
+				this.deleteDocument(document.getId());
+			} catch (IOException e) {
+				LOGGER.error("Could not delete all interposed questions {}", session);
+			}
+		}
+	}
+
+	@Override
+	public void publishAllQuestions(Session session, boolean publish) {
+		List<Question> questions = this.getQuestions(new NovaView("skill_question/by_session"), session);
+		for (Question q : questions) {
+			q.setActive(publish);
+		}
+		List<Document> documents = new ArrayList<Document>();
+		for (Question q : questions) {
+			Document d = toQuestionDocument(session, q);
+			d.setId(q.get_id());
+			d.setRev(q.get_rev());
+			documents.add(d);
+		}
+		try {
+			this.database.bulkSaveDocuments(documents.toArray(new Document[documents.size()]));
+		} catch (IOException e) {
+			LOGGER.error("Could not bulk publish all questions: {}", e.getMessage());
+		}
+	}
+
+	@Override
+	public void deleteAllQuestionsAnswers(Session session) {
+		List<Question> questions = this.getQuestions(new NovaView("skill_question/by_session"), session);
+		for (Question q : questions) {
+			this.deleteAnswers(q);
+		}
+	}
+
+	@Override
+	public int getLearningProgress(Session session) {
+		NovaView courseView = new NovaView("learning_progress/course_value");
+		NovaView maximumView = new NovaView("learning_progress/maximum_value");
+		courseView.setKey(session.get_id());
+		maximumView.setKey(session.get_id());
+
+		return getProgressPercentage(courseView, maximumView);
+	}
+
+	@Override
+	public int getMyLearningProgress(Session session, User user) {
+		NovaView userView = new NovaView("learning_progress/user_value");
+		NovaView maximumView = new NovaView("learning_progress/maximum_value");
+		userView.setKey(session.get_id(), user.getUsername());
+		maximumView.setKey(session.get_id());
+
+		return getProgressPercentage(userView, maximumView);
+	}
+
+	private int getProgressPercentage(NovaView progressView, NovaView maximumView) {
+		List<Document> progressValue = this.getDatabase().view(progressView).getResults();
+		List<Document> maximumValue = this.getDatabase().view(maximumView).getResults();
+		if (maximumValue.isEmpty()) {
+			return 0;
+		}
+		int maximum = maximumValue.get(0).getInt("value");
+		int progress = 0;
+		if (!progressValue.isEmpty()) {
+			progress = progressValue.get(0).getInt("value");
+		}
+		int percentage = (int)((progress * 100.0f) / maximum);
+		return percentage < 0 ? 0 : percentage;
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 2827c41b08336e1e33e8655875d9939d09b0d07c..b4c9c3003b345bacdefed2fe06ed5113bb44d0a1 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -48,7 +48,7 @@ public interface IDatabaseDao {
 
 	Question getQuestion(String id);
 
-	List<Question> getSkillQuestions(String session);
+	List<Question> getSkillQuestions(User user, Session session);
 
 	int getSkillQuestionCount(Session session);
 
@@ -68,14 +68,12 @@ public interface IDatabaseDao {
 
 	List<Answer> getAnswers(String questionId, int piRound);
 
-	int getAnswerCount(String questionId);
+	int getAnswerCount(Question question, int piRound);
 
 	List<Answer> getFreetextAnswers(String questionId);
 
 	int countActiveUsers(long since);
 
-	int countActiveUsers(Session session, long since);
-
 	List<Answer> getMyAnswers(String sessionKey);
 
 	int getTotalAnswerCount(String sessionKey);
@@ -131,4 +129,40 @@ public interface IDatabaseDao {
 	Session updateSession(Session session);
 
 	void deleteSession(Session session);
+
+	List<Question> getLectureQuestions(User user, Session session);
+
+	List<Question> getFlashcards(User user, Session session);
+
+	List<Question> getPreparationQuestions(User user, Session session);
+
+	int getLectureQuestionCount(Session session);
+
+	int getFlashcardCount(Session session);
+
+	int getPreparationQuestionCount(Session session);
+
+	int countLectureQuestionAnswers(Session session);
+
+	int countPreparationQuestionAnswers(Session session);
+
+	void deleteAllLectureQuestionsWithAnswers(Session session);
+
+	void deleteAllFlashcardsWithAnswers(Session session);
+
+	void deleteAllPreparationQuestionsWithAnswers(Session session);
+
+	List<String> getUnAnsweredLectureQuestionIds(Session session, User user);
+
+	List<String> getUnAnsweredPreparationQuestionIds(Session session, User user);
+
+	void deleteAllInterposedQuestions(Session session);
+
+	void publishAllQuestions(Session session, boolean publish);
+
+	void deleteAllQuestionsAnswers(Session session);
+
+	int getLearningProgress(Session session);
+
+	int getMyLearningProgress(Session session, User user);
 }
diff --git a/src/main/java/de/thm/arsnova/dao/NovaView.java b/src/main/java/de/thm/arsnova/dao/NovaView.java
index b9325b598ea5208be3412643ed0c31999ef2dc04..e525f06c32ff9c6dbb6d84a304f1e2f2c3e1d733 100644
--- a/src/main/java/de/thm/arsnova/dao/NovaView.java
+++ b/src/main/java/de/thm/arsnova/dao/NovaView.java
@@ -100,7 +100,7 @@ public class NovaView extends View {
 	private String quote(String string) {
 		return encode("\"" + string + "\"");
 	}
-	
+
 	private boolean isNumber(String string) {
 		return string.matches("^[0-9]+$");
 	}
diff --git a/src/main/java/de/thm/arsnova/entities/Answer.java b/src/main/java/de/thm/arsnova/entities/Answer.java
index 278ac92d50b61363859b23a4133e836993b331a9..d2361ed901256dfb1906f059d87ef92d6ffea750 100644
--- a/src/main/java/de/thm/arsnova/entities/Answer.java
+++ b/src/main/java/de/thm/arsnova/entities/Answer.java
@@ -9,12 +9,14 @@ public class Answer {
 	private String questionId;
 	private String answerText;
 	private String answerSubject;
+	private String questionVariant;
+	private int questionValue;
 	private int piRound;
 	private String user;
 	private long timestamp;
 	private int answerCount = 1;
-	private boolean abstention; // Currently available only for freetext and mc answers!
-	private int abstentionCount; // Currently available only for freetext and mc answers!
+	private boolean abstention;
+	private int abstentionCount;
 
 	public Answer() {
 		this.type = "skill_question_answer";
@@ -124,6 +126,22 @@ public class Answer {
 		this.abstentionCount = abstentionCount;
 	}
 
+	public String getQuestionVariant() {
+		return questionVariant;
+	}
+
+	public void setQuestionVariant(String questionVariant) {
+		this.questionVariant = questionVariant;
+	}
+
+	public int getQuestionValue() {
+		return questionValue;
+	}
+
+	public void setQuestionValue(int questionValue) {
+		this.questionValue = questionValue;
+	}
+
 	@Override
 	public final String toString() {
 		return "Answer type:'" + type + "'"
diff --git a/src/main/java/de/thm/arsnova/entities/LoggedIn.java b/src/main/java/de/thm/arsnova/entities/LoggedIn.java
index f44650438b17212e99a9183dcd038155ed714aee..1c4b91719ebaf41eb769b65fbb016a458d120555 100644
--- a/src/main/java/de/thm/arsnova/entities/LoggedIn.java
+++ b/src/main/java/de/thm/arsnova/entities/LoggedIn.java
@@ -122,7 +122,7 @@ public class LoggedIn {
 	}
 
 	public boolean hasConflicts() {
-		return ! (_conflicts == null || _conflicts.isEmpty());
+		return !(_conflicts == null || _conflicts.isEmpty());
 	}
 
 	@Override
@@ -132,4 +132,4 @@ public class LoggedIn {
 				+ ", timestamp=" + timestamp + ", visitedSessions="
 				+ visitedSessions + "]";
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java b/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java
index acfea0d3de09a13c2d1e469de0963c85714d110d..ebc36f98e9c2f88d9ac05668ae808a01170289fb 100644
--- a/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java
+++ b/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java
@@ -23,6 +23,7 @@ public class PossibleAnswer {
 	private String id;
 	private String text;
 	private boolean correct;
+	private int value;
 
 	public String getId() {
 		return this.id;
@@ -48,6 +49,14 @@ public class PossibleAnswer {
 		this.correct = correct;
 	}
 
+	public int getValue() {
+		return value;
+	}
+
+	public void setValue(int value) {
+		this.value = value;
+	}
+
 	@Override
 	public String toString() {
 		return "PossibleAnswer [id=" + id + ", text=" + text + ", correct=" + correct + "]";
diff --git a/src/main/java/de/thm/arsnova/entities/Question.java b/src/main/java/de/thm/arsnova/entities/Question.java
index de56243c017d4932b02ae8ae76fbe832d2b9045c..8b2d36e30c75c655eec2f7fdc76b95bffe0060fe 100644
--- a/src/main/java/de/thm/arsnova/entities/Question.java
+++ b/src/main/java/de/thm/arsnova/entities/Question.java
@@ -24,6 +24,7 @@ public class Question {
 
 	private String type;
 	private String questionType;
+	private String questionVariant;
 	private String subject;
 	private String text;
 	private boolean active;
@@ -43,6 +44,12 @@ public class Question {
 	private String _id;
 	private String _rev;
 
+	private String image;
+	private int gridSize;
+	private int offsetX;
+	private int offsetY;
+	private int zoomLvl;
+
 	public final String getType() {
 		return type;
 	}
@@ -59,6 +66,14 @@ public class Question {
 		this.questionType = questionType;
 	}
 
+	public final String getQuestionVariant() {
+		return questionVariant;
+	}
+
+	public final void setQuestionVariant(final String questionVariant) {
+		this.questionVariant = questionVariant;
+	}
+
 	public final String getSubject() {
 		return subject;
 	}
@@ -203,6 +218,46 @@ public class Question {
 		this._rev = _rev;
 	}
 
+	public String getImage() {
+		return image;
+	}
+
+	public void setImage(String image) {
+		this.image = image;
+	}
+
+	public int getGridSize() {
+		return gridSize;
+	}
+
+	public void setGridSize(int gridSize) {
+		this.gridSize = gridSize;
+	}
+
+	public int getOffsetX() {
+		return offsetX;
+	}
+
+	public void setOffsetX(int offsetX) {
+		this.offsetX = offsetX;
+	}
+
+	public int getOffsetY() {
+		return offsetY;
+	}
+
+	public void setOffsetY(int offsetY) {
+		this.offsetY = offsetY;
+	}
+
+	public int getZoomLvl() {
+		return zoomLvl;
+	}
+
+	public void setZoomLvl(int zoomLvl) {
+		this.zoomLvl = zoomLvl;
+	}
+
 	@Override
 	public final String toString() {
 		return "Question type '" + this.type + "': " + this.subject + ";\n" + this.text + this.possibleAnswers;
diff --git a/src/main/java/de/thm/arsnova/entities/Session.java b/src/main/java/de/thm/arsnova/entities/Session.java
index 0e17a2df5bb68032853d86cc71bb4e332ea579d3..1bbf8ad0fd45ae1242608636427690abb136fa3e 100644
--- a/src/main/java/de/thm/arsnova/entities/Session.java
+++ b/src/main/java/de/thm/arsnova/entities/Session.java
@@ -21,6 +21,8 @@ package de.thm.arsnova.entities;
 import java.io.Serializable;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 public class Session implements Serializable {
 
 	private static final long serialVersionUID = 1L;
@@ -110,7 +112,7 @@ public class Session implements Serializable {
 	public String get_rev() {
 		return _rev;
 	}
-	
+
 	public void set_conflicts(List<String> conflicts) {
 		_conflicts = conflicts;
 	}
@@ -139,10 +141,11 @@ public class Session implements Serializable {
 		this.courseId = courseId;
 	}
 
+	@JsonIgnore
 	public boolean isCourseSession() {
 		return (this.getCourseId() != null) && (!this.getCourseId().isEmpty());
 	}
-	
+
 	@Override
 	public String toString() {
 		return "User [keyword=" + keyword+ ", type=" + type + "]";
diff --git a/src/main/java/de/thm/arsnova/events/Publisher.java b/src/main/java/de/thm/arsnova/events/Publisher.java
index c8906725eeaa6280d3a103feefa6d15ce41a8f45..ac5b64fa218f3668198e2c1ac74c64bd22de8aa3 100644
--- a/src/main/java/de/thm/arsnova/events/Publisher.java
+++ b/src/main/java/de/thm/arsnova/events/Publisher.java
@@ -1,6 +1,5 @@
 package de.thm.arsnova.events;
 
-import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
@@ -13,7 +12,7 @@ public class Publisher implements ApplicationContextAware {
 	private ApplicationContext context;
 
 	@Override
-	public void setApplicationContext(ApplicationContext c) throws BeansException {
+	public void setApplicationContext(ApplicationContext c) {
 		this.context = c;
 	}
 
diff --git a/src/main/java/de/thm/arsnova/services/IQuestionService.java b/src/main/java/de/thm/arsnova/services/IQuestionService.java
index 4f04a0c73506ff5b42baaf5c87cf24e8321047a8..596d1ffd40bc9986f29f060f281bc22a597306d8 100644
--- a/src/main/java/de/thm/arsnova/services/IQuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/IQuestionService.java
@@ -37,8 +37,6 @@ public interface IQuestionService {
 
 	int getSkillQuestionCount(String sessionkey);
 
-	List<String> getQuestionIds(String sessionKey);
-
 	void deleteQuestion(String questionId);
 
 	void deleteAllQuestions(String sessionKeyword);
@@ -79,4 +77,36 @@ public interface IQuestionService {
 
 	void deleteInterposedQuestion(String questionId);
 
+	List<Question> getLectureQuestions(String sessionkey);
+
+	List<Question> getFlashcards(String sessionkey);
+
+	List<Question> getPreparationQuestions(String sessionkey);
+
+	int getLectureQuestionCount(String sessionkey);
+
+	int getFlashcardCount(String sessionkey);
+
+	int getPreparationQuestionCount(String sessionkey);
+
+	int countLectureQuestionAnswers(String sessionkey);
+
+	int countPreparationQuestionAnswers(String sessionkey);
+
+	void deleteLectureQuestions(String sessionkey);
+
+	void deleteFlashcards(String sessionkey);
+
+	void deletePreparationQuestions(String sessionkey);
+
+	List<String> getUnAnsweredLectureQuestionIds(String sessionkey);
+
+	List<String> getUnAnsweredPreparationQuestionIds(String sessionkey);
+
+	void deleteAllInterposedQuestions(String sessionKeyword);
+
+	void publishAll(String sessionkey, boolean publish);
+
+	void deleteAllQuestionsAnswers(String sessionkey);
+
 }
diff --git a/src/main/java/de/thm/arsnova/services/ISessionService.java b/src/main/java/de/thm/arsnova/services/ISessionService.java
index 7a54db07f45c19267d88556d2cc7fab0e87df456..611f3ce91aece07210e2472c8f709316a05f80ad 100644
--- a/src/main/java/de/thm/arsnova/services/ISessionService.java
+++ b/src/main/java/de/thm/arsnova/services/ISessionService.java
@@ -42,8 +42,6 @@ public interface ISessionService {
 
 	LoggedIn registerAsOnlineUser(User user, String sessionkey);
 
-	int countActiveUsers(String sessionkey);
-
 	int countSessions(List<Course> courses);
 
 	Session setActive(String sessionkey, Boolean lock);
@@ -53,4 +51,8 @@ public interface ISessionService {
 	Session updateSession(String sessionkey, Session session);
 
 	void deleteSession(String sessionkey, User user);
+
+	int getLearningProgress(String sessionkey);
+
+	int getMyLearningProgress(String sessionkey);
 }
diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java
index f6f51d6d732f4a049684c7013ff7b0ae7d46839a..f91da75e999fb8f84ae0589072373c8325b2a9a1 100644
--- a/src/main/java/de/thm/arsnova/services/QuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/QuestionService.java
@@ -24,9 +24,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+import de.thm.arsnova.ImageUtils;
 import de.thm.arsnova.annotation.Authenticated;
 import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.Answer;
@@ -35,8 +39,8 @@ import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
+import de.thm.arsnova.exceptions.BadRequestException;
 import de.thm.arsnova.exceptions.ForbiddenException;
-import de.thm.arsnova.exceptions.NoContentException;
 import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
 import de.thm.arsnova.socket.ARSnovaSocketIOServer;
@@ -52,6 +56,11 @@ public class QuestionService implements IQuestionService {
 
 	@Autowired
 	private ARSnovaSocketIOServer socketIoServer;
+	
+	@Value("${upload.filesize_b}")
+	private int uploadFileSizeByte;
+	
+	public static final Logger LOGGER = LoggerFactory.getLogger(QuestionService.class);
 
 	public void setDatabaseDao(IDatabaseDao databaseDao) {
 		this.databaseDao = databaseDao;
@@ -60,11 +69,7 @@ public class QuestionService implements IQuestionService {
 	@Override
 	@Authenticated
 	public List<Question> getSkillQuestions(String sessionkey) {
-		List<Question> result = databaseDao.getSkillQuestions(sessionkey);
-		if (result == null || result.size() == 0) {
-			throw new NoContentException();
-		}
-		return result;
+		return databaseDao.getSkillQuestions(userService.getCurrentUser(), getSession(sessionkey));
 	}
 
 	@Override
@@ -91,6 +96,25 @@ public class QuestionService implements IQuestionService {
 		} else if (question.getPiRound() < 1 || question.getPiRound() > 2) {
 			question.setPiRound(1);
 		}
+		
+		// convert imageurl to base64 if neccessary
+		if ("grid".equals(question.getQuestionType())) {
+			org.slf4j.Logger logger = LoggerFactory.getLogger(QuestionService.class);
+			if (question.getImage().startsWith("http")) {
+				String base64ImageString = ImageUtils.encodeImageToString(question.getImage());
+				if (base64ImageString == null) {
+					throw new BadRequestException();
+				}
+				question.setImage(base64ImageString);
+			}
+			
+			// base64 adds offset to filesize, formular taken from: http://en.wikipedia.org/wiki/Base64#MIME
+			int fileSize =  (int)((question.getImage().length()-814)/1.37);
+			if ( fileSize > this.uploadFileSizeByte ) {
+				LOGGER.error("Could not save file. File is too large with "+ fileSize + " Byte.");
+				throw new BadRequestException();
+			}
+		}
 
 		Question result = this.databaseDao.saveQuestion(session, question);
 		socketIoServer.reportLecturerQuestionAvailable(result.getSessionKeyword(), result.get_id());
@@ -117,6 +141,9 @@ public class QuestionService implements IQuestionService {
 	@Authenticated
 	public Question getQuestion(String id) {
 		Question result = databaseDao.getQuestion(id);
+		if (result == null) {
+			return null;
+		}
 		if (!"freetext".equals(result.getQuestionType()) && 0 == result.getPiRound()) {
 			/* needed for legacy questions whose piRound property has not been set */
 			result.setPiRound(1);
@@ -125,20 +152,6 @@ public class QuestionService implements IQuestionService {
 		return result;
 	}
 
-	@Override
-	@Authenticated
-	public List<String> getQuestionIds(String sessionKey) {
-		User user = userService.getCurrentUser();
-		if (user == null) {
-			throw new UnauthorizedException();
-		}
-		Session session = databaseDao.getSessionFromKeyword(sessionKey);
-		if (session == null) {
-			throw new NotFoundException();
-		}
-		return databaseDao.getQuestionIds(session, user);
-	}
-
 	@Override
 	@Authenticated
 	public void deleteQuestion(String questionId) {
@@ -158,12 +171,17 @@ public class QuestionService implements IQuestionService {
 	@Override
 	@Authenticated
 	public void deleteAllQuestions(String sessionKeyword) {
+		Session session = getSessionWithAuthCheck(sessionKeyword);
+		databaseDao.deleteAllQuestionsWithAnswers(session);
+	}
+
+	private Session getSessionWithAuthCheck(String sessionKeyword) {
 		User user = userService.getCurrentUser();
 		Session session = databaseDao.getSession(sessionKeyword);
 		if (user == null || session == null || ! session.isCreator(user)) {
 			throw new UnauthorizedException();
 		}
-		databaseDao.deleteAllQuestionsWithAnswers(session);
+		return session;
 	}
 
 	@Override
@@ -180,6 +198,17 @@ public class QuestionService implements IQuestionService {
 		}
 		databaseDao.deleteInterposedQuestion(question);
 	}
+	
+	@Override
+	@Authenticated
+	public void deleteAllInterposedQuestions(String sessionKeyword) {
+		User user = userService.getCurrentUser();
+		Session session = databaseDao.getSessionFromKeyword(sessionKeyword);
+		if (user == null || session == null || ! session.isCreator(user)) {
+			throw new UnauthorizedException();
+		}
+		databaseDao.deleteAllInterposedQuestions(session);
+	}
 
 	@Override
 	@Authenticated
@@ -200,15 +229,17 @@ public class QuestionService implements IQuestionService {
 	@Override
 	@Authenticated
 	public List<String> getUnAnsweredQuestionIds(String sessionKey) {
+		User user = getCurrentUser();
+		Session session = getSession(sessionKey);
+		return databaseDao.getUnAnsweredQuestionIds(session, user);
+	}
+
+	private User getCurrentUser() {
 		User user = userService.getCurrentUser();
 		if (user == null) {
 			throw new UnauthorizedException();
 		}
-		Session session = databaseDao.getSessionFromKeyword(sessionKey);
-		if (session == null) {
-			throw new NotFoundException();
-		}
-		return databaseDao.getUnAnsweredQuestionIds(session, user);
+		return user;
 	}
 
 	@Override
@@ -237,11 +268,12 @@ public class QuestionService implements IQuestionService {
 		return getAnswers(questionId, question.getPiRound());
 	}
 
-	/* TODO add implementation for piRound */
 	@Override
 	@Authenticated
 	public int getAnswerCount(String questionId) {
-		return databaseDao.getAnswerCount(questionId);
+		Question question = getQuestion(questionId);
+		
+		return databaseDao.getAnswerCount(question, question.getPiRound());
 	}
 
 	@Override
@@ -349,10 +381,7 @@ public class QuestionService implements IQuestionService {
 	@Override
 	@Authenticated
 	public Answer saveAnswer(Answer answer) {
-		User user = userService.getCurrentUser();
-		if (user == null) {
-			throw new UnauthorizedException();
-		}
+		User user = getCurrentUser();
 		Question question = this.getQuestion(answer.getQuestionId());
 		if (question == null) {
 			throw new NotFoundException();
@@ -401,4 +430,119 @@ public class QuestionService implements IQuestionService {
 
 		socketIoServer.reportAnswersToLecturerQuestionAvailable(question.getSessionKeyword(), question.get_id());
 	}
+
+	@Override
+	@Authenticated
+	public List<Question> getLectureQuestions(String sessionkey) {
+		return databaseDao.getLectureQuestions(userService.getCurrentUser(), getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public List<Question> getFlashcards(String sessionkey) {
+		return databaseDao.getFlashcards(userService.getCurrentUser(), getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public List<Question> getPreparationQuestions(String sessionkey) {
+		return databaseDao.getPreparationQuestions(userService.getCurrentUser(), getSession(sessionkey));
+	}
+	
+	private Session getSession(String sessionkey) {
+		Session session = this.databaseDao.getSessionFromKeyword(sessionkey);
+		if (session == null) {
+			throw new NotFoundException();
+		}
+		return session;
+	}
+
+	@Override
+	@Authenticated
+	public int getLectureQuestionCount(String sessionkey) {
+		return databaseDao.getLectureQuestionCount(getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public int getFlashcardCount(String sessionkey) {
+		return databaseDao.getFlashcardCount(getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public int getPreparationQuestionCount(String sessionkey) {
+		return databaseDao.getPreparationQuestionCount(getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public int countLectureQuestionAnswers(String sessionkey) {
+		return databaseDao.countLectureQuestionAnswers(getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public int countPreparationQuestionAnswers(String sessionkey) {
+		return databaseDao.countPreparationQuestionAnswers(getSession(sessionkey));
+	}
+
+	@Override
+	@Authenticated
+	public void deleteLectureQuestions(String sessionkey) {
+		Session session = getSessionWithAuthCheck(sessionkey);
+		databaseDao.deleteAllLectureQuestionsWithAnswers(session);
+	}
+
+	@Override
+	@Authenticated
+	public void deleteFlashcards(String sessionkey) {
+		Session session = getSessionWithAuthCheck(sessionkey);
+		databaseDao.deleteAllFlashcardsWithAnswers(session);
+	}
+
+	@Override
+	@Authenticated
+	public void deletePreparationQuestions(String sessionkey) {
+		Session session = getSessionWithAuthCheck(sessionkey);
+		databaseDao.deleteAllPreparationQuestionsWithAnswers(session);
+	}
+
+	@Override
+	@Authenticated
+	public List<String> getUnAnsweredLectureQuestionIds(String sessionkey) {
+		User user = getCurrentUser();
+		Session session = getSession(sessionkey);
+		return databaseDao.getUnAnsweredLectureQuestionIds(session, user);
+	}
+
+	@Override
+	@Authenticated
+	public List<String> getUnAnsweredPreparationQuestionIds(String sessionkey) {
+		User user = getCurrentUser();
+		Session session = getSession(sessionkey);
+		return databaseDao.getUnAnsweredPreparationQuestionIds(session, user);
+	}
+
+	@Override
+	@Authenticated
+	public void publishAll(String sessionkey, boolean publish) {
+		User user = getCurrentUser();
+		Session session = getSession(sessionkey);
+		if (!session.isCreator(user)) {
+			throw new UnauthorizedException();
+		}
+		databaseDao.publishAllQuestions(session, publish);
+	}
+
+	@Override
+	@Authenticated
+	public void deleteAllQuestionsAnswers(String sessionkey) {
+		User user = getCurrentUser();
+		Session session = getSession(sessionkey);
+		if (!session.isCreator(user)) {
+			throw new UnauthorizedException();
+		}
+		databaseDao.deleteAllQuestionsAnswers(session);
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java
index 869acf1d6040718e0fd9843028a1f7e4d5b5d709..0d63d14a80ef35230a96756db568389880948199 100644
--- a/src/main/java/de/thm/arsnova/services/SessionService.java
+++ b/src/main/java/de/thm/arsnova/services/SessionService.java
@@ -45,8 +45,6 @@ import de.thm.arsnova.socket.ARSnovaSocketIOServer;
 @Service
 public class SessionService implements ISessionService {
 
-	private static final int DURATION_IN_MILLIS = 3 * 60 * 1000;
-
 	@Autowired
 	private IDatabaseDao databaseDao;
 
@@ -130,8 +128,8 @@ public class SessionService implements ISessionService {
 		}
 
 		List<Session> courseSessions = databaseDao.getCourseSessions(
-			connectorClient.getCourses(user.getUsername()).getCourse()
-		);
+				connectorClient.getCourses(user.getUsername()).getCourse()
+				);
 
 		Map<String, Session> allAvailableSessions = new HashMap<String, Session>();
 
@@ -154,8 +152,8 @@ public class SessionService implements ISessionService {
 	public final Session saveSession(final Session session) {
 		if (connectorClient != null && session.getCourseId() != null) {
 			if (!connectorClient.getMembership(
-				userService.getCurrentUser().getUsername(), session.getCourseId()).isMember()
-			) {
+					userService.getCurrentUser().getUsername(), session.getCourseId()).isMember()
+					) {
 				throw new ForbiddenException();
 			}
 		}
@@ -196,13 +194,6 @@ public class SessionService implements ISessionService {
 		return databaseDao.registerAsOnlineUser(user, session);
 	}
 
-	@Override
-	public int countActiveUsers(String sessionkey) {
-		final long since = System.currentTimeMillis() - DURATION_IN_MILLIS;
-		Session session = databaseDao.getSessionFromKeyword(sessionkey);
-		return databaseDao.countActiveUsers(session, since);
-	}
-
 	public static class SessionNameComperator implements Comparator<Session>, Serializable {
 		private static final long serialVersionUID = 1L;
 
@@ -260,9 +251,24 @@ public class SessionService implements ISessionService {
 		if (!session.isCreator(user)) {
 			throw new ForbiddenException();
 		}
-		for (Question q : databaseDao.getSkillQuestions(sessionkey)) {
+		for (Question q : databaseDao.getSkillQuestions(user, session)) {
 			databaseDao.deleteQuestionWithAnswers(q);
 		}
 		databaseDao.deleteSession(session);
 	}
+
+	@Override
+	@Authenticated
+	public int getLearningProgress(String sessionkey) {
+		Session session = databaseDao.getSession(sessionkey);
+		return databaseDao.getLearningProgress(session);
+	}
+
+	@Override
+	@Authenticated
+	public int getMyLearningProgress(String sessionkey) {
+		Session session = databaseDao.getSession(sessionkey);
+		User user = userService.getCurrentUser();
+		return databaseDao.getMyLearningProgress(session, user);
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/services/UserService.java b/src/main/java/de/thm/arsnova/services/UserService.java
index 99521ec7530b50d628bd9b9555633967da72b3f4..73b5e79d4236370e7f8aaeee212ec028cd1020aa 100644
--- a/src/main/java/de/thm/arsnova/services/UserService.java
+++ b/src/main/java/de/thm/arsnova/services/UserService.java
@@ -86,17 +86,7 @@ public class UserService implements IUserService {
 		User user = null;
 
 		if (authentication instanceof OAuthAuthenticationToken) {
-			OAuthAuthenticationToken token = (OAuthAuthenticationToken) authentication;
-			if (token.getUserProfile() instanceof Google2Profile) {
-				Google2Profile profile = (Google2Profile) token.getUserProfile();
-				user = new User(profile);
-			} else if (token.getUserProfile() instanceof TwitterProfile) {
-				TwitterProfile profile = (TwitterProfile) token.getUserProfile();
-				user = new User(profile);
-			} else if (token.getUserProfile() instanceof FacebookProfile) {
-				FacebookProfile profile = (FacebookProfile) token.getUserProfile();
-				user = new User(profile);
-			}
+			user = getOAuthUser(authentication, user);
 		} else if (authentication instanceof CasAuthenticationToken) {
 			CasAuthenticationToken token = (CasAuthenticationToken) authentication;
 			user = new User(token.getAssertion().getPrincipal());
@@ -115,6 +105,21 @@ public class UserService implements IUserService {
 		return user;
 	}
 
+	private User getOAuthUser(Authentication authentication, User user) {
+		OAuthAuthenticationToken token = (OAuthAuthenticationToken) authentication;
+		if (token.getUserProfile() instanceof Google2Profile) {
+			Google2Profile profile = (Google2Profile) token.getUserProfile();
+			user = new User(profile);
+		} else if (token.getUserProfile() instanceof TwitterProfile) {
+			TwitterProfile profile = (TwitterProfile) token.getUserProfile();
+			user = new User(profile);
+		} else if (token.getUserProfile() instanceof FacebookProfile) {
+			FacebookProfile profile = (FacebookProfile) token.getUserProfile();
+			user = new User(profile);
+		}
+		return user;
+	}
+
 	@Override
 	public User getUser2SocketId(UUID socketId) {
 		return socketid2user.get(socketId);
diff --git a/src/main/java/de/thm/arsnova/services/UserSessionService.java b/src/main/java/de/thm/arsnova/services/UserSessionService.java
index df3110cd50221cba01a1dc79b7ddb1951271091a..170030f67b8e6076203f9b2f2f780be73f8f45e3 100644
--- a/src/main/java/de/thm/arsnova/services/UserSessionService.java
+++ b/src/main/java/de/thm/arsnova/services/UserSessionService.java
@@ -30,4 +30,4 @@ public interface UserSessionService {
 	boolean isAuthenticated();
 	
 	void sendEventViaWebSocket(ARSnovaSocketIOServer server, ARSnovaEvent event);
-}
\ No newline at end of file
+}
diff --git a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java
index f9d41fcd95e3c1052b9ffc906ecb69424a3cc0bf..7fbb17ae61e3f4ec1a63cd14f63cbfb53d866bed 100644
--- a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java
+++ b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java
@@ -30,7 +30,6 @@ import de.thm.arsnova.entities.User;
 import de.thm.arsnova.events.ARSnovaEvent;
 import de.thm.arsnova.exceptions.NoContentException;
 import de.thm.arsnova.services.IFeedbackService;
-import de.thm.arsnova.services.IQuestionService;
 import de.thm.arsnova.services.ISessionService;
 import de.thm.arsnova.services.IUserService;
 import de.thm.arsnova.socket.message.Feedback;
@@ -41,9 +40,6 @@ public class ARSnovaSocketIOServer {
 	@Autowired
 	private IFeedbackService feedbackService;
 
-	@Autowired
-	private IQuestionService questionService;
-
 	@Autowired
 	private IUserService userService;
 
@@ -65,14 +61,14 @@ public class ARSnovaSocketIOServer {
 	public ARSnovaSocketIOServer() {
 		config = new Configuration();
 	}
-	
+
 	@PreDestroy
 	public void closeAllSessions() {
 		LOGGER.info("Close all websockets due to @PreDestroy");
 		for (SocketIOClient c : server.getAllClients()) {
 			c.disconnect();
 		}
-		
+
 		int clientCount = 0;
 		for (SocketIOClient c : server.getAllClients()) {
 			c.send(new Packet(PacketType.DISCONNECT));
@@ -109,7 +105,7 @@ public class ARSnovaSocketIOServer {
 				 * a feedback
 				 */
 				User u = userService.getUser2SocketId(client.getSessionId());
-				if (u == null || ! userService.isUserInSession(u, data.getSessionkey())) {
+				if (u == null || !userService.isUserInSession(u, data.getSessionkey())) {
 					return;
 				}
 				feedbackService.saveFeedback(data.getSessionkey(), data.getValue(), u);
@@ -135,7 +131,11 @@ public class ARSnovaSocketIOServer {
 		server.addDisconnectListener(new DisconnectListener() {
 			@Override
 			public void onDisconnect(SocketIOClient client) {
-				if (userService == null || client.getSessionId() == null || userService.getUser2SocketId(client.getSessionId()) == null) {
+				if (
+						userService == null
+						|| client.getSessionId() == null
+						|| userService.getUser2SocketId(client.getSessionId()) == null
+						) {
 					LOGGER.warn("NullPointer in ARSnovaSocketIOServer DisconnectListener");
 					return;
 				}
@@ -306,15 +306,15 @@ public class ARSnovaSocketIOServer {
 		broadcastInSession(sessionKey, "lecQuestionAvail", lecturerQuestionId);
 	}
 
-	/** Sends event to a websocket connection identified by UUID 
-	 * 
+	/** Sends event to a websocket connection identified by UUID
+	 *
 	 * @param sessionId The UUID of the websocket ID
 	 * @param event The event to be send to client
+	 * TODO This method is unimplemented!
 	 */
 	public void sendToClient(UUID sessionId, ARSnovaEvent event) {
 		for (SocketIOClient c : server.getAllClients()) {
 			if (c.getSessionId().equals(sessionId)) {
-				System.out.println(sessionId);
 				break;
 			}
 		}
diff --git a/src/main/java/de/thm/arsnova/web/CorsFilter.java b/src/main/java/de/thm/arsnova/web/CorsFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc2e55f393103ae8fbbb6d17df6a05f4fa61af12
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/web/CorsFilter.java
@@ -0,0 +1,29 @@
+package de.thm.arsnova.web;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+@Component
+public class CorsFilter extends OncePerRequestFilter {
+
+	@Override
+	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+			throws ServletException, IOException {
+		response.addHeader("Access-Control-Allow-Credentials", "true");
+		response.addHeader("Access-Control-Allow-Methods", "GET");
+		response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
+
+		if (request.getHeader("origin") != null) {
+			response.addHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
+		}
+
+		filterChain.doFilter(request, response);
+	}
+}
diff --git a/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml b/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml
index 769d623d444bdef4015a34aa7ab01a1be4ffa082..d53da559f2020b02ebbaeab5fcf0cf56f4fca5ef 100644
--- a/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml
+++ b/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml
@@ -1,64 +1,71 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:aop="http://www.springframework.org/schema/aop"
-	xmlns:mvc="http://www.springframework.org/schema/mvc"
-	xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
+	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
 	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
 		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
 		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
 	<!-- ARSnova Servlet Context -->
-	
-	<context:component-scan base-package="de.thm.arsnova.controller" />
-	<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
-	
-	<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
-	    <property name="favorPathExtension" value="false" />
-	    <property name="favorParameter" value="true" />
-	    <property name="mediaTypes" >
-	        <value>
-	        	html=text/html
-	          	json=application/json
-	        </value>
-	    </property>
+
+	<context:component-scan base-package="de.thm.arsnova.controller,de.thm.arsnova.web" />
+	<mvc:annotation-driven
+		content-negotiation-manager="contentNegotiationManager" />
+
+	<bean id="contentNegotiationManager"
+		class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
+		<property name="favorPathExtension" value="false" />
+		<property name="favorParameter" value="true" />
+		<property name="mediaTypes">
+			<value>
+				html=text/html
+				json=application/json
+			</value>
+		</property>
 	</bean>
 
 	<mvc:annotation-driven />
 	<mvc:resources mapping="/**" location="/" />
-	
+
 	<!-- -->
-	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
-	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+	<bean
+		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
+	<bean
+		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
 		<property name="messageConverters">
 			<list>
-	            <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
-	                <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
-	            </bean>
-				<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
+				<bean
+					class="org.springframework.http.converter.StringHttpMessageConverter">
+					<property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
+				</bean>
+				<bean
+					class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
 			</list>
 		</property>
 	</bean>
 	<!-- -->
 
-	<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
-		<property name="viewResolvers">  
-			<list>  
-				<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
-					<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
-					<property name="prefix" value="/WEB-INF/jsp/"/>  
-					<property name="suffix" value=".jsp"/>  
-				</bean>  
-		    </list>  
-		</property>  
-		<property name="defaultViews">  
-			<list>  
-				<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">  
-					<property name="prefixJson" value="false"/>  
-				</bean>  
-			</list>  
-		</property>  
+	<bean
+		class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
+		<property name="viewResolvers">
+			<list>
+				<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
+					<property name="viewClass"
+						value="org.springframework.web.servlet.view.JstlView" />
+					<property name="prefix" value="/WEB-INF/jsp/" />
+					<property name="suffix" value=".jsp" />
+				</bean>
+			</list>
+		</property>
+		<property name="defaultViews">
+			<list>
+				<bean
+					class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
+					<property name="prefixJson" value="false" />
+				</bean>
+			</list>
+		</property>
 	</bean>
-	
+
 </beans>
diff --git a/src/main/webapp/WEB-INF/spring/spring-main.xml b/src/main/webapp/WEB-INF/spring/spring-main.xml
index 5d98f04108fe0cb98ad701f318b93f37ea8c8637..5c1803e9ff2971938fa6d5449c703789f17e7c3d 100644
--- a/src/main/webapp/WEB-INF/spring/spring-main.xml
+++ b/src/main/webapp/WEB-INF/spring/spring-main.xml
@@ -24,14 +24,14 @@
 			</list>
 		</property>
 	</bean>
-	
+
 	<import resource="spring-security.xml" />
 
 	<context:component-scan base-package="de.thm.arsnova.dao,de.thm.arsnova.services,de.thm.arsnova.events" />
 	<context:annotation-config />
 
 	<task:annotation-driven />
-	
+
 	<aop:aspectj-autoproxy>
 		<aop:include name="authorizationAdviser" />
 		<aop:include name="userSessionAspect" />
@@ -41,11 +41,11 @@
 		init-method="startServer" destroy-method="stopServer" scope="singleton"
 		p:portNumber="${socketio.port}" p:hostIp="${socketio.ip}" p:useSSL="${security.ssl}" p:keystore="${security.keystore}"
 		p:storepass="${security.storepass}" />
-		
+
 	<bean id="authorizationAdviser" class="de.thm.arsnova.aop.AuthorizationAdviser">
 		<property name="userService" ref="userService" />
 	</bean>
-	
+
 	<bean id="userSessionAspect" class="de.thm.arsnova.aop.UserSessionAspect" />
 
 	<bean id="userService" scope="singleton" class="de.thm.arsnova.services.UserService" />
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index 79137518b9ebfe1e03bc0fab3eda26ecaeab1443..8798a75df6eccae31b54f131c5845af8228791d4 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -59,10 +59,23 @@
 		<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
 	</listener>
 
+	<filter>
+		<filter-name>corsFilter</filter-name>
+		<filter-class>de.thm.arsnova.web.CorsFilter</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>corsFilter</filter-name>
+		<url-pattern>/*</url-pattern>
+	</filter-mapping>
+
 	<mime-mapping>
 		<extension>manifest</extension>
 		<mime-type>text/cache-manifest</mime-type>
 	</mime-mapping>
+	<mime-mapping>
+		<extension>json</extension>
+		<mime-type>application/json</mime-type>
+	</mime-mapping>
 
 	<error-page>
 		<error-code>401</error-code>
diff --git a/src/main/webapp/arsnova.properties.example b/src/main/webapp/arsnova.properties.example
index 19734f43ca0f6db41eed5b36a6eff5543e035df3..678e41714db1ab3a418171b325721564d19f0b19 100644
--- a/src/main/webapp/arsnova.properties.example
+++ b/src/main/webapp/arsnova.properties.example
@@ -17,6 +17,9 @@ security.storepass=arsnova
 # minutes, after which the feedback is deleted
 feedback.cleanup=10
 
+# maximal filesize in bytes
+upload.filesize_b=1048576
+
 couchdb.host=localhost
 couchdb.port=5984
 couchdb.name=arsnova
diff --git a/src/site/apt/development.apt b/src/site/apt/development.apt
deleted file mode 100644
index a03c524381d5be473e1b760983413912737ae7d1..0000000000000000000000000000000000000000
--- a/src/site/apt/development.apt
+++ /dev/null
@@ -1,127 +0,0 @@
- -------------------
- ARSnova Development
- -------------------
- -------------------
- ARSnova Developers
- -------------------
- 2013-03-11
-
-Development
-
- This short guide will help you get your development environment up and running. In brief, here is the list of the required tools:
- 
- 	* Apache HTTP Server
- 
-	* Apache Maven
-
-	* Git
-	
-	* Apache CouchDB
-	
-	* ARSnova
-	
-	ARSnova consists of several sub projects. The first one is the project you're currently looking at. All projects except for 'arsnova-war' are optional: you don't need to download them if you do not plan to work with them.
-	
-		* arsnova-war (this project)
-		
-		* arsnova-legacy-js
-		
-		* arsnova-js
-		
-		* arsnova-st2-js
-		
-		* setuptool
-		
-		* connector (manual installation is currently required in order to run 'arsnova-war')
-	
-	* Sonar and Sonar Runner
-	
-		* JavaScript Plugin
-		
-	* Eclipse JEE
- 
-	Install the following plugins from the Eclipse Marketplace:
-	
-		* Maven WTP
-	
-		* EGit
-	
-		* Sonar
-	
-		* Checkstyle
-		
- A note to all Windows users: We did not test this documentation on any Windows machine, so your mileage will certainly vary.
-
-* Apache HTTP Server
-
- The best option is to use your distribution's package manager to install your first piece of software: the Apache HTTP Server. For now, no additional configuration is necessary.
-		
-* Apache Maven
-
- As you might have noticed, ARSnova and its tools require a JDK. So go ahead and install it from your favorite package manager if you haven't already.
- 
- Download Maven and follow the installation instructions: {{http://maven.apache.org/download.cgi}}
- 
-* Git
-
- Install Git via your package manager. Windows users might want to try {{{http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git}msysgit}}.
- 
-* Apache CouchDB
-
- Again, the best way is to use your package manager to install CouchDB. Additionally, some binaries are available at {{http://couchdb.apache.org}}.
- 
-* ARSnova
-
- Head over to {{https://scm.thm.de/arsnova}}. Here you'll find all ARSnova repositories. You could now either clone them directly onto your machine, or create a personal clone first ('Clone repository' button). The first option will usually suffice, and you may create a personal clone later at any time.
- 
- It's best to first create an ARSnova project folder. Inside this folder clone all of the following repositories:
- 
- 	* arsnova-war
-	
-	* arsnova-legacy-js
-	
-	* arsnova-st2-js
-	
-	* arsnova-js
-	
-	* setuptool
-	
-	* connector
-
- A folder for each project will be created during checkout.	
- 
- Now is a good time to check if you configured your Git client correctly. Type in the commands 'git config --global user.name' and 'git config --global user.email', and verify they return the values you want. By leaving out the '--global' part while being inside a folder with a Git repository, the settings will be specific to this repository.
- 
- The next task is to configure ARSnova according to the {{{installation.html}installation manual}}.
- 
- As we're going to modify the local CouchDB, make sure you also specify the properties 'couchdb.username' and 'couchdb.password'; they are not present in the example properties file. Either put in your CouchDB credentials, or leave them blank if you did follow this guide step by step.
- 
- If your system has Python installed, head into the 'setuptool' project and run 'python tool.py' to automatically set up the CouchDB database and all views. If Python is not available, you will need to execute this project from Eclipse.
- 
- Finally, by running 'mvn install' inside each repository you will compile, test and install the project into your local Maven repository. This step is not required, but it will show if everything is set up correctly.
- 
- Note: If you get build failures because the 'connector' dependency could not be resolved, you have to manually 'mvn install' the 'connector'.
- 
-* Sonar
-
- Use your package manager to install Sonar and Sonar Runner, or follow the instructions at {{http://docs.codehaus.org/display/SONAR/Installing+Sonar}}. Once both are installed start the Sonar server if it is not yet running, then go to {{http://localhost:9000}}, and click 'Log in' (located in the far right corner). Username and password both are 'admin'. Then, click on 'Settings' and select 'System'. In the menu on the left you can then select 'Update Center'. Now, change to 'Available Plugins' and search for JavaScript. Click the name and then click Install. A restart of Sonar is required to finish the installation process.
- 
-* Eclipse
-
- For our IDE we chose Eclipse JEE: {{http://www.eclipse.org/downloads/}}
- 
- Unpack it into a folder of your choice. Run Eclipe, and then open the Eclipse Marketplace; it's located in the Help menu. There, search and install the following plugins (you might have to restart Eclipse several times along the way):
- 
- 	* m2e-wtp
-	
-	* EGit (might already be installed)
-	
-	* Sonar (you might want to deselect the Python and C/C++ analyzers)
-	
-	* Checkstyle
-	
- Next, you're going to import each project into the workspace. Select 'Import...' from the File menu, open the 'Maven' category, and select 'Existing Maven Projects'. Browse into a project you cloned previously, checkmark the project as it appears and click finish. Repeat for every project you want to develop for.
- 
- For Checkstyle support in 'arsnova-war', right click the project, open the properties, and select the Checkstyle category. Switch to the 'Local Check Configurations' tab, and for 'Type' select 'External Configuration File'. Give it a name (eg. 'ARSnova'), then browse into the project's folder, and select 'ARSnova-checkstyle-checker.xml'. When you click on 'OK', you will get an error message. But don't worry, just click on 'Edit properties...' and follow the instructions. An empty property for a cache file will get created, and you need to enter a file name of your choice. Now Close all dialogs. To test drive Checkstyle right clicking on the project and select 'Check Code with Checkstyle' from the 'Checkstyle' menu.
- 
- And that's it! If you have spotted any mistakes please let us know.
\ No newline at end of file
diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt
index 0de3f466fa60e79e2162c6808ee9f3adb955a7ec..3cb05dc4ca849716242dd9978f95514530cc1eb8 100644
--- a/src/site/apt/index.apt
+++ b/src/site/apt/index.apt
@@ -14,7 +14,7 @@ ARSnova
 	
 	* {{{https://scm.thm.de/redmine/documents/16}Präsentation über ARSnova}}
 	
-	* {{{https://ars.thm.de/download/}Desktop-Widget}}
+	* {{{https://arsnova.eu/overlay/}Desktop-Widget}}
 	
 	* {{{http://prezi.com/bkfz1utyaiiw/arsnova/}ARSnova auf Prezi}}
 
diff --git a/src/site/apt/installation.apt b/src/site/apt/installation.apt
deleted file mode 100644
index e30cf7011119154090972cc365713a56e487b5e9..0000000000000000000000000000000000000000
--- a/src/site/apt/installation.apt
+++ /dev/null
@@ -1,111 +0,0 @@
- -----
- Installation Instructions
- -----
- ARSnova Developers
- -----
- -----
-
- 
-Deployment
-
- You will need to do some configuration work upfront.
-
-  * Add a new directory "arsnova" in /etc and create a copy of arsnova.properties.example named arsnova.properties in this directory.
-  
-  * Change settings to match your environment
-
-Server configuration
-
- In order to build up a full featured server installation containing ARSnova2 and CouchDB you have to install at least the following services:
-  
-  * Apache Tomcat 7.0.29 (or newer)
-  
-  * Apache Webserver 2.2 or newer with buildin mod_proxy, mod_proxy_ajp and mod_proxy_http
-  
-  * Apache CouchDB
- 
- Make sure all services are installed. Next step is to configure the Apache Webserver. Find the configuration file or create a new one for use with a virtal host. This depends on your needs. At least you should have a configuration containing these settings:
-
-+--------------------------------------------------------+
-	
-	<Location /couchdb/>
-		ProxyPass http://127.0.0.1:5984/
-		ProxyPassReverse http://127.0.0.1:5984/
-	</Location> 
-	
-	<Location />
-		ProxyPass ajp://127.0.0.1:8009/
-		ProxyPassReverse ajp://127.0.0.1:8009/
-	</Location>
-	
-+--------------------------------------------------------+
-
- This will redirect all requests for "/couchdb/..." to your Apache CouchDB server, running on port 5984.
- All other requests will be send to your Apache Tomcat servelt container, using AJP running on port 8009.
-
- To enable the needed Apache Webserver simply type:
-
-+---------------------------+
- 
-  # a2enmod proxy
-  # a2enmod proxy_ajp
-  # a2enmod proxy_http
- 
-+---------------------------+
-
- The configuration is ready for development usage. You should (re)start all services. ARSnova2 is now listening on HTTP port 80.
-
-Make environment usable for productive usage
-
- If you intend to use ARSnova in productive environment, you will have to change a setting in your Tomcat installation.
- Look for your Tomcat configuration directory and change the file "context.xml" to match this example:
- 
-+---------------------------+
- 
-<Context>
-	<Manager pathname="<...your_tomcat_installation...>/sessions/arsnova.ser"/>
-</Context> 
- 
-+---------------------------+
- 
- This will enable session persistance across restarts as described {{{http://tomcat.apache.org/tomcat-7.0-doc/config/manager.html#Special_Features}here}}.
-
- To protect requests and responses you should use HTTPS and configure your Apache Webserver installation to redirect all traffic according to this
- {{{http://wiki.apache.org/httpd/RedirectSSL}example}}.
-
- Finally you should (re)start all services. ARSnova2 is now listening on HTTP port 80 and 443.
- 
-Securing your websocket connection
-
- To provide SSL websocket encryption, you have to provide the servers ssl key and certificate in a Java keystore. The following steps will guide you threw this process.
- 
- Use your webserver certificate, private key and certificate chain to create a PKCS12 keystore
-
-+---------------------------+
-openssl pkcs12 -export -in <servercert>.crt -inkey <serverkey>.key \
-               -out keystore.p12 -name 1 \
-               -certfile <your_cert_chain_file>
-+---------------------------+
-
- You will be asked for a password for your PKCS12 keystore. This password must be used for importing this keystore into your java keystore.
- The import can be done by using this command:
-
-+---------------------------+
-keytool -importkeystore \
-        -deststorepass <your_java_keystore_password> -destkeypass <your_java_keystore_password> -destkeystore arsnova.jks \
-        -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass <your_pkcs12_keystore_password> \
-        -alias 1
-+---------------------------+
- 
- Be sure to provide the correct certificate and key file names and to use the correct passwords for your keystore.
- 
- The last step is to find your ARSnova configuration file, setup the location of your Java keystore and its password.
- 
-+---------------------------+
- 
-security.ssl=true
-security.keystore=<your keystore location>
-security.storepass=<your keystore password>
- 
-+---------------------------+
- 
\ No newline at end of file
diff --git a/src/site/site.xml b/src/site/site.xml
index c29364d8c13c22a3d033de91e8b5119873d37e80..cd6bc92b515e5b3f9771b9086524777e607b241d 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 
-<project name="ARSNova" xmlns="http://maven.apache.org/DECORATION/1.0.0"
+<project name="ARSnova" xmlns="http://maven.apache.org/DECORATION/1.0.0"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://maven.apache.org/DECORATION/1.0.0 http://maven.apache.org/xsd/decoration-1.0.0.xsd">
 
@@ -50,8 +50,8 @@
 			<item name="The Team" href="team-list.html" />
 		</menu>
 		<menu name="Documentation">
-			<item name="Installation" href="installation.html" />
-			<item name="Development" href="development.html" />
+			<item name="Installation" href="https://github.com/thm-projects/arsnova-war#production-use" />
+			<item name="Development" href="https://github.com/thm-projects/arsnova-war#development" />
 			<item name="Dependencies" href="dependencies.html" />
 			<item name="API Docs" href="apidocs/index.html" />
 		</menu>
diff --git a/src/test/java/de/thm/arsnova/ARSnovaChromeDriver.java b/src/test/java/de/thm/arsnova/ARSnovaChromeDriver.java
deleted file mode 100644
index 97905e6acc4a7a63f94180b896f1c3020092ca4d..0000000000000000000000000000000000000000
--- a/src/test/java/de/thm/arsnova/ARSnovaChromeDriver.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2012 THM webMedia
- * 
- * This file is part of ARSnova.
- *
- * ARSnova 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 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;
-
-import org.openqa.selenium.chrome.ChromeDriver;
-import org.openqa.selenium.html5.*;
-import org.openqa.selenium.remote.html5.*;
-
-public class ARSnovaChromeDriver extends ChromeDriver implements WebStorage {
-
-	public LocalStorage getLocalStorage() {
-		return new RemoteLocalStorage(this.getExecuteMethod());
-	}
-
-	@Override
-	public SessionStorage getSessionStorage() {
-		return new RemoteSessionStorage(this.getExecuteMethod());
-	}
-}
diff --git a/src/test/java/de/thm/arsnova/HttpRestApiTest.java b/src/test/java/de/thm/arsnova/HttpRestApiTest.java
deleted file mode 100644
index 31c8994a2dc4352f21ae51d3eba59bf414ca0c79..0000000000000000000000000000000000000000
--- a/src/test/java/de/thm/arsnova/HttpRestApiTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2012 THM webMedia
- * 
- * This file is part of ARSnova.
- *
- * ARSnova 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 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.BufferedReader;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * Unit test to verify the public RESTlike API.
- * 
- * These tests only check the API communication and structure of responses. They do not verify data.
- */
-public class HttpRestApiTest {
-	public final String host = "localhost";
-	public final int port = 8080;
-	public final String pathPrefix = "/";
-	
-	private HttpURLConnection sendRequest(String path, String method, String accept, HashMap<String, String> parameters, String contentType, String body) throws IOException {
-		HttpURLConnection conn;
-		
-		try {
-			conn = (HttpURLConnection) (new URL("http", host, port, pathPrefix + path)).openConnection();
-			System.out.println(conn.getURL().toExternalForm());
-			
-			conn.setRequestMethod(method);
-			conn.setRequestProperty("Accept", accept);
-			conn.setRequestProperty("Host", host + ":" + Integer.valueOf(port));
-			
-			if (null != body) {
-				conn.setRequestProperty("Content-Type", contentType);
-				conn.setRequestProperty("Content-Length", Integer.toString(body.getBytes().length));
-				conn.setDoOutput(true);
-				DataOutputStream out = new DataOutputStream(conn.getOutputStream());
-				out.writeBytes(body);
-				out.flush();
-				out.close();
-			}
-		} catch (MalformedURLException e) {
-			conn = null;
-			e.printStackTrace();
-		}
-		
-		return conn;
-	}
-	
-	private HttpURLConnection sendRequest(String path, String method, String accept, HashMap<String, String> parameters) throws IOException {
-		return sendRequest(path, method, accept, parameters, null, null);
-	}
-	
-	private String transformInputToString(InputStream input) throws IOException {
-		BufferedReader reader = new BufferedReader(new InputStreamReader(input));
-		StringBuilder str = new StringBuilder();
-		String line;
-		while (null != (line = reader.readLine())) {
-			str.append(line);
-		}
-		System.out.println(str);
-		
-		return str.toString();
-	}
-	
-	private JSONObject transformInputToJsonObject(InputStream input) throws IOException, JSONException {
-		return new JSONObject(transformInputToString(input));
-	}
-	
-	private JSONArray transformInputToJsonArray(InputStream input) throws IOException, JSONException {
-		return new JSONArray(transformInputToString(input));
-	}
-
-	@Ignore("Test not implemented")
-	@Test
-	public void testSession() throws Exception {
-
-	}
-	
-	@Ignore("Test not implemented")
-	@Test
-	public void testQuestionByLecturer() throws Exception {
-
-	}
-
-	@Ignore("Test not implemented")
-	@Test
-	public void testQuestionByAudience() throws Exception {
-
-	}
-
-	@Ignore("Test not implemented")
-	@Test
-	public void testSocket() throws Exception {
-
-	}
-
-	@Test
-	public void testCanteen() throws Exception {
-		HttpURLConnection conn;
-		JSONArray jsonArr;
-		String responseBody;
-		
-		/* TODO: make test case more specific  */
-		conn = sendRequest("canteen/menu/vote", "GET", "application/json", null);
-		assertEquals(200, conn.getResponseCode());
-		jsonArr = transformInputToJsonArray(conn.getInputStream());
-		assertNotNull(jsonArr);
-		
-		conn = sendRequest("canteen/menu/vote/count", "GET", "text/plain", null);
-		assertEquals(200, conn.getResponseCode());
-		responseBody = transformInputToString(conn.getInputStream());
-		Integer.valueOf(responseBody);
-		
-		/* TODO: implement test for POST /canteen/menu/vote */
-	}
-
-	@Test
-	public void testStatistics() throws Exception {
-		HttpURLConnection conn;
-		JSONObject jsonObj;
-		String responseBody;
-		
-		conn = sendRequest("statistics", "GET", "application/json", null);
-		assertEquals(200, conn.getResponseCode());
-		jsonObj = transformInputToJsonObject(conn.getInputStream());
-		assertTrue(jsonObj.has("answers"));
-		assertTrue(jsonObj.has("questions"));
-		assertTrue(jsonObj.has("openSessions"));
-		assertTrue(jsonObj.has("closedSessions"));
-		assertTrue(jsonObj.has("activeUsers"));
-		
-		conn = sendRequest("statistics/activeusercount", "GET", "text/plain", null);
-		assertEquals(200, conn.getResponseCode());
-		responseBody = transformInputToString(conn.getInputStream());
-		Integer.parseInt(responseBody);
-		
-		conn = sendRequest("statistics/sessioncount", "GET", "text/plain", null);
-		assertEquals(200, conn.getResponseCode());
-		responseBody = transformInputToString(conn.getInputStream());
-		Integer.parseInt(responseBody);
-	}
-}
\ No newline at end of file
diff --git a/src/test/java/de/thm/arsnova/Selenium2Test.java b/src/test/java/de/thm/arsnova/Selenium2Test.java
deleted file mode 100644
index 98a5211c11e13cbcbb125d0e70bd5412015a949e..0000000000000000000000000000000000000000
--- a/src/test/java/de/thm/arsnova/Selenium2Test.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package de.thm.arsnova;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.html5.LocalStorage;
-import org.openqa.selenium.support.ui.ExpectedCondition;
-import org.openqa.selenium.support.ui.ExpectedConditions;
-import org.openqa.selenium.support.ui.WebDriverWait;
-import org.springframework.core.io.FileSystemResource;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.PropertiesLoaderUtils;
-
-import de.thm.arsnova.dao.CouchDBDao;
-import de.thm.arsnova.entities.Feedback;
-import de.thm.arsnova.entities.Session;
-import de.thm.arsnova.services.FeedbackService;
-import de.thm.arsnova.services.SessionService;
-import de.thm.arsnova.services.StubUserService;
-
-public class Selenium2Test {
-
-	private ARSnovaChromeDriver driver;
-	private Properties properties;
-
-	private CouchDBDao couchdbDao;
-	private SessionService sessionService;
-	private StubUserService userService;
-	private FeedbackService feedbackService;
-
-	@Before
-	public final void setUp() throws IOException {
-		Resource resource = new FileSystemResource("/etc/arsnova/arsnova.properties");
-		properties = PropertiesLoaderUtils.loadProperties(resource);
-
-		userService = new StubUserService();
-		userService.setUserAuthenticated(true);
-
-		couchdbDao = new CouchDBDao();
-		couchdbDao.setDatabaseHost(properties.getProperty("couchdb.host", "localhost"));
-		couchdbDao.setDatabasePort(properties.getProperty("couchdb.port", "5984"));
-		couchdbDao.setDatabaseName(properties.getProperty("couchdb.name", "arsnova"));
-		sessionService = new SessionService();
-		couchdbDao.setSessionService(sessionService);
-		couchdbDao.setUserService(userService);
-		sessionService.setDatabaseDao(couchdbDao);
-		feedbackService = new FeedbackService();
-		feedbackService.setDatabaseDao(couchdbDao);
-
-		this.driver = new ARSnovaChromeDriver();
-		driver.get(properties.getProperty("security.arsnova-url", "http://localhost:8080/arsnova-war/"));
-		LocalStorage localStorage = this.driver.getLocalStorage();
-		localStorage.setItem("html5 info read", "");
-	}
-
-	@After
-	public final void tearDown() {
-		driver.close();
-		driver.quit();
-	}
-
-	@Test
-	public final void studentGuestShouldPostFeedback() {
-		Session session = couchdbDao.saveSession(createSession());
-		Feedback initialFeedback = feedbackService.getFeedback(session.getKeyword());
-
-		selectStudentRole();
-		loginAsGuest();
-		joinSession(session);
-
-		WebElement feedbackBadButton = waitForElement(By.className("feedbackBad"));
-		// Before clicking, ensure that no loading mask is displayed
-		By loadingSpinner = By.className("x-mask");
-		waitWhileVisible(loadingSpinner);
-		feedbackBadButton.click();
-		
-		// Wait for the feedback to arrive back at the client
-		By feedbackResultToolbar = By.id("ext-comp-1125");
-		waitForElementWithContent(feedbackResultToolbar, "1/");
-		
-		Feedback feedback = feedbackService.getFeedback(session.getKeyword());
-		assertEquals(new Feedback(0, 0, 0, 0), initialFeedback);
-		assertEquals(new Feedback(0, 0, 1, 0), feedback);
-	}
-
-	private void waitForElementWithContent(final By by, final String content) {
-		final long timeoutInSecs = 10;
-		(new WebDriverWait(driver, timeoutInSecs)).until(new ExpectedCondition<Boolean>() {
-			public Boolean apply(final WebDriver d) {
-				WebElement element = d.findElement(by);
-				return element != null && element.getText().contains(content);
-			}
-		});
-	}
-
-	private void assertEquals(Feedback feedback, Feedback feedback2) {
-		assertTrue(feedback.equals(feedback2));
-	}
-
-	private WebElement waitForElement(final By by) {
-		final long timeoutInSecs = 10;
-		(new WebDriverWait(driver, timeoutInSecs)).until(new ExpectedCondition<Boolean>() {
-			public Boolean apply(final WebDriver d) {
-				return d.findElement(by) != null;
-			}
-		});
-		return driver.findElement(by);
-	}
-	
-	private void waitWhileVisible(final By by) {
-		final long timeoutInSecs = 10;
-		(new WebDriverWait(driver, timeoutInSecs)).until(ExpectedConditions.invisibilityOfElementLocated(by));
-	}
-
-	private Session createSession() {
-		return createNamedSession(null, null);
-	}
-
-	private Session createNamedSession(final String name, final String shortName) {
-		Session session = new Session();
-		session.setName(name != null ? name : "selenium test session");
-		session.setShortName(shortName != null ? shortName : "selenium");
-		return session;
-	}
-
-	private void joinSession(Session session) {
-		WebElement sessionKeywordField = waitForElement(By.name("keyword"));
-		sessionKeywordField.sendKeys(session.getKeyword());
-		WebElement joinSessionButton = waitForElement(By.id("ext-gen1138"));
-		joinSessionButton.click();
-	}
-
-	private void loginAsGuest() {
-		WebElement guestLoginButton = waitForElement(By.id("ext-gen1016"));
-		guestLoginButton.click();
-	}
-
-	private void selectStudentRole() {
-		WebElement studentRoleButton = waitForElement(By.id("ext-gen1047"));
-		studentRoleButton.click();
-	}
-}
diff --git a/src/test/java/de/thm/arsnova/controller/FeedbackControllerTest.java b/src/test/java/de/thm/arsnova/controller/FeedbackControllerTest.java
index 9a9ef5bd836eaa7b38e0ddf22ea5fa47a3befca4..0c9ae13d77bc7dee889f5aff3c8891f9406befbc 100644
--- a/src/test/java/de/thm/arsnova/controller/FeedbackControllerTest.java
+++ b/src/test/java/de/thm/arsnova/controller/FeedbackControllerTest.java
@@ -1,113 +1,72 @@
 package de.thm.arsnova.controller;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
-import javax.inject.Inject;
-
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.http.MediaType;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
 
-import de.thm.arsnova.FeedbackStorage;
-import de.thm.arsnova.dao.StubDatabaseDao;
-import de.thm.arsnova.exceptions.NoContentException;
-import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.services.StubUserService;
 
 @RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
 @ContextConfiguration(locations = {
 		"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
 		"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
-		"file:src/test/resources/test-config.xml"
+		"file:src/test/resources/test-config.xml",
+		"file:src/test/resources/test-socketioconfig.xml"
 })
 public class FeedbackControllerTest {
 
-	@Inject
-	private ApplicationContext applicationContext;
-	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
-	private HandlerAdapter handlerAdapter;
-
-	@Autowired
-	private FeedbackController feedbackController;
-
 	@Autowired
 	private StubUserService userService;
-	
-	@Autowired
-	private StubDatabaseDao databaseDao;
-	
-	private FeedbackStorage feedbackStorage;
 
-	@After
-	public final void cleanup() {
-		databaseDao.cleanupTestData();
-	}
+	private MockMvc mockMvc;
+
+	@Autowired
+	private WebApplicationContext webApplicationContext;
 
 	@Before
-	public void setUp() {
-		this.request = new MockHttpServletRequest();
-		this.response = new MockHttpServletResponse();
-		handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
-		this.feedbackStorage = new FeedbackStorage(databaseDao); 
+	public void setup() {
+		mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 	}
 
-	@Test(expected = NotFoundException.class)
+	@Test
 	public void testShouldNotGetFeedbackForUnknownSession() throws Exception {
 		userService.setUserAuthenticated(true);
-
-		request.setMethod("GET");
-		request.setRequestURI("/session/00000000/feedback");
-		final ModelAndView mav = handlerAdapter.handle(request, response, feedbackController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 404);
+		mockMvc.perform(get("/session/00000000/feedback").accept(MediaType.APPLICATION_JSON))
+		.andExpect(status().isNotFound());
 	}
 
-	@Test(expected = NoContentException.class)
+	@Test
 	public void testShouldNotGetAverageFeedbackContentForSessionWithoutFeedback() throws Exception {
 		userService.setUserAuthenticated(true);
-
-		request.setMethod("GET");
-		request.setRequestURI("/session/12345678/averagefeedback");
-		final ModelAndView mav = handlerAdapter.handle(request, response, feedbackController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 204);
+		mockMvc.perform(get("/session/12345678/averagefeedback").accept(MediaType.APPLICATION_JSON))
+		.andExpect(status().isNoContent());
 	}
 
 	@Test
 	public void testShouldNotGetCorrectFeedbackCountForSessionWithoutFeedback() throws Exception {
 		userService.setUserAuthenticated(true);
-
-		request.setMethod("GET");
-		request.setRequestURI("/session/12345678/feedbackcount");
-		handlerAdapter.handle(request, response, feedbackController);
-
-		assertTrue(response.getStatus() == 200);
-		assertEquals("0", response.getContentAsString());
+		mockMvc.perform(get("/session/12345678/feedbackcount").accept(MediaType.APPLICATION_JSON))
+		.andExpect(status().isOk())
+		.andExpect(content().string("0"));
 	}
-	
+
 	@Test
 	public void testShouldReturnFeedback() throws Exception {
 		userService.setUserAuthenticated(true);
-
-		request.setMethod("GET");
-		request.setRequestURI("/session/87654321/feedback");
-		handlerAdapter.handle(request, response, feedbackController);
-
-		assertTrue(response.getStatus() == 200);
+		mockMvc.perform(get("/session/87654321/feedback").accept(MediaType.APPLICATION_JSON))
+		.andExpect(status().isOk());
 	}
 }
diff --git a/src/test/java/de/thm/arsnova/controller/LecturerQuestionControllerTest.java b/src/test/java/de/thm/arsnova/controller/LecturerQuestionControllerTest.java
deleted file mode 100644
index 3ea9fb83d1eab66be3813cda4a7eec8933b43e8f..0000000000000000000000000000000000000000
--- a/src/test/java/de/thm/arsnova/controller/LecturerQuestionControllerTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package de.thm.arsnova.controller;
-
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import javax.inject.Inject;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
-
-import de.thm.arsnova.dao.StubDatabaseDao;
-import de.thm.arsnova.exceptions.NotFoundException;
-import de.thm.arsnova.exceptions.UnauthorizedException;
-import de.thm.arsnova.services.StubUserService;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = {
-		"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
-		"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
-		"file:src/test/resources/test-config.xml" })
-public class LecturerQuestionControllerTest {
-
-	@Inject
-	private ApplicationContext applicationContext;
-	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
-	private HandlerAdapter handlerAdapter;
-
-	@Autowired
-	private LecturerQuestionController lecturerQuestionController;
-	
-	@Autowired
-	private StubUserService userService;
-	
-	@Autowired
-	private StubDatabaseDao databaseDao;
-
-	@After
-	public final void cleanup() {
-		databaseDao.cleanupTestData();
-	}
-
-	@Before
-	public void setUp() {
-		this.request = new MockHttpServletRequest();
-		this.response = new MockHttpServletResponse();
-		handlerAdapter = applicationContext
-				.getBean(AnnotationMethodHandlerAdapter.class);
-	}
-
-	/* TODO: update test case for API changes or remove it if it is not necessary anymore */
-	@Ignore
-	@Test(expected=NotFoundException.class)
-	public void testShouldNotGetQestionIdsForUnknownSession() throws Exception {
-		userService.setUserAuthenticated(true);
-		
-		request.setMethod("GET");
-		request.setRequestURI("/session/00000000/questionids");
-		final ModelAndView mav = handlerAdapter.handle(request, response, lecturerQuestionController);
-		
-		assertNull(mav);
-		assertTrue(response.getStatus() == 404);
-	}
-	
-	/* TODO: update test case for API changes or remove it if it is not necessary anymore */
-	@Ignore
-	@Test(expected=UnauthorizedException.class)
-	public void testShouldNotGetQuestionIdsIfUnauthorized() throws Exception {
-		userService.setUserAuthenticated(false);
-		
-		request.setMethod("GET");
-		request.setRequestURI("/session/00000000/questionids");
-		final ModelAndView mav = handlerAdapter.handle(request, response, lecturerQuestionController);
-		
-		assertNull(mav);
-		assertTrue(response.getStatus() == 401);
-	}
-
-}
diff --git a/src/test/java/de/thm/arsnova/controller/LoginControllerTest.java b/src/test/java/de/thm/arsnova/controller/LoginControllerTest.java
index 65b8ffa4af117a2a211af79108bd93fbc928193d..2b2287dd40b005e494caf32c75d3330b915a078e 100644
--- a/src/test/java/de/thm/arsnova/controller/LoginControllerTest.java
+++ b/src/test/java/de/thm/arsnova/controller/LoginControllerTest.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 THM webMedia
- * 
+ *
  * This file is part of ARSnova.
  *
  * ARSnova is free software: you can redistribute it and/or modify
@@ -19,139 +19,78 @@
 package de.thm.arsnova.controller;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import javax.inject.Inject;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
-import org.springframework.web.servlet.view.RedirectView;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
 
-import de.thm.arsnova.dao.StubDatabaseDao;
 import de.thm.arsnova.services.StubUserService;
 
 @RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
 @ContextConfiguration(locations = {
 		"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
 		"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
-		"file:src/test/resources/test-config.xml" })
+		"file:src/test/resources/test-config.xml",
+		"file:src/test/resources/test-socketioconfig.xml"
+})
 public class LoginControllerTest {
 
-	@Inject
-	private ApplicationContext applicationContext;
-	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
-	private HandlerAdapter handlerAdapter;
-
-	@Autowired
-	private LoginController loginController;
-
 	@Autowired
 	private StubUserService userService;
-	
-	@Autowired
-	private StubDatabaseDao databaseDao;
 
-	@After
-	public final void cleanup() {
-		databaseDao.cleanupTestData();
-	}
+	private MockMvc mockMvc;
+
+	@Autowired
+	private WebApplicationContext webApplicationContext;
 
 	@Before
-	public void setUp() throws Exception {
-		this.request = new MockHttpServletRequest();
-		this.response = new MockHttpServletResponse();
-		handlerAdapter = applicationContext
-				.getBean(AnnotationMethodHandlerAdapter.class);
+	public void setup() {
+		mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 	}
 
 	@Test
 	public void testGuestLogin() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/doLogin");
-		request.addParameter("type", "guest");
-
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				loginController);
-
-		assertNotNull(mav);
-		assertNotNull(mav.getView());
-		RedirectView view = (RedirectView) mav.getView();
-		assertEquals("/#auth/checkLogin", view.getUrl());
-		Authentication auth = SecurityContextHolder.getContext()
-				.getAuthentication();
-		assertEquals(auth.getClass(), UsernamePasswordAuthenticationToken.class);
+		mockMvc.perform(get("/doLogin").param("type", "guest")).andExpect(status().isMovedTemporarily()).andExpect(redirectedUrl("/#auth/checkLogin"));
 	}
 
 	@Test
 	public void testReuseGuestLogin() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/doLogin");
-		request.addParameter("type", "guest");
-		request.addParameter("user", "Guest1234567890");
+		mockMvc.perform(get("/doLogin").param("type", "guest").param("user","Guest1234567890"))
+		.andExpect(status().isMovedTemporarily()).andExpect(redirectedUrl("/#auth/checkLogin"));
 
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				loginController);
-
-		assertNotNull(mav);
-		assertNotNull(mav.getView());
-		RedirectView view = (RedirectView) mav.getView();
-		assertEquals("/#auth/checkLogin", view.getUrl());
 		Authentication auth = SecurityContextHolder.getContext()
 				.getAuthentication();
 		assertEquals(auth.getClass(), UsernamePasswordAuthenticationToken.class);
 		assertEquals("Guest1234567890", auth.getName());
+
 	}
 
 	@Test
 	public void testUser() throws Exception {
 		userService.setUserAuthenticated(true);
 
-		request.setMethod("GET");
-		request.setRequestURI("/whoami");
-
-		handlerAdapter.handle(request, response, loginController);
-		assertNotNull(response);
-		assertEquals("{\"username\":\"ptsr00\",\"type\":\"ldap\",\"role\":null}", response.getContentAsString());
+		mockMvc.perform(get("/whoami"))
+		.andExpect(status().isOk())
+		.andExpect(content().string("{\"username\":\"ptsr00\",\"type\":\"ldap\",\"role\":null}"));
 	}
 
 	@Test
 	public void testLogoutWithoutRedirect() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/logout");
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				loginController);
-		assertNotNull(mav);
-		assertNotNull(mav.getView());
-		RedirectView view = (RedirectView) mav.getView();
-		assertEquals("/", view.getUrl());
-	}
-
-	@Test
-	public void testLogoutWithRedirect() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/logout");
-		request.addHeader("referer", "/dojo-index.html");
-
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				loginController);
-		assertNotNull(mav);
-		assertNotNull(mav.getView());
-		RedirectView view = (RedirectView) mav.getView();
-		assertEquals("/dojo-index.html", view.getUrl());
+		mockMvc.perform(get("/logout")).andExpect(status().isMovedTemporarily()).andExpect(redirectedUrl("/"));
 	}
 }
diff --git a/src/test/java/de/thm/arsnova/controller/SessionControllerTest.java b/src/test/java/de/thm/arsnova/controller/SessionControllerTest.java
index cdb927ae3b831584dc1f6f78db5decd11327273a..3b8ff88723dbeae89c5873522777534b565b3369 100644
--- a/src/test/java/de/thm/arsnova/controller/SessionControllerTest.java
+++ b/src/test/java/de/thm/arsnova/controller/SessionControllerTest.java
@@ -1,139 +1,79 @@
 package de.thm.arsnova.controller;
 
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
-import javax.inject.Inject;
-
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.http.MediaType;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
-
-import de.thm.arsnova.dao.StubDatabaseDao;
-import de.thm.arsnova.entities.Session;
-import de.thm.arsnova.exceptions.ForbiddenException;
-import de.thm.arsnova.exceptions.NotFoundException;
-import de.thm.arsnova.exceptions.UnauthorizedException;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
 import de.thm.arsnova.services.StubUserService;
-import de.thm.arsnova.services.UserSessionService;
 
 @RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
 @ContextConfiguration(locations = {
 		"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
 		"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
-		"file:src/test/resources/test-config.xml"
+		"file:src/test/resources/test-config.xml",
+		"file:src/test/resources/test-socketioconfig.xml"
 })
 public class SessionControllerTest {
 
-	@Inject
-	private ApplicationContext applicationContext;
-	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
-	private HandlerAdapter handlerAdapter;
+	@Autowired
+	private StubUserService userService;
 
 	@Autowired
 	private SessionController sessionController;
 
-	@Autowired
-	private StubUserService userService;
-	
-	@Autowired
-	private StubDatabaseDao databaseDao;
+	private MockMvc mockMvc;
 
-	@After
-	public final void cleanup() {
-		databaseDao.cleanupTestData();
-	}
+	@Autowired
+	private WebApplicationContext webApplicationContext;
 
 	@Before
-	public void setUp() {
-		this.request = new MockHttpServletRequest();
-		this.response = new MockHttpServletResponse();
-		handlerAdapter = applicationContext
-				.getBean(AnnotationMethodHandlerAdapter.class);
+	public void setup() {
+		mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 	}
 
-	@Test(expected = NotFoundException.class)
+	@Test
 	public void testShouldNotGetUnknownSession() throws Exception {
 		userService.setUserAuthenticated(true);
 
-		request.setMethod("GET");
-		request.setRequestURI("/session/00000000");
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				sessionController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 404);
+		mockMvc.perform(get("/session/00000000"))
+		.andExpect(status().isNotFound());
 	}
 
-	@Test(expected = ForbiddenException.class)
-	public void testShouldNotGetForbiddenSession() throws Exception {
-		Session session = new Session();
-		session.setKeyword("08154711");
-		session.setCreator("some other user");
-		session.setActive(false);
-		databaseDao.saveSession(session);
-		userService.setUserAuthenticated(true);
-		userService.setRole(UserSessionService.Role.STUDENT);
-
-		request.setMethod("GET");
-		request.setRequestURI("/session/08154711");
-		final ModelAndView mav = handlerAdapter.handle(request, response, sessionController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 403);
-	}
-
-	@Test(expected = UnauthorizedException.class)
+	@Test
 	public void testShouldNotGetSessionIfUnauthorized() throws Exception {
 		userService.setUserAuthenticated(false);
 
-		request.setMethod("GET");
-		request.setRequestURI("/session/00000000");
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				sessionController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 401);
+		mockMvc.perform(get("/session/00000000"))
+		.andExpect(status().isUnauthorized());
 	}
 
-	@Test(expected = UnauthorizedException.class)
+	@Test
 	public void testShouldNotGetSessionIfAnonymous() throws Exception {
 		userService.setUserAuthenticated(false);
 		userService.useAnonymousUser();
 
-		request.setMethod("GET");
-		request.setRequestURI("/session/00000000");
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				sessionController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 401);
+		mockMvc.perform(get("/session/00000000"))
+		.andExpect(status().isUnauthorized());
 	}
 
-	@Test(expected = UnauthorizedException.class)
+	@Test
 	public void testShouldCreateSessionIfUnauthorized() throws Exception {
 		userService.setUserAuthenticated(false);
 
-		request.setMethod("POST");
-		request.setRequestURI("/session/");
-		request.setContentType("application/json");
-		request.setContent("{}".getBytes());
-
-		final ModelAndView mav = handlerAdapter.handle(request, response,
-				sessionController);
-
-		assertNull(mav);
-		assertTrue(response.getStatus() == 401);
+		mockMvc.perform(post("/session/").contentType(MediaType.APPLICATION_JSON).content("{}"))
+		.andExpect(status().isUnauthorized());
 	}
 }
diff --git a/src/test/java/de/thm/arsnova/controller/StatisticsControllerTest.java b/src/test/java/de/thm/arsnova/controller/StatisticsControllerTest.java
index 63fcbcd0bc271b89c926688f3bbc8fc09b7a0fb9..788c22d376d5b2486b7bb7641d32dfed27fb7f16 100644
--- a/src/test/java/de/thm/arsnova/controller/StatisticsControllerTest.java
+++ b/src/test/java/de/thm/arsnova/controller/StatisticsControllerTest.java
@@ -1,70 +1,61 @@
 package de.thm.arsnova.controller;
 
-import static org.junit.Assert.assertEquals;
-
-import javax.inject.Inject;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
 
 @RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
 @ContextConfiguration(locations = {
 		"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
 		"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
-		"file:src/test/resources/test-config.xml"
+		"file:src/test/resources/test-config.xml",
+		"file:src/test/resources/test-socketioconfig.xml"
 })
 public class StatisticsControllerTest {
 
-	@Inject
-	private ApplicationContext applicationContext;
-	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
-	private HandlerAdapter handlerAdapter;
-
 	@Autowired
 	private StatisticsController statisticsController;
 
+	private MockMvc mockMvc;
+
+	@Autowired
+	private WebApplicationContext webApplicationContext;
+
 	@Before
-	public final void setUp() {
-		this.request = new MockHttpServletRequest();
-		this.response = new MockHttpServletResponse();
-		handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
+	public void setup() {
+		mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 	}
 
 	@Test
 	public final void testShouldGetCurrentOnlineUsers() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/statistics/activeusercount");
-		handlerAdapter.handle(request, response, statisticsController);
-
-		assertEquals("0", response.getContentAsString());
+		mockMvc.perform(get("/statistics/activeusercount"))
+		.andExpect(status().isOk())
+		.andExpect(content().string("0"));
 	}
-	
+
 	@Test
 	public final void testShouldGetSessionCount() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/statistics/sessioncount");
-		handlerAdapter.handle(request, response, statisticsController);
-
-		assertEquals("3", response.getContentAsString());
+		mockMvc.perform(get("/statistics/sessioncount"))
+		.andExpect(status().isOk())
+		.andExpect(content().string("3"));
 	}
-	
+
 	@Test
 	public final void testShouldGetStatistics() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/statistics/");
-		handlerAdapter.handle(request, response, statisticsController);
-		
-		String expected = "{\"answers\":0,\"questions\":0,\"openSessions\":3,\"closedSessions\":0,\"activeUsers\":0}";
-		assertEquals(expected, response.getContentAsString());
+		mockMvc.perform(get("/statistics"))
+		.andExpect(status().isOk())
+		.andExpect(content().string("{\"answers\":0,\"questions\":0,\"openSessions\":3,\"closedSessions\":0,\"activeUsers\":0}"));
 	}
 }
diff --git a/src/test/java/de/thm/arsnova/controller/WelcomeControllerTest.java b/src/test/java/de/thm/arsnova/controller/WelcomeControllerTest.java
deleted file mode 100644
index 35d3287b375e24ca4039d45dfafc72f1d86a594d..0000000000000000000000000000000000000000
--- a/src/test/java/de/thm/arsnova/controller/WelcomeControllerTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 THM webMedia
- * 
- * This file is part of ARSnova.
- *
- * ARSnova 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 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.controller;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import javax.inject.Inject;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = {
-		"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
-		"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
-		"file:src/test/resources/test-config.xml" })
-public class WelcomeControllerTest {
-
-	@Inject
-	private ApplicationContext applicationContext;
-	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
-	private HandlerAdapter handlerAdapter;
-
-	@Autowired
-	private WelcomeController welcomeController;
-
-	@Before
-	public final void setUp() {
-		this.request = new MockHttpServletRequest();
-		this.response = new MockHttpServletResponse();
-		handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
-	}
-
-	@Test
-	public void testIndexPage() throws Exception {
-		request.setMethod("GET");
-		request.setRequestURI("/");
-
-		final ModelAndView mav = handlerAdapter.handle(request, response, welcomeController);
-		assertNotNull(mav);
-		assertEquals("redirect:/index.html", mav.getViewName());
-	}
-}
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index 8bef8eb9b932d22de9d0d0d4a080bdee49428402..bfd23302b147be58f012b22e2b8dcec6380d9c35 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -172,8 +172,8 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public List<Question> getSkillQuestions(String session) {
-		if (getSession(session) == null)
+	public List<Question> getSkillQuestions(User user, Session session) {
+		if (session == null)
 			throw new NotFoundException();
 		List<Question> questions = stubQuestions.get(session);
 		if (questions == null)
@@ -217,7 +217,7 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public int getAnswerCount(String questionId) {
+	public int getAnswerCount(Question question, int piRound) {
 		// TODO Auto-generated method stub
 		return 0;
 	}
@@ -274,12 +274,6 @@ public class StubDatabaseDao implements IDatabaseDao {
 		return null;
 	}
 
-	@Override
-	public int countActiveUsers(Session session, long since) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
 	@Override
 	public int countAnswers() {
 		// TODO Auto-generated method stub
@@ -409,4 +403,110 @@ public class StubDatabaseDao implements IDatabaseDao {
 		// TODO Auto-generated method stub
 		
 	}
+
+	@Override
+	public List<Question> getLectureQuestions(User user, Session session) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public List<Question> getFlashcards(User user, Session session) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public List<Question> getPreparationQuestions(User user, Session session) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public int getLectureQuestionCount(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int getFlashcardCount(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int getPreparationQuestionCount(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int countLectureQuestionAnswers(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int countPreparationQuestionAnswers(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public void deleteAllLectureQuestionsWithAnswers(Session session) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void deleteAllFlashcardsWithAnswers(Session session) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void deleteAllPreparationQuestionsWithAnswers(Session session) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public List<String> getUnAnsweredLectureQuestionIds(Session session, User user) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public List<String> getUnAnsweredPreparationQuestionIds(Session session, User user) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public void deleteAllInterposedQuestions(Session session) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void publishAllQuestions(Session session, boolean publish) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void deleteAllQuestionsAnswers(Session session) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public int getLearningProgress(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int getMyLearningProgress(Session session, User user) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
 }
diff --git a/src/test/java/de/thm/arsnova/services/FeedbackServiceTest.java b/src/test/java/de/thm/arsnova/services/FeedbackServiceTest.java
index e96de49ee2e1a51b206a68e319cf8566f49f652f..06409e42b480b04fc1cf9118e84534722672967f 100644
--- a/src/test/java/de/thm/arsnova/services/FeedbackServiceTest.java
+++ b/src/test/java/de/thm/arsnova/services/FeedbackServiceTest.java
@@ -166,9 +166,6 @@ public class FeedbackServiceTest {
 	public static class TestUser extends User {
 		private static final long serialVersionUID = 1L;
 		
-		private String username;
-		private String type;
-
 		public TestUser(String username) {
 			super( new UsernamePasswordAuthenticationToken(username, "secret") );
 		}
diff --git a/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java b/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java
index a78e67a1749853f061c92849ccc78d53e41a2a21..96e81937abb951675eff7769f6301a30db4a638e 100644
--- a/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java
+++ b/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java
@@ -101,10 +101,4 @@ public class QuestionServiceTest {
 		
 		assertFalse(theQ.isRead());
 	}
-
-	@Test
-	public void testShouldNotThrowExceptionInMyAnsersCall() {
-		userService.setUserAuthenticated(true);
-		assertNotNull(questionService.getMyAnswers("12345678"));
-	}
 }
diff --git a/src/test/java/de/thm/arsnova/services/SessionServiceTest.java b/src/test/java/de/thm/arsnova/services/SessionServiceTest.java
index c6ede4f8dfd05792f6996ab9a81aed41f0cb3a35..06956f115a28b51d14b39d478183e94d3e23e14d 100644
--- a/src/test/java/de/thm/arsnova/services/SessionServiceTest.java
+++ b/src/test/java/de/thm/arsnova/services/SessionServiceTest.java
@@ -67,7 +67,6 @@ public class SessionServiceTest {
 	
 	@Test
 	public void testShouldGenerateSessionKeyword() {
-		System.out.println(sessionService.generateKeyword());
 		assertTrue(sessionService.generateKeyword().matches("^[0-9]{8}$"));
 	}
 
@@ -126,7 +125,7 @@ public class SessionServiceTest {
 			Question q2 = new Question();
 	
 			IDatabaseDao mockDatabase = mock(IDatabaseDao.class);
-			when(mockDatabase.getSkillQuestions(anyString())).thenReturn(Arrays.asList(q1, q2));
+			when(mockDatabase.getSkillQuestions(userService.getCurrentUser(), session)).thenReturn(Arrays.asList(q1, q2));
 			when(mockDatabase.getSession(anyString())).thenReturn(session);
 			ReflectionTestUtils.setField(getTargetObject(sessionService), "databaseDao", mockDatabase);
 	
diff --git a/src/test/resources/arsnova.properties.example b/src/test/resources/arsnova.properties.example
index f6b818d06c9a997d55c0026f526b61887ab6a94c..00c73a8d1f13c8447711d48b080be7cd480e78bb 100644
--- a/src/test/resources/arsnova.properties.example
+++ b/src/test/resources/arsnova.properties.example
@@ -21,9 +21,12 @@ couchdb.name=arsnova
 # minutes, after which the feedback is deleted
 feedback.cleanup=10
 
+# maximal filesize in bytes
+upload.filesize_b=1048576
+
 socketio.ip=0.0.0.0
 socketio.port=10443
 
 connector.uri=http://localhost:8080/connector-service
 connector.username=test
-connector.password=test
\ No newline at end of file
+connector.password=test
diff --git a/src/test/resources/test-socketioconfig.xml b/src/test/resources/test-socketioconfig.xml
new file mode 100644
index 0000000000000000000000000000000000000000..844695c967c031e2b3900ce737c2ea0a5811944c
--- /dev/null
+++ b/src/test/resources/test-socketioconfig.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
+
+	<bean id="socketServer" class="de.thm.arsnova.socket.ARSnovaSocketIOServer"
+		init-method="startServer" destroy-method="stopServer" scope="singleton"
+		p:portNumber="11443" p:hostIp="${socketio.ip}" p:useSSL="${security.ssl}" p:keystore="${security.keystore}"
+		p:storepass="${security.storepass}" />
+</beans>