diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 0c174c7a926a665afd13d79f6400c4d924f4bd62..0000000000000000000000000000000000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "src/test/db"]
-	path = src/test/db
-	url = ssh://git@lab01560.intranet.chuv:2222/mip-portal/portal-db.git
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 1d24297ed36ea5281519e7b6e6a33b628c37d4df..0000000000000000000000000000000000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-# This Dockerfile encapsulate the MIP portal backend application for development purposes.
-# We use it to bootstrap the generation of the Hibernate mapping file and the application jar.
-
-FROM maven:3-jdk-8
-
-COPY ./src/docker/init/build-in-docker.sh /build-in-docker.sh
-
-CMD mkdir /opt/portal/
-
-VOLUME /opt/portal/
-
-WORKDIR /opt/portal/
-
-CMD ["/build-in-docker.sh"]
diff --git a/README.md b/README.md
index ce9c373c3c20a5b07e8620e7c0d2079dad7ca5f3..7656211a77aeb1eca4651d816ddf99192ed70d26 100644
--- a/README.md
+++ b/README.md
@@ -1,32 +1,17 @@
 ## Introduction
 
-This is the MIP implementation.
+This is the MIP backend.
 
 ## Usage
 
-Build the project with `./build` and run it with `./run`.
+* Build and run the project (including clean target): `./go.sh`
+* Build the project (including clean target): `./build.sh`
+* Run the project: `./run.sh`
+* Show live logs: `./log.sh` (CTRL+C to quit)
+* Stop and remove the running container: `./halt.sh`
+* Clean Maven cache, etc: `./clean.sh`
 
-## API Documentation using Swagger (Springfox)
+## Generate PDF API documentation on build
 
-The API documentation is available at `<BASE URL>/swagger-ui.html`. A JSON version is available at `<BASE URL>/v2/api-docs`
-
-## TODO
-
-* Implement SoapUI tests;
-* Clean code (both back-end front-end);
-* Sync with original Swagger description;
-* Externalize configuration (DB parameters, security enabled/disabled, ...);
-* Make user tests with multiple users;
-* Fix bugs.
-
-## BUGS
-
-* Export PDF does not work;
-
-### Maintenance
-
-* To keep an updated API documentation, the developers should keep synchronized both the auto-generated swagger file (from Java annotations) with the hand written one. You can follow this method to get a YAML description from the Java-annotated code:
-  * Add annotations to the Java code;
-  * Get JSON from `<BASE URL>/v2/api-docs`;
-  * Convert JSON to YAML on [http://jsontoyaml.com](http://jsontoyaml.com).
-  
\ No newline at end of file
+Uncomment the following line in src/docker/build/build-in-docker.sh :
+`mvn swagger2markup:convertSwagger2markup asciidoctor:process-asciidoc`
diff --git a/after-git-clone.sh b/after-git-clone.sh
deleted file mode 100755
index 423f04205dc182d5ab78d9e1e32bc8a3c0f88635..0000000000000000000000000000000000000000
--- a/after-git-clone.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-git submodule update --init
diff --git a/after-update.sh b/after-update.sh
deleted file mode 100755
index c70bd5d6716f6d10e03a1d446958b58ea2ee7a6b..0000000000000000000000000000000000000000
--- a/after-update.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-git submodule sync
-git submodule update --init
-git submodule foreach git pull origin master
diff --git a/build.sh b/build.sh
index 748d7fb5c3af2af5940511f0c5df9206f5f57c4f..e29e8d77076c421f9f0a98bc49d4d61b9454c2bd 100755
--- a/build.sh
+++ b/build.sh
@@ -1,13 +1,5 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
 
-if groups $USER | grep &>/dev/null '\bdocker\b'; then
-  DOCKER_COMPOSE="docker-compose"
-else
-  DOCKER_COMPOSE="sudo docker-compose"
-fi
-
-# TODO: Cannot clean otherwise the build fails because of Hibernate schema generation
-mvn package
-cp target/mip.jar src/docker/build/
-
-$DOCKER_COMPOSE build
+./halt.sh
+docker-compose -f ./docker-compose_build.yml build
+docker-compose -f ./docker-compose_build.yml run --rm backend_build
diff --git a/clean.sh b/clean.sh
new file mode 100755
index 0000000000000000000000000000000000000000..55a2f1aee44299fce253f3d085abf053854d0298
--- /dev/null
+++ b/clean.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+./halt.sh
+sudo rm -r ./.m2/
+sudo rm -r ./target/
+sudo rm -r ./pgdata/
\ No newline at end of file
diff --git a/config/application.yml b/config/application.yml
index 6f752d822bf63ecaf3bfb238dd920f177f05e2f3..05b35323155e50d61963cbe6b4480f53a40c73e2 100644
--- a/config/application.yml
+++ b/config/application.yml
@@ -1,9 +1,17 @@
-# Configuration for the portal running inside a Docker container for development
+# Configuration for the portal running inside a Docker container
 
-connection:
-  url: "jdbc:postgresql://portaldb:5432/postgres"
-  username: "postgres"
-  password: "test"
+spring:
+  datasource:
+    url: jdbc:postgresql://db:5432/postgres
+    username: postgres
+    password: pass
+    driver-class-name: org.postgresql.Driver
+  jpa:
+    hibernate:
+      dialect: org.hibernate.dialect.PostgreSQL9Dialect
+  resources:
+      chain:
+        enabled: true
 
 security:
   enabled: false
@@ -17,9 +25,6 @@ hbp:
     tokenName: oauth_token
     authenticationScheme: query
     clientAuthenticationScheme: form
-    # use-current-uri: false  # For both production and HBPS1 deployments
-    # pre-established-redirect-uri: https://mip.humanbrainproject.eu/services/login/hbp  # For production deployment
-    # pre-established-redirect-uri: http://hbps1.chuv.ch/services/login/hbp  # For HBPS1 deployment
   resource:
     userInfoUri: https://services.humanbrainproject.eu/oidc/userinfo
 
@@ -27,11 +32,6 @@ logging:
   level:
     org.springframework.security: DEBUG
 
-spring:
-  resources:
-    chain:
-      enabled: true
-
 server:
   contextPath: /services
   port: 8080
@@ -45,3 +45,6 @@ workflow:
   miningMipUrl: http://dockerhost:8087/mining
   miningExaremeUrl: http://hbps2.chuv.ch:9090/mining/query
 
+frontend:
+  redirect:
+    url: http://frontend/home
diff --git a/docker-compose.init.yml b/docker-compose.init.yml
deleted file mode 100644
index e5828d70bd0765e4ea7b22decc6685d3a6551456..0000000000000000000000000000000000000000
--- a/docker-compose.init.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-# Build the application and regenerate the Hibernate mapping
-
-portaldb:
-  image: postgres:9.5.3
-  container_name: portaldb
-  ports:
-    - "55432:5432"
-  volumes:
-    - ./src/test/db/sql:/docker-entrypoint-initdb.d/
-  environment:
-    POSTGRES_PASSWORD: test
-
-portal-backend:
-  build: .
-  volumes:
-    - ./:/portal/
-    - ./.m2/:/root/.m2/
-  links:
-    - portaldb
-  ports:
-    - "8080:8080"
diff --git a/docker-compose.yml b/docker-compose.yml
index ad6a91c77c771a297d969a83a5cd6f464c14735e..ca9461e4de83255ad5d6b13d3ecb1698e79bcd78 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,20 +1,26 @@
+version: '2'
 
-portaldb:
-  image: postgres:9.5.3
-  container_name: portaldb
-  ports:
-    - "55432:5432"
-  volumes:
-    - ./src/test/db/sql:/docker-entrypoint-initdb.d/
-  environment:
-    POSTGRES_PASSWORD: test
-
-portal-backend:
-  build: ./src/docker/build
-  volumes:
-    - ./src/test/docker/:/opt/portal/config/
-    - ./target/:/opt/portal/lib/
-  links:
-    - portaldb
-  ports:
-    - "8080:8080"
+services:
+  backend:
+    container_name: backend
+    build:
+      context: .
+      dockerfile: ./src/docker/run/Dockerfile
+    depends_on:
+      - "db"
+    ports:
+      - "8080:8080"
+    links:
+      - "db"
+    volumes:
+      - ./config:/config
+  db:
+    container_name: db
+    image: postgres:9.5.3
+    ports:
+      - "5432:5432"
+    volumes:
+      - ./pgdata:/var/lib/postgresql/data/pgdata
+    environment:
+      POSTGRES_USER: postgres
+      PGDATA: /var/lib/postgresql/data/pgdata
diff --git a/docker-compose_build.yml b/docker-compose_build.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b29bf59ecd0f6a068269bcc0fed3f0498bb9505d
--- /dev/null
+++ b/docker-compose_build.yml
@@ -0,0 +1,11 @@
+version: '2'
+
+services:
+  backend_build:
+    container_name: backend_build
+    build: ./src/docker/build/
+    volumes:
+      - ./:/opt/portal/
+      - .m2:/root/.m2/
+    ports:
+      - "8080:8080"
diff --git a/go.sh b/go.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2d044fe98b7c6eab6d5f6b38794762d9659f5e56
--- /dev/null
+++ b/go.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+./build.sh
+./run.sh
diff --git a/halt.sh b/halt.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7b9c9e76afdaad93310047eeef58c64326caffb9
--- /dev/null
+++ b/halt.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+docker-compose kill
+docker-compose rm -f
diff --git a/log.sh b/log.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f1cd4924d74ad499aef9188c070880d2be956cf2
--- /dev/null
+++ b/log.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+docker-compose logs -f backend
diff --git a/pom.xml b/pom.xml
index a9cb39f28e7cf809c411420afed6756ec9965b9e..2726b792b10f1c0eb89bde75ea2b578390aa8f4b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
 
     <groupId>org.hbp.mip</groupId>
     <artifactId>backend-services</artifactId>
-    <version>0.1.0</version>
+    <version>DOCKER_BUILD</version>
     <packaging>jar</packaging>
 
     <name>backend-services</name>
@@ -15,63 +15,46 @@
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>1.3.2.RELEASE</version>
-        <relativePath /> <!-- lookup parent from repository -->
+        <relativePath />
     </parent>
-    <profiles>
-        <profile>
-            <id>prod</id>
-            <properties>
-                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-                <java.version>1.8</java.version>
-                <connection.driver_class>org.postgresql.Driver</connection.driver_class>
-                <connection.url>jdbc:postgresql://hbpmdw1.chuv.ch:31432/portal</connection.url>
-                <connection.username>portal</connection.username>
-                <connection.password>iaezXODVLb1e70I</connection.password>
-                <hibernate.dialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernate.dialect>
-                <schema.deploy>false</schema.deploy>
-                <frontend.redirect>https://mip.humanbrainproject.eu/home</frontend.redirect>
-                <flyway.url>${connection.url}</flyway.url>
-                <flyway.user>${connection.username}</flyway.user>
-                <flyway.password>${connection.password}</flyway.password>
-            </properties>
-        </profile>
-        <profile>
-            <id>dev</id>
-            <properties>
-                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-                <java.version>1.8</java.version>
-                <connection.driver_class>org.postgresql.Driver</connection.driver_class>
-                <connection.url>jdbc:postgresql://portaldb:5432/postgres</connection.url>
-                <connection.username>postgres</connection.username>
-                <connection.password>test</connection.password>
-                <hibernate.dialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernate.dialect>
-                <schema.deploy>false</schema.deploy>
-                <frontend.redirect>http://frontend/home</frontend.redirect>
-                <flyway.url>${connection.url}</flyway.url>
-                <flyway.user>${connection.username}</flyway.user>
-                <flyway.password>${connection.password}</flyway.password>
-            </properties>
-        </profile>
-        <profile>
-            <id>hbps1</id>
-            <properties>
-                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-                <java.version>1.8</java.version>
-                <connection.driver_class>org.postgresql.Driver</connection.driver_class>
-                <connection.url>jdbc:postgresql://portaldb:5432/postgres</connection.url>
-                <connection.username>postgres</connection.username>
-                <connection.password>test</connection.password>
-                <hibernate.dialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernate.dialect>
-                <schema.deploy>false</schema.deploy>
-                <frontend.redirect>http://hbps1.chuv.ch/home</frontend.redirect>
-                <flyway.url>${connection.url}</flyway.url>
-                <flyway.user>${connection.username}</flyway.user>
-                <flyway.password>${connection.password}</flyway.password>
-            </properties>
-        </profile>
-    </profiles>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <sonar.host.url>http://dockerhost:9000</sonar.host.url>
+        <sonar.projectName>MIP Backend</sonar.projectName>
+        <sonar.sources>src/main/java/</sonar.sources>
+        <java.version>1.8</java.version>
+        <asciidoctor.maven.plugin.version>1.5.3</asciidoctor.maven.plugin.version>
+        <asciidoctorj.pdf.version>1.5.0-alpha.11</asciidoctorj.pdf.version>
+        <asciidoctorj.version>1.5.4</asciidoctorj.version>
+        <spring-data-commons.version>1.12.2.RELEASE</spring-data-commons.version>
+        <angularjs.version>1.4.3</angularjs.version>
+        <jquery.version>2.1.1</jquery.version>
+        <bootstrap.version>3.2.0</bootstrap.version>
+        <hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
+        <hibernate-core.version>4.3.8.Final</hibernate-core.version>
+        <hibernate-entitymanager.version>4.3.8.Final</hibernate-entitymanager.version>
+        <h2.version>1.4.187</h2.version>
+        <postgresql.version>9.4-1205-jdbc42</postgresql.version>
+        <springfox-swagger2.version>2.3.1</springfox-swagger2.version>
+        <springfox-swagger-ui.version>2.3.1</springfox-swagger-ui.version>
+        <gson.version>2.5</gson.version>
+        <slugify.version>2.1.4</slugify.version>
+        <spring-data-jpa.version>1.10.2.RELEASE</spring-data-jpa.version>
+        <maven-resources-plugin.version>2.3</maven-resources-plugin.version>
+        <sonar-maven-plugin.version>3.0.1</sonar-maven-plugin.version>
+        <swagger2markup-maven-plugin.version>1.0.0</swagger2markup-maven-plugin.version>
+        <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
+        <hibernate4-maven-plugin.version>1.1.0</hibernate4-maven-plugin.version>
+        <flyway-core.version>4.0.3</flyway-core.version>
+    </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons</artifactId>
+            <version>${spring-data-commons.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
@@ -95,17 +78,17 @@
         <dependency>
             <groupId>org.webjars</groupId>
             <artifactId>angularjs</artifactId>
-            <version>1.4.3</version>
+            <version>${angularjs.version}</version>
         </dependency>
         <dependency>
             <groupId>org.webjars</groupId>
             <artifactId>jquery</artifactId>
-            <version>2.1.1</version>
+            <version>${jquery.version}</version>
         </dependency>
         <dependency>
             <groupId>org.webjars</groupId>
             <artifactId>bootstrap</artifactId>
-            <version>3.2.0</version>
+            <version>${bootstrap.version}</version>
         </dependency>
         <dependency>
             <groupId>org.webjars</groupId>
@@ -119,47 +102,64 @@
         <dependency>
             <groupId>org.hibernate.javax.persistence</groupId>
             <artifactId>hibernate-jpa-2.1-api</artifactId>
-            <version>1.0.0.Final</version>
+            <version>${hibernate-jpa-2.1-api.version}</version>
         </dependency>
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
-            <version>4.3.8.Final</version>
+            <version>${hibernate-core.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <version>${hibernate-entitymanager.version}</version>
         </dependency>
         <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
-            <version>1.4.187</version>
+            <version>${h2.version}</version>
         </dependency>
         <dependency>
             <groupId>org.postgresql</groupId>
             <artifactId>postgresql</artifactId>
-            <version>9.4-1205-jdbc42</version>
+            <version>${postgresql.version}</version>
         </dependency>
         <dependency>
             <groupId>io.springfox</groupId>
             <artifactId>springfox-swagger2</artifactId>
-            <version>2.3.1</version>
+            <version>${springfox-swagger2.version}</version>
         </dependency>
         <dependency>
             <groupId>io.springfox</groupId>
             <artifactId>springfox-swagger-ui</artifactId>
-            <version>2.3.1</version>
+            <version>${springfox-swagger-ui.version}</version>
         </dependency>
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
-            <version>2.5</version>
+            <version>${gson.version}</version>
         </dependency>
         <dependency>
             <groupId>com.github.slugify</groupId>
             <artifactId>slugify</artifactId>
-            <version>2.1.4</version>
+            <version>${slugify.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-jpa</artifactId>
+            <version>${spring-data-jpa.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-dbcp</groupId>
+            <artifactId>commons-dbcp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-core</artifactId>
+            <version>${flyway-core.version}</version>
         </dependency>
     </dependencies>
 
-
-
     <pluginRepositories>
         <pluginRepository>
             <id>jcenter-snapshots</id>
@@ -176,15 +176,6 @@
         </pluginRepository>
     </pluginRepositories>
 
-    <properties>
-        <asciidoctor.maven.plugin.version>1.5.3</asciidoctor.maven.plugin.version>
-        <asciidoctorj.pdf.version>1.5.0-alpha.11</asciidoctorj.pdf.version>
-        <asciidoctorj.version>1.5.4</asciidoctorj.version>
-        <sonar.host.url>http://dockerhost:9000</sonar.host.url>
-        <sonar.projectName>MIP Backend</sonar.projectName>
-        <sonar.sources>src/main/java/</sonar.sources>
-    </properties>
-
     <build>
         <resources>
             <resource>
@@ -193,6 +184,7 @@
                     <include>**/*.xml</include>
                     <include>**/*.json</include>
                     <include>**/*.csv</include>
+                    <include>**/*.sql</include>
                 </includes>
                 <filtering>true</filtering>
             </resource>
@@ -202,7 +194,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-resources-plugin</artifactId>
-                <version>2.3</version>
+                <version>${maven-resources-plugin.version}</version>
                 <configuration>
                     <!-- specify UTF-8, ISO-8859-1 or any other file encoding -->
                     <encoding>UTF-8</encoding>
@@ -215,7 +207,7 @@
             <plugin>
                 <groupId>de.juplo</groupId>
                 <artifactId>hibernate4-maven-plugin</artifactId>
-                <version>1.1.0</version>
+                <version>${hibernate4-maven-plugin.version}</version>
                 <executions>
                     <execution>
                         <phase>compile</phase>
@@ -224,21 +216,16 @@
             </plugin>
             <plugin>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.1</version>
+                <version>${maven-compiler-plugin.version}</version>
                 <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.flywaydb</groupId>
-                <artifactId>flyway-maven-plugin</artifactId>
-                <version>4.0.1</version>
-            </plugin>
             <plugin>
                 <groupId>io.github.swagger2markup</groupId>
                 <artifactId>swagger2markup-maven-plugin</artifactId>
-                <version>1.0.0</version>
+                <version>${swagger2markup-maven-plugin.version}</version>
                 <configuration>
                     <swaggerInput>http://localhost:8080/services/v2/api-docs</swaggerInput>
                     <outputFile>${project.build.directory}/asciidoc/api</outputFile>
@@ -270,7 +257,7 @@
             <plugin>
                 <groupId>org.sonarsource.scanner.maven</groupId>
                 <artifactId>sonar-maven-plugin</artifactId>
-                <version>3.0.1</version>
+                <version>${sonar-maven-plugin.version}</version>
             </plugin>
         </plugins>
     </build>
diff --git a/run.sh b/run.sh
index 3483bbcfcb1c7446b56537d6792375c48896efe9..5d9339d5dd5ee1458a5d47d420904917ac0cef13 100755
--- a/run.sh
+++ b/run.sh
@@ -1,20 +1,12 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
 
-# Run the backend in a Docker container and start the database.
-# The current project is compiler inside the Docker container
+docker-compose build
+docker-compose up -d db
 
-if groups $USER | grep &>/dev/null '\bdocker\b'; then
-  DOCKER_COMPOSE="docker-compose"
-else
-  DOCKER_COMPOSE="sudo docker-compose"
-fi
+echo 'Waiting for database to be ready...'
+until [ $(docker-compose exec db psql -U postgres -c "\q" | wc -l) -eq 0 ]; do
+    printf '.'
+    sleep 1
+done
 
-# Create a symlink to the local Maven repository
-[ -L .m2 ] || ln -s -t . ~/.m2
-
-$DOCKER_COMPOSE --file=docker-compose.init.yml --project-name=portal-backend-init up
-
-echo "Need to set the current user as owner of the files generated in target directory..."
-sudo chown -R $USER:$USER ./target
-
-echo "Done"
+docker-compose up -d backend
diff --git a/src/docker/build/.gitignore b/src/docker/build/.gitignore
deleted file mode 100644
index d392f0e82c4ac6dd2e7bb17eb9253e1b30d07105..0000000000000000000000000000000000000000
--- a/src/docker/build/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.jar
diff --git a/src/docker/build/Dockerfile b/src/docker/build/Dockerfile
index 1369edf76009678d08db82e5e5ce87ef7b829f85..b4318d788f65cf01d672e59aab38c69b6e4aa17f 100644
--- a/src/docker/build/Dockerfile
+++ b/src/docker/build/Dockerfile
@@ -1,19 +1,8 @@
-# This Dockerfile encapsulate the MIP portal  backend application for development purposes.
-
 FROM maven:3-jdk-8
 
-RUN apt-get update && apt-get install -y wget
-RUN wget https://github.com/jwilder/dockerize/releases/download/v0.2.0/dockerize-linux-amd64-v0.2.0.tar.gz
-RUN tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.2.0.tar.gz
-
-COPY mip.sh /opt/portal/
-COPY mip.jar /opt/portal/lib/
-RUN chmod +x /opt/portal/mip.sh
-EXPOSE 8080
-
-VOLUME /opt/portal/config/
-VOLUME /opt/portal/lib/
+COPY ./build-in-docker.sh /build-in-docker.sh
 
+VOLUME /opt/portal/
 WORKDIR /opt/portal/
 
-CMD ["/usr/local/bin/dockerize", "-timeout", "240s", "-wait", "tcp://portaldb:5432", "/opt/portal/mip.sh"]
+CMD ["bash", "/build-in-docker.sh"]
diff --git a/src/docker/build/build-in-docker.sh b/src/docker/build/build-in-docker.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7b77f1e6688bd0b49f0ea3462cdf75ca86c79be0
--- /dev/null
+++ b/src/docker/build/build-in-docker.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+echo 'Removing old target folder...'
+rm -r target/
+
+echo 'Packaging...'
+mvn package
diff --git a/src/docker/build/mip.sh b/src/docker/build/mip.sh
deleted file mode 100644
index cfae68474c42a1e66b80edb0ea849911ddd8eef4..0000000000000000000000000000000000000000
--- a/src/docker/build/mip.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env bash
-
-/usr/bin/java -DconfigFile=/opt/portal/config/application.yml -jar /opt/portal/lib/mip.jar
diff --git a/src/docker/init/build-in-docker.sh b/src/docker/init/build-in-docker.sh
deleted file mode 100644
index aff4c2e6c8eaabb623c62b16339b0dde606ead82..0000000000000000000000000000000000000000
--- a/src/docker/init/build-in-docker.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh -e
-
-echo ">>> Building inside Docker"
-cd /portal
-
-mvn package
-
-echo ">>> Press Ctrl+C to stop, build is complete"
diff --git a/src/docker/run/Dockerfile b/src/docker/run/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b3a112a35d01fdb2bd1644ea5e21e79154c2c365
--- /dev/null
+++ b/src/docker/run/Dockerfile
@@ -0,0 +1,6 @@
+FROM frolvlad/alpine-oraclejdk8:slim
+
+VOLUME /config
+
+COPY ./target/backend-services-DOCKER_BUILD.jar backend.jar
+CMD ["java", "-jar", "backend.jar"]
diff --git a/src/main/java/org/hbp/mip/MIPApplication.java b/src/main/java/org/hbp/mip/MIPApplication.java
index f6d5aeb3d156eeac8afd31340c8bf1b190065e61..4814eb9e11f657e89133218e9d21622ad215eaf8 100644
--- a/src/main/java/org/hbp/mip/MIPApplication.java
+++ b/src/main/java/org/hbp/mip/MIPApplication.java
@@ -5,275 +5,14 @@
 
 package org.hbp.mip;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiParam;
-import org.apache.log4j.Logger;
-import org.hbp.mip.model.User;
-import org.hbp.mip.utils.CORSFilter;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Session;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
-import org.springframework.boot.context.embedded.FilterRegistrationBean;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportResource;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.client.OAuth2ClientContext;
-import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
-import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
-import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
-import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
-import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
-import org.springframework.security.oauth2.provider.OAuth2Authentication;
-import org.springframework.security.web.access.channel.ChannelProcessingFilter;
-import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
-import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
-import org.springframework.security.web.csrf.CsrfFilter;
-import org.springframework.security.web.csrf.CsrfToken;
-import org.springframework.security.web.csrf.CsrfTokenRepository;
-import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.filter.OncePerRequestFilter;
-import org.springframework.web.util.WebUtils;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger.web.UiConfiguration;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.security.Principal;
 
 @SpringBootApplication
-@Configuration
-@ImportResource("classpath:spring/application-context.xml")
-@RestController
-@EnableOAuth2Client
-@EnableSwagger2
-@Api(value = "/", description = "MIP API")
-public class MIPApplication extends WebSecurityConfigurerAdapter {
-
-    private static final Logger LOGGER = Logger.getLogger(MIPApplication.class);
-
-    @Autowired
-    OAuth2ClientContext oauth2ClientContext;
-
-    @Autowired
-    HttpSessionCsrfTokenRepository httpSessionCsrfTokenRepository;
-
-    @Autowired
-    OAuth2ClientAuthenticationProcessingFilter hbpFilter;
-
+public class MIPApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(MIPApplication.class, args);
     }
 
-    public String getUserInfos() {
-        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
-        Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();
-        return userAuthentication.getDetails().toString();
-    }
-
-    /**
-     * returns the user for the current session.
-     *
-     * the "synchronized" keyword is there to avoid a bug that the transaction is supposed to protect me from.
-     * To test if your solution to removing it works, do the following:
-     * - clean DB from scratch
-     * - restart DB and backend (no session or anything like that)
-     * - log in using the front end
-     * - check you have no 500 error in the network logs.
-     * @return
-     */
-    public synchronized User getUser() {
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        User user = new User(getUserInfos());
-        try {
-            session.beginTransaction();
-            Boolean agreeNDA = (Boolean) session
-                    .createQuery("SELECT agreeNDA FROM User WHERE username= :username")
-                    .setString("username", user.getUsername())
-                    .uniqueResult();
-            user.setAgreeNDA(agreeNDA);
-            session.merge(user);
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return user;
-    }
-
-    @Bean
-    public Docket documentation() {
-        return new Docket(DocumentationType.SWAGGER_2)
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("org.hbp.mip.controllers"))
-                .build()
-                .pathMapping("/")
-                .apiInfo(metadata());
-    }
-
-    @Bean
-    public UiConfiguration uiConfig() {
-        return UiConfiguration.DEFAULT;
-    }
-
-    private ApiInfo metadata() {
-        return new ApiInfoBuilder()
-                .title("Medical Informatics Platform API")
-                .description("Serve the MIP Frontend")
-                .version("1.0")
-                .contact("mirco.nasuti@chuv.ch")
-                .build();
-    }
-
-    @RequestMapping(path = "/user", method = RequestMethod.GET)
-    public Principal user(Principal principal, HttpServletResponse response) {
-        ObjectMapper mapper = new ObjectMapper();
-
-        try {
-            String userJSON = mapper.writeValueAsString(getUser());
-            Cookie cookie = new Cookie("user", URLEncoder.encode(userJSON, "UTF-8"));
-            cookie.setSecure(true);
-            cookie.setPath("/");
-            response.addCookie(cookie);
-        } catch (JsonProcessingException | UnsupportedEncodingException e) {
-            LOGGER.trace(e);
-        }
-        return principal;
-    }
-
-    @RequestMapping(path = "/user", method = RequestMethod.POST)
-    public ResponseEntity<Void> postUser(@ApiParam(value = "Has the user agreed on the NDA") @RequestParam(value = "agreeNDA", required = true) Boolean agreeNDA) {
-        String username = getUser().getUsername();
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try {
-            session.beginTransaction();
-            User user = (User) session
-                    .createQuery("from User where username= :username")
-                    .setString("username", username)
-                    .uniqueResult();
-            if (user != null) {
-                user.setAgreeNDA(agreeNDA);
-                session.update(user);
-            }
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-
-        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-    }
-
-    @Override
-    protected void configure(HttpSecurity http) throws Exception {
-        // @formatter:off
-        http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
-        http.antMatcher("/**")
-                .authorizeRequests()
-                .antMatchers("/", "/frontend/**", "/webjars/**", "/v2/api-docs").permitAll()
-                .anyRequest().authenticated()
-                .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint("/login/hbp"))
-                .and().logout().logoutSuccessUrl("/login/hbp").permitAll()
-                .and().logout().logoutUrl("/logout").permitAll()
-                .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
-                .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
-                .addFilterBefore(hbpFilter, BasicAuthenticationFilter.class);
-    }
-
-    @Bean
-    public FilterRegistrationBean oauth2ClientFilterRegistration(
-            OAuth2ClientContextFilter filter) {
-        FilterRegistrationBean registration = new FilterRegistrationBean();
-        registration.setFilter(filter);
-        registration.setOrder(-100);
-        return registration;
-    }
-
-    @Bean(name="hbp")
-    @ConfigurationProperties("hbp.client")
-    OAuth2ProtectedResourceDetails hbp() {
-        return new AuthorizationCodeResourceDetails();
-    }
-
-    @Bean(name="hbpResource")
-    @ConfigurationProperties("hbp.resource")
-    ResourceServerProperties hbpResource() {
-        return new ResourceServerProperties();
-    }
-
-    private Filter csrfHeaderFilter() {
-        return new OncePerRequestFilter() {
-            @Override
-            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
-                                            FilterChain filterChain) throws ServletException, IOException {
-                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
-                if (csrf != null) {
-                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
-                    String token = csrf.getToken();
-                    if (cookie == null || token != null && !token.equals(cookie.getValue())) {
-                        cookie = new Cookie("XSRF-TOKEN", token);
-                        cookie.setPath("/");
-                        response.addCookie(cookie);
-                    }
-                }
-                filterChain.doFilter(request, response);
-            }
-        };
-    }
-
-    private CsrfTokenRepository csrfTokenRepository() {
-        return httpSessionCsrfTokenRepository;
-    }
-
-}
-
-class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
-
-    public CustomLoginUrlAuthenticationEntryPoint(String url) {
-        super(url);
-    }
-
-    @Override
-    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
-        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-    }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/hbp/mip/configuration/PersistenceConfiguration.java b/src/main/java/org/hbp/mip/configuration/PersistenceConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..35ce472e97215226e3bc4bd26e647d22d3498b2b
--- /dev/null
+++ b/src/main/java/org/hbp/mip/configuration/PersistenceConfiguration.java
@@ -0,0 +1,52 @@
+package org.hbp.mip.configuration;
+
+import org.flywaydb.core.Flyway;
+import org.hbp.mip.utils.CSVUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.orm.jpa.EntityScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+
+import javax.sql.DataSource;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+@Configuration
+@EnableJpaRepositories(value = "org.hbp.mip.repositories")
+@EntityScan(basePackages = "org.hbp.mip.model")
+public class PersistenceConfiguration {
+
+    @Autowired
+    DataSource dataSource;
+
+    @Bean
+    public CSVUtil csvUtil() {
+        return new CSVUtil();
+    }
+
+    @Bean
+    @DependsOn("flyway")
+    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+        em.setDataSource(dataSource);
+        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+        em.setJpaVendorAdapter(vendorAdapter);
+        return em;
+    }
+
+    @Bean(initMethod = "migrate")
+    public Flyway flyway() {
+        Flyway flyway = new Flyway();
+        flyway.setBaselineOnMigrate(true);
+        flyway.setDataSource(dataSource);
+        return flyway;
+    }
+
+}
diff --git a/src/main/java/org/hbp/mip/configuration/SecurityConfiguration.java b/src/main/java/org/hbp/mip/configuration/SecurityConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..79b437fed3218f9337b3b0486357244c8c5a861f
--- /dev/null
+++ b/src/main/java/org/hbp/mip/configuration/SecurityConfiguration.java
@@ -0,0 +1,212 @@
+package org.hbp.mip.configuration;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.swagger.annotations.ApiParam;
+import org.apache.log4j.Logger;
+import org.hbp.mip.controllers.ArticlesApi;
+import org.hbp.mip.model.User;
+import org.hbp.mip.repositories.UserRepository;
+import org.hbp.mip.utils.CORSFilter;
+import org.hbp.mip.utils.CustomLoginUrlAuthenticationEntryPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
+import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
+import org.springframework.boot.context.embedded.FilterRegistrationBean;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.client.OAuth2ClientContext;
+import org.springframework.security.oauth2.client.OAuth2RestTemplate;
+import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
+import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
+import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
+import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.web.access.channel.ChannelProcessingFilter;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+import org.springframework.security.web.csrf.CsrfFilter;
+import org.springframework.security.web.csrf.CsrfToken;
+import org.springframework.security.web.csrf.CsrfTokenRepository;
+import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.WebUtils;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.Principal;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+@Configuration
+@EnableOAuth2Client
+@RestController
+public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+    private static final Logger LOGGER = Logger.getLogger(ArticlesApi.class);
+
+    @Autowired
+    OAuth2ClientContext oauth2ClientContext;
+
+    @Autowired
+    UserRepository userRepository;
+
+    @Value("#{'${hbp.client.pre-established-redirect-uri:/login/hbp}'}")
+    String loginUrl;
+
+    @Value("#{'${hbp.client.logout-uri:/logout}'}")
+    String logoutUrl;
+
+    @Value("#{'${frontend.redirect.url:http://frontend/home}'}")
+    String frontendRedirect;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        // @formatter:off
+        http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
+        http.antMatcher("/**")
+                .authorizeRequests()
+                .antMatchers("/", "/frontend/**", "/webjars/**", "/v2/api-docs").permitAll()
+                .anyRequest().authenticated()
+                .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
+                .and().logout().logoutSuccessUrl(loginUrl).permitAll()
+                .and().logout().logoutUrl(logoutUrl).permitAll()
+                .and().csrf().ignoringAntMatchers(logoutUrl).csrfTokenRepository(csrfTokenRepository())
+                .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
+                .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
+    }
+
+    private Filter ssoFilter() {
+        OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter(loginUrl);
+        OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
+        hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirect));
+        hbpFilter.setRestTemplate(hbpTemplate);
+        hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId()));
+        return hbpFilter;
+    }
+
+    @Bean
+    public FilterRegistrationBean oauth2ClientFilterRegistration(
+            OAuth2ClientContextFilter filter) {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(filter);
+        registration.setOrder(-100);
+        return registration;
+    }
+
+    @Bean(name="hbp")
+    @ConfigurationProperties("hbp.client")
+    OAuth2ProtectedResourceDetails hbp() {
+        return new AuthorizationCodeResourceDetails();
+    }
+
+    @Bean(name="hbpResource")
+    @ConfigurationProperties("hbp.resource")
+    ResourceServerProperties hbpResource() {
+        return new ResourceServerProperties();
+    }
+
+    private Filter csrfHeaderFilter() {
+        return new OncePerRequestFilter() {
+            @Override
+            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+                                            FilterChain filterChain) throws ServletException, IOException {
+                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
+                if (csrf != null) {
+                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
+                    String token = csrf.getToken();
+                    if (cookie == null || token != null && !token.equals(cookie.getValue())) {
+                        cookie = new Cookie("XSRF-TOKEN", token);
+                        cookie.setPath("/");
+                        response.addCookie(cookie);
+                    }
+                }
+                filterChain.doFilter(request, response);
+            }
+        };
+    }
+
+    private CsrfTokenRepository csrfTokenRepository() {
+        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
+        repository.setHeaderName("X-XSRF-TOKEN");
+        return repository;
+    }
+
+    public String getUserInfos() {
+        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
+        Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();
+        return userAuthentication.getDetails().toString();
+    }
+
+    /**
+     * returns the user for the current session.
+     * <p>
+     * the "synchronized" keyword is there to avoid a bug that the transaction is supposed to protect me from.
+     * To test if your solution to removing it works, do the following:
+     * - clean DB from scratch
+     * - restart DB and backend (no session or anything like that)
+     * - log in using the front end
+     * - check you have no 500 error in the network logs.
+     *
+     * @return
+     */
+    public synchronized User getUser() {
+        User user = new User(getUserInfos());
+        User foundUser = userRepository.findOne(user.getUsername());
+        if(foundUser != null)
+        {
+            user.setAgreeNDA(foundUser.getAgreeNDA());
+        }
+        userRepository.save(user);
+        return user;
+    }
+
+    @RequestMapping(path = "/user", method = RequestMethod.GET)
+    public Principal user(Principal principal, HttpServletResponse response) {
+        ObjectMapper mapper = new ObjectMapper();
+
+        try {
+            String userJSON = mapper.writeValueAsString(getUser());
+            Cookie cookie = new Cookie("user", URLEncoder.encode(userJSON, "UTF-8"));
+            cookie.setSecure(true);
+            cookie.setPath("/");
+            response.addCookie(cookie);
+        } catch (JsonProcessingException | UnsupportedEncodingException e) {
+            LOGGER.trace(e);
+        }
+        return principal;
+    }
+
+    @RequestMapping(path = "/user", method = RequestMethod.POST)
+    public ResponseEntity<Void> postUser(@ApiParam(value = "Has the user agreed on the NDA") @RequestParam(value = "agreeNDA", required = true) Boolean agreeNDA) {
+        User user = getUser();
+        if (user != null) {
+            user.setAgreeNDA(agreeNDA);
+            userRepository.save(user);
+        }
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+    }
+
+}
diff --git a/src/main/java/org/hbp/mip/configuration/WebConfiguration.java b/src/main/java/org/hbp/mip/configuration/WebConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..888fbd1e7e58c5725c60782c2c02aa220e3e33cc
--- /dev/null
+++ b/src/main/java/org/hbp/mip/configuration/WebConfiguration.java
@@ -0,0 +1,46 @@
+package org.hbp.mip.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.web.config.EnableSpringDataWebSupport;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger.web.UiConfiguration;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+@Configuration
+@EnableSwagger2
+@EnableSpringDataWebSupport
+public class WebConfiguration {
+
+    @Bean
+    public UiConfiguration uiConfig() {
+        return UiConfiguration.DEFAULT;
+    }
+
+    @Bean
+    public Docket documentation() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("org.hbp.mip.controllers"))
+                .build()
+                .pathMapping("/")
+                .apiInfo(metadata());
+    }
+
+    private ApiInfo metadata() {
+        return new ApiInfoBuilder()
+                .title("Medical Informatics Platform API")
+                .description("Serve the MIP Frontend")
+                .version("1.0")
+                .contact("mirco.nasuti@chuv.ch")
+                .build();
+    }
+}
diff --git a/src/main/java/org/hbp/mip/controllers/AppsApi.java b/src/main/java/org/hbp/mip/controllers/AppsApi.java
index b89ef31b4836ba1e52966ae8a002e341bdb13546..351a2efb069e6b23831857e461a2a7db6f16a1a2 100644
--- a/src/main/java/org/hbp/mip/controllers/AppsApi.java
+++ b/src/main/java/org/hbp/mip/controllers/AppsApi.java
@@ -6,14 +6,13 @@ package org.hbp.mip.controllers;
 
 import io.swagger.annotations.*;
 import org.apache.log4j.Logger;
-import org.hbp.mip.MIPApplication;
+import org.hbp.mip.configuration.SecurityConfiguration;
 import org.hbp.mip.model.App;
 import org.hbp.mip.model.User;
 import org.hbp.mip.model.Vote;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.NonUniqueObjectException;
-import org.hibernate.Query;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.AppRepository;
+import org.hbp.mip.repositories.UserRepository;
+import org.hbp.mip.repositories.VoteRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -22,9 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.validation.ConstraintViolationException;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.Iterator;
 
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 
@@ -36,31 +33,23 @@ public class AppsApi {
     private static final Logger LOGGER = Logger.getLogger(AppsApi.class);
 
     @Autowired
-    MIPApplication mipApplication;
+    SecurityConfiguration securityConfiguration;
+
+    @Autowired
+    AppRepository appRepository;
+
+    @Autowired
+    VoteRepository voteRepository;
+
+    @Autowired
+    UserRepository userRepository;
 
     @ApiOperation(value = "Get apps", response = App.class, responseContainer = "List")
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<List> getApps(
+    public ResponseEntity<Iterable> getApps(
     ) {
-        List apps = new LinkedList<>();
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try {
-            session.beginTransaction();
-            Query query = session.createQuery("FROM App");
-            apps = query.list();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(apps);
+        return ResponseEntity.ok(appRepository.findAll());
     }
 
     @ApiOperation(value = "Post a vote")
@@ -70,69 +59,26 @@ public class AppsApi {
             @ApiParam(value = "id", required = true) @PathVariable("id") Integer id,
             @ApiParam(value = "value", required = true) @PathVariable("value") Integer value
     ) {
+        User user = userRepository.findOne(securityConfiguration.getUser().getUsername());
+        App app = appRepository.findOne(id);
+        Vote vote;
 
-        User user = mipApplication.getUser();
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try {
-            session.beginTransaction();
-
-            Vote vote = (Vote) session.createQuery("" +
-                    "SELECT v FROM Vote v, User u, App a " +
-                    "WHERE u=v.user " +
-                    "AND a=v.app " +
-                    "AND u.username= :username " +
-                    "AND a.id= :app_id")
-                    .setString("username", user.getUsername())
-                    .setLong("app_id", id)
-                    .uniqueResult();
-            App app = (App) session.createQuery("FROM App where id= :id").setLong("id", id).uniqueResult();
-
-            if (vote != null) {
-                vote.setValue(value);
-
-                session.update(vote);
-                session.getTransaction().commit();
-                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-            }
-            else
-            {
-                vote = new Vote();
-                vote.setUser(user);
-                vote.setValue(value);
-                vote.setApp(app);
-
-                session.save(vote);
-                session.getTransaction().commit();
-                return new ResponseEntity<>(HttpStatus.CREATED);
-            }
-        }
-        catch (ConstraintViolationException cve)
-        {
-            LOGGER.trace(cve);
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-            }
-            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
-        }
-        catch (NonUniqueObjectException nuoe)
+        Iterator<Vote> voteIter = voteRepository.findByUserAndApp(user, app).iterator();
+        if(voteIter.hasNext())
         {
-            LOGGER.trace(nuoe);
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-            }
-            return new ResponseEntity<>(HttpStatus.CONFLICT);
+            vote = voteIter.next();
         }
-        catch (Exception e)
+        else
         {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+            vote = new Vote();
+            vote.setUser(user);
+            vote.setApp(app);
         }
+
+        vote.setValue(value);
+        voteRepository.save(vote);
+
+        return new ResponseEntity<>(HttpStatus.CREATED);
+
     }
 }
diff --git a/src/main/java/org/hbp/mip/controllers/ArticlesApi.java b/src/main/java/org/hbp/mip/controllers/ArticlesApi.java
index 99fe8334aef8fa27ba2fde647794b472b1cdb196..83eed713395da1593b216eb44431370fdcd8d214 100644
--- a/src/main/java/org/hbp/mip/controllers/ArticlesApi.java
+++ b/src/main/java/org/hbp/mip/controllers/ArticlesApi.java
@@ -8,12 +8,10 @@ package org.hbp.mip.controllers;
 import com.github.slugify.Slugify;
 import io.swagger.annotations.*;
 import org.apache.log4j.Logger;
-import org.hbp.mip.MIPApplication;
+import org.hbp.mip.configuration.SecurityConfiguration;
 import org.hbp.mip.model.Article;
 import org.hbp.mip.model.User;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Query;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.ArticleRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -22,8 +20,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.validation.Valid;
 import java.io.IOException;
 import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.Iterator;
 
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 
@@ -35,54 +32,44 @@ public class ArticlesApi {
     private static final Logger LOGGER = Logger.getLogger(ArticlesApi.class);
 
     @Autowired
-    MIPApplication mipApplication;
+    SecurityConfiguration securityConfiguration;
+
+    @Autowired
+    ArticleRepository articleRepository;
 
     @ApiOperation(value = "Get articles", response = Article.class, responseContainer = "List")
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<List> getArticles(
+    public ResponseEntity<Iterable> getArticles(
             @ApiParam(value = "Only ask own articles") @RequestParam(value = "own", required = false) Boolean own,
             @ApiParam(value = "Only ask results matching status", allowableValues = "{values=[draft, published, closed]}") @RequestParam(value = "status", required = false) String status,
             @ApiParam(value = "Only ask articles from own team") @RequestParam(value = "team", required = false) Boolean team
     ) {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
+        Iterable<Article> articles;
 
-        String queryString = "SELECT a FROM Article a, User u WHERE a.createdBy=u.username";
-        if(status != null)
-        {
-            queryString += " AND status= :status";
-        }
         if(own != null && own)
         {
-            queryString += " AND u.username= :username";
+             articles = articleRepository.findByCreatedBy(user);
         }
         else
         {
-            queryString += " AND (status='published' or u.username= :username)";
+            articles = articleRepository.findByStatusOrCreatedBy("published", user);
         }
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        List articles = new LinkedList<>();
-        try {
-            session.beginTransaction();
-            Query query = session.createQuery(queryString);
-            if (status != null) {
-                query.setString("status", status);
-            }
-            query.setString("username", user.getUsername());
-            articles = query.list();
-            session.getTransaction().commit();
-        } catch (Exception e)
+        if(status != null)
         {
-            if(session.getTransaction() != null)
+            for(Iterator<Article> i = articles.iterator(); i.hasNext();)
             {
-                session.getTransaction().rollback();
-                throw e;
+                Article a = i.next();
+                if(!status.equals(a.getStatus()))
+                {
+                    i.remove();
+                }
             }
         }
 
-
         return ResponseEntity.ok(articles);
     }
 
@@ -94,7 +81,7 @@ public class ArticlesApi {
             @RequestBody @ApiParam(value = "Article to create", required = true) @Valid Article article
     ) {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
 
         article.setCreatedAt(new Date());
         if ("published".equals(article.getStatus())) {
@@ -102,62 +89,45 @@ public class ArticlesApi {
         }
         article.setCreatedBy(user);
 
-        Long count;
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try{
-            session.beginTransaction();
-
-            int i = 0;
-            do{
-                i++;
-                count = (Long) session
-                        .createQuery("select count(*) from Article where title= :title")
-                        .setString("title", article.getTitle())
-                        .uniqueResult();
+        long count = 1;
+        for(int i = 1; count > 0; i++)
+        {
+            count = articleRepository.countByTitle(article.getTitle());
 
-                if(count > 0)
-                {
-                    String title = article.getTitle();
-                    if(i > 1)
-                    {
-                        title = title.substring(0, title.length()-4);
-                    }
-                    article.setTitle(title + " (" + i + ")");
-                }
-            } while(count > 0);
-
-            String slug = new Slugify().slugify(article.getTitle());
-
-            i = 0;
-            do {
-                i++;
-                count = (Long) session
-                        .createQuery("select count(*) from Article where slug= :slug")
-                        .setString("slug", slug)
-                        .uniqueResult();
-                if(count > 0)
+            if(count > 0)
+            {
+                String title = article.getTitle();
+                if(i > 1)
                 {
-                    if(i > 1)
-                    {
-                        slug = slug.substring(0, slug.length()-2);
-                    }
-                    slug += "-"+i;
+                    title = title.substring(0, title.length()-4);
                 }
-                article.setSlug(slug);
-            } while(count > 0);
+                article.setTitle(title + " (" + i + ")");
+            }
+        }
 
-            session.save(article);
-            session.getTransaction().commit();
+        String slug;
+        try {
+            slug = new Slugify().slugify(article.getTitle());
         } catch (IOException e) {
-        LOGGER.trace(e);
-        } catch (Exception e) {
-            if(session.getTransaction() != null)
+            slug = "";
+            LOGGER.trace(e);
+        }
+
+        boolean alreadyExists = true;
+        for(int i = 1; alreadyExists; i++)
+        {
+            alreadyExists = articleRepository.exists(slug);
+            if(alreadyExists)
             {
-                session.getTransaction().rollback();
-                throw e;
+                if(i > 1)
+                {
+                    slug = slug.substring(0, slug.length()-2);
+                }
+                slug += "-"+i;
             }
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+            article.setSlug(slug);
         }
+        articleRepository.save(article);
 
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
@@ -170,33 +140,13 @@ public class ArticlesApi {
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
     ) {
 
-        User user = mipApplication.getUser();
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Article article = null;
-        try{
-            session.beginTransaction();
-
-            article = (Article) session
-                    .createQuery("FROM Article WHERE slug= :slug")
-                    .setString("slug", slug)
-                    .uniqueResult();
-
-            session.getTransaction().commit();
-
-            if (!"published".equals(article.getStatus()) && !article.getCreatedBy().getUsername().equals(user.getUsername()))
-            {
-                return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-            }
-        } catch (Exception e)
+        User user = securityConfiguration.getUser();
+        Article article;
+        article = articleRepository.findOne(slug);
+        if (!"published".equals(article.getStatus()) && !article.getCreatedBy().getUsername().equals(user.getUsername()))
         {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
+            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
         }
-
         return ResponseEntity.ok(article);
     }
 
@@ -209,60 +159,36 @@ public class ArticlesApi {
             @RequestBody @ApiParam(value = "Article to update", required = true) @Valid Article article
     ) {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try{
-            session.beginTransaction();
+        String author = articleRepository.findOne(slug).getCreatedBy().getUsername();
 
-            String author = (String) session
-                    .createQuery("select U.username from User U, Article A where A.createdBy = U.username and A.slug = :slug")
-                    .setString("slug", slug)
-                    .uniqueResult();
+        if(!user.getUsername().equals(author))
+        {
+            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
+        }
 
-            if(!user.getUsername().equals(author))
-            {
-                session.getTransaction().commit();
-                return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-            }
+        String oldTitle = articleRepository.findOne(slug).getTitle();
 
-            String oldTitle = (String) session
-                    .createQuery("select title from Article where slug= :slug")
-                    .setString("slug", slug)
-                    .uniqueResult();
-
-            String newTitle = article.getTitle();
-
-            if(!newTitle.equals(oldTitle)) {
-                Long count;
-                int i = 0;
-                do {
-                    i++;
-                    newTitle = article.getTitle();
-                    count = (Long) session
-                            .createQuery("select count(*) from Article where title= :title")
-                            .setString("title", newTitle)
-                            .uniqueResult();
-                    if (count > 0 && !newTitle.equals(oldTitle)) {
-                        if (i > 1) {
-                            newTitle = newTitle.substring(0, newTitle.length() - 4);
-                        }
-                        article.setTitle(newTitle + " (" + i + ")");
-                    }
-                } while (count > 0 && !newTitle.equals(oldTitle));
-            }
+        String newTitle = article.getTitle();
 
-            session.update(article);
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
+        if(!newTitle.equals(oldTitle)) {
+            long count = 1;
+            for(int i = 1; count > 0 && !newTitle.equals(oldTitle); i++)
             {
-                session.getTransaction().rollback();
-                throw e;
+                newTitle = article.getTitle();
+                count = articleRepository.countByTitle(newTitle);
+                if (count > 0 && !newTitle.equals(oldTitle)) {
+                    if (i > 1) {
+                        newTitle = newTitle.substring(0, newTitle.length() - 4);
+                    }
+                    article.setTitle(newTitle + " (" + i + ")");
+                }
             }
         }
 
+        articleRepository.save(article);
+
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
diff --git a/src/main/java/org/hbp/mip/controllers/DatasetsApi.java b/src/main/java/org/hbp/mip/controllers/DatasetsApi.java
index 4f3b67bfb063cd6504f7df85cf99c8cc4089a1d7..05fc11d6a8b93a573e0c5ffe149de1e2d2a9a1fc 100644
--- a/src/main/java/org/hbp/mip/controllers/DatasetsApi.java
+++ b/src/main/java/org/hbp/mip/controllers/DatasetsApi.java
@@ -7,8 +7,8 @@ package org.hbp.mip.controllers;
 
 import io.swagger.annotations.*;
 import org.hbp.mip.model.Dataset;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.DatasetRepository;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,32 +22,16 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/datasets", description = "the datasets API")
 public class DatasetsApi {
 
+    @Autowired
+    DatasetRepository datasetRepository;
+
     @ApiOperation(value = "Get a dataset", response = Dataset.class)
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(value = "/{code}", method = RequestMethod.GET)
     public ResponseEntity<Dataset> getADataset(
             @ApiParam(value = "code", required = true) @PathVariable("code") String code
     )  {
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Dataset dataset = null;
-        try{
-            session.beginTransaction();
-            dataset = (Dataset) session
-                    .createQuery("from Dataset where code= :code")
-                    .setString("code", code)
-                    .uniqueResult();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(dataset);
+        return ResponseEntity.ok(datasetRepository.findOne(code));
     }
 
 }
diff --git a/src/main/java/org/hbp/mip/controllers/ExperimentApi.java b/src/main/java/org/hbp/mip/controllers/ExperimentApi.java
index 5adbdaa35ffd233717ea958b54e6a3cdfc7f78a2..99275314da2f0fdd068157e99e927b57aa949ca8 100644
--- a/src/main/java/org/hbp/mip/controllers/ExperimentApi.java
+++ b/src/main/java/org/hbp/mip/controllers/ExperimentApi.java
@@ -1,18 +1,16 @@
 package org.hbp.mip.controllers;
 
+import com.google.common.collect.Lists;
 import com.google.gson.*;
 import io.swagger.annotations.*;
 import org.apache.log4j.Logger;
-import org.hbp.mip.MIPApplication;
+import org.hbp.mip.configuration.SecurityConfiguration;
 import org.hbp.mip.model.Experiment;
-import org.hbp.mip.model.Model;
 import org.hbp.mip.model.User;
+import org.hbp.mip.repositories.ExperimentRepository;
+import org.hbp.mip.repositories.ModelRepository;
 import org.hbp.mip.utils.HTTPUtil;
-import org.hbp.mip.utils.HibernateUtil;
 import org.hbp.mip.utils.JSONUtil;
-import org.hibernate.Query;
-import org.hibernate.Session;
-import org.hibernate.Transaction;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpStatus;
@@ -24,7 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.MalformedURLException;
-import java.util.LinkedList;
+import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
@@ -61,7 +59,13 @@ public class ExperimentApi {
     private String miningExaremeQueryUrl;
 
     @Autowired
-    MIPApplication mipApplication;
+    SecurityConfiguration securityConfiguration;
+
+    @Autowired
+    ModelRepository modelRepository;
+
+    @Autowired
+    ExperimentRepository experimentRepository;
 
 
     @ApiOperation(value = "Send a request to the workflow to run an experiment", response = Experiment.class)
@@ -72,35 +76,14 @@ public class ExperimentApi {
 
         Experiment experiment = new Experiment();
         experiment.setUuid(UUID.randomUUID());
-        User user = mipApplication.getUser();
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Transaction transaction = session.beginTransaction();
-
-        try {
+        User user = securityConfiguration.getUser();
 
-            experiment.setAlgorithms(incomingQuery.get("algorithms").toString());
-            experiment.setValidations(incomingQuery.get("validations").toString());
-            experiment.setName(incomingQuery.get("name").getAsString());
-            experiment.setCreatedBy(user);
-
-            Query hibernateQuery = session.createQuery("from Model as model where model.slug = :slug");
-            hibernateQuery.setParameter("slug", incomingQuery.get("model").getAsString());
-            experiment.setModel((Model)hibernateQuery.uniqueResult());
-
-            session.save(experiment);
-            transaction.commit();
-
-        } catch (Exception e) {
-            if(transaction != null)
-            {
-                transaction.rollback();
-            }
-            LOGGER.trace(e);
-            LOGGER.warn("Cannot create experiment to run ! This is probably caused by a bad request !");
-            // 400 here probably
-            return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
-        }
+        experiment.setAlgorithms(incomingQuery.get("algorithms").toString());
+        experiment.setValidations(incomingQuery.get("validations").toString());
+        experiment.setName(incomingQuery.get("name").getAsString());
+        experiment.setCreatedBy(user);
+        experiment.setModel(modelRepository.findOne(incomingQuery.get("model").getAsString()));
+        experimentRepository.save(experiment);
 
         try {
             if(isExaremeAlgo(experiment))
@@ -130,23 +113,7 @@ public class ExperimentApi {
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-
-        try {
-            session.beginTransaction();
-
-            Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
-            hibernateQuery.setParameter("uuid", experimentUuid);
-            experiment = (Experiment) hibernateQuery.uniqueResult();
-            session.getTransaction().commit();
-        } catch (Exception e) {
-            // 404 here probably
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-            }
-            throw e;
-        }
+        experiment = experimentRepository.findOne(experimentUuid);
 
         if (experiment == null) {
             return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
@@ -161,7 +128,7 @@ public class ExperimentApi {
 
         Experiment experiment;
         UUID experimentUuid;
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
@@ -170,31 +137,11 @@ public class ExperimentApi {
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Transaction transaction = null;
-        try {
-            transaction = session.beginTransaction();
-
-            Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
-            hibernateQuery.setParameter("uuid", experimentUuid);
-            experiment = (Experiment) hibernateQuery.uniqueResult();
-
-            if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
-                return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
-
-            experiment.setResultsViewed(true);
-            session.update(experiment);
-
-            transaction.commit();
-        } catch (Exception e) {
-            // 404 here probably
-            if(transaction != null)
-            {
-                transaction.rollback();
-            }
-            throw e;
-        }
-
+        experiment = experimentRepository.findOne(experimentUuid);;
+        if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
+            return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
+        experiment.setResultsViewed(true);
+        experimentRepository.save(experiment);
         return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
     }
 
@@ -265,61 +212,38 @@ public class ExperimentApi {
             int maxResultCount,
             String modelSlug
     ) {
-        List<Experiment> experiments = new LinkedList<>();
-        User user = mipApplication.getUser();
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-
-        try {
-            session.beginTransaction();
-
-            Query hibernateQuery;
-            String baseQuery = "from Experiment as e WHERE ";
-
-            baseQuery += mine ? "e.createdBy = :user" : "(e.createdBy = :user OR e.shared is true)";
-
-            if (modelSlug == null || "".equals(modelSlug)) {
-                hibernateQuery = session.createQuery(baseQuery);
-            } else {
-                baseQuery += " AND e.model.slug = :slug";
-                hibernateQuery = session.createQuery(baseQuery);
-                hibernateQuery.setParameter("slug", modelSlug);
-            }
-            hibernateQuery.setParameter("user", user);
-
-            if (maxResultCount > 0)
-                hibernateQuery.setMaxResults(maxResultCount);
-
-            for (Object experiment: hibernateQuery.list()) {
-                if (experiment instanceof Experiment) { // should definitely be true
-                    Experiment experiment1 = (Experiment) experiment;
-                    // remove some fields because it is costly and not useful to send them over the network
-                    experiment1.setResult(null);
-                    experiment1.setAlgorithms(null);
-                    experiment1.setValidations(null);
-                    experiments.add(experiment1);
-
-                }
+        User user = securityConfiguration.getUser();
+        Iterable<Experiment> experiments = null;
+
+        Iterable<Experiment> myExperiments = experimentRepository.findByCreatedBy(user);
+        List<Experiment> expList = Lists.newLinkedList(myExperiments);
+        if(!mine)
+        {
+            Iterable<Experiment> sharedExperiments = experimentRepository.findByShared(true);
+            List<Experiment> sharedExpList = Lists.newLinkedList(sharedExperiments);
+            expList.addAll(sharedExpList);
+        }
 
-            }
-        } catch (Exception e) {
-            // 404 here probably
-            LOGGER.trace(e);
-            throw e;
-        } finally {
-            if(session.getTransaction() != null)
+        if (modelSlug != null && !"".equals(modelSlug)) {
+            for(Experiment e : expList)
             {
-                session.getTransaction().rollback();
+                e.setResult(null);
+                e.setAlgorithms(null);
+                e.setValidations(null);
+                if(!e.getModel().getSlug().equals(modelSlug))
+                {
+                    expList.remove(e);
+                }
             }
         }
 
-        return new ResponseEntity<>(gson.toJson(experiments), HttpStatus.OK);
+        return new ResponseEntity<>(gson.toJson(expList), HttpStatus.OK);
     }
 
     private ResponseEntity<String> doMarkExperimentAsShared(String uuid, boolean shared) {
         Experiment experiment;
         UUID experimentUuid;
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
@@ -328,30 +252,13 @@ public class ExperimentApi {
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Transaction transaction = null;
-        try {
-            transaction = session.beginTransaction();
-
-            Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
-            hibernateQuery.setParameter("uuid", experimentUuid);
-            experiment = (Experiment) hibernateQuery.uniqueResult();
+        experiment = experimentRepository.findOne(experimentUuid);
 
-            if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
-                return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
+        if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
+            return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
 
-            experiment.setShared(shared);
-            session.update(experiment);
-
-            transaction.commit();
-        } catch (Exception e) {
-            // 404 here probably
-            if(transaction != null)
-            {
-                transaction.rollback();
-            }
-            throw e;
-        }
+        experiment.setShared(shared);
+        experimentRepository.save(experiment);
 
         return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
     }
@@ -361,10 +268,10 @@ public class ExperimentApi {
         new Thread() {
             @Override
             public void run() {
-                    String url = experimentUrl;
-                    String query = experiment.computeQuery();
+                String url = experimentUrl;
+                String query = experiment.computeQuery();
 
-                    // Results are stored in the experiment object
+                // Results are stored in the experiment object
                 try {
                     executeExperiment(url, query, experiment);
                 } catch (IOException e) {
@@ -372,8 +279,7 @@ public class ExperimentApi {
                     LOGGER.warn("Experiment failed to run properly !");
                     setExperimentError(e, experiment);
                 }
-
-                experiment.finish();
+                finishExpermient(experiment);
             }
         }.start();
     }
@@ -399,12 +305,17 @@ public class ExperimentApi {
                     {
                         experiment.setResult("Unsupported variables !");
                     }
-
-                experiment.finish();
+                finishExpermient(experiment);
             }
         }.start();
     }
 
+    private void finishExpermient(Experiment experiment)
+    {
+        experiment.setFinished(new Date());
+        experimentRepository.save(experiment);
+    }
+
     private static void executeExperiment(String url, String query, Experiment experiment) throws IOException {
         StringBuilder results = new StringBuilder();
         int code = HTTPUtil.sendPost(url, query, results);
diff --git a/src/main/java/org/hbp/mip/controllers/GroupsApi.java b/src/main/java/org/hbp/mip/controllers/GroupsApi.java
index 9f23ad3b43b379ceb8c148900aaac129ac3ae0ad..48574e48cec79d8a23005db34c3125521d7f9c7a 100644
--- a/src/main/java/org/hbp/mip/controllers/GroupsApi.java
+++ b/src/main/java/org/hbp/mip/controllers/GroupsApi.java
@@ -9,8 +9,8 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import org.hbp.mip.model.Group;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.GroupRepository;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -23,32 +23,16 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/groups", description = "the groups API")
 public class GroupsApi {
 
+    private static final String ROOT_CODE = "root";
+
+    @Autowired
+    GroupRepository groupRepository;
+
     @ApiOperation(value = "Get the root group (containing all subgroups)", response = Group.class)
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(method = RequestMethod.GET)
     public ResponseEntity<Group> getTheRootGroup()  {
-
-        String rootCode = "root";
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Group group = null;
-        try{
-            session.beginTransaction();
-            group = (Group) session
-                    .createQuery("FROM Group WHERE code= :code")
-                    .setString("code", rootCode)
-                    .uniqueResult();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(group);
+        return ResponseEntity.ok(groupRepository.findOne(ROOT_CODE));
     }
 
 
diff --git a/src/main/java/org/hbp/mip/controllers/ModelsApi.java b/src/main/java/org/hbp/mip/controllers/ModelsApi.java
index 21b102e1858a508f92bff344a4aded93006c10f2..2570b9a6770cd6b264549d472528ec55fd517e34 100644
--- a/src/main/java/org/hbp/mip/controllers/ModelsApi.java
+++ b/src/main/java/org/hbp/mip/controllers/ModelsApi.java
@@ -7,12 +7,13 @@ package org.hbp.mip.controllers;
 import com.github.slugify.Slugify;
 import io.swagger.annotations.*;
 import org.apache.log4j.Logger;
-import org.hbp.mip.MIPApplication;
+import org.hbp.mip.configuration.SecurityConfiguration;
 import org.hbp.mip.model.*;
+import org.hbp.mip.repositories.ConfigRepository;
+import org.hbp.mip.repositories.DatasetRepository;
+import org.hbp.mip.repositories.ModelRepository;
+import org.hbp.mip.repositories.QueryRepository;
 import org.hbp.mip.utils.CSVUtil;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Query;
-import org.hibernate.Session;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -32,88 +33,62 @@ public class ModelsApi {
     private static final Logger LOGGER = Logger.getLogger(ModelsApi.class);
 
     @Autowired
-    MIPApplication mipApplication;
+    SecurityConfiguration securityConfiguration;
+
+    @Autowired
+    CSVUtil csvUtil;
+
+    @Autowired
+    DatasetRepository datasetRepository;
+
+    @Autowired
+    ModelRepository modelRepository;
+
+    @Autowired
+    QueryRepository queryRepository;
+
+    @Autowired
+    ConfigRepository configRepository;
 
     private static final String DATA_FILE = "data/values.csv";
 
     @ApiOperation(value = "Get models", response = Model.class, responseContainer = "List")
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<List<Model>> getModels(
+    public ResponseEntity<Iterable> getModels(
             @ApiParam(value = "Max number of results") @RequestParam(value = "limit", required = false) Integer limit,
             @ApiParam(value = "Only ask own models") @RequestParam(value = "own", required = false) Boolean own,
             @ApiParam(value = "Only ask models from own team") @RequestParam(value = "team", required = false) Boolean team,
             @ApiParam(value = "Only ask published models") @RequestParam(value = "valid", required = false) Boolean valid
     )  {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
+        Iterable<Model> models = null;
 
-        String queryString = "SELECT m FROM Model m, User u WHERE m.createdBy=u.username";
-        if(valid != null && valid)
-        {
-            queryString += " AND m.valid= :valid";
-        }
         if(own != null && own)
         {
-            queryString += " AND u.username= :username";
+            models = modelRepository.findByCreatedByOrderByCreatedAt(user);
         }
         else
         {
-            queryString += " AND (m.valid=true or u.username= :username)";
+            models = modelRepository.findByValidOrCreatedByOrderByCreatedAt(true, user);
         }
 
-        queryString += " ORDER BY m.createdAt DESC";
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        List<Model> models = new LinkedList<>();
-        try{
-            session.beginTransaction();
-            Query query = session.createQuery(queryString);
-            if(valid != null)
-            {
-                query.setBoolean("valid", valid);
-            }
-            query.setString("username", user.getUsername());
-            if(limit != null)
-            {
-                query.setMaxResults(limit);  // Pagination : Use query.setFirstResult(...) to set begining index
-            }
-            models = query.list();
-            session.getTransaction().commit();
-        } catch (Exception e)
+        if(valid != null && models != null)
         {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        for(Model model:models){
-            String dsCode = model.getDataset().getCode();
-
-            session = HibernateUtil.getSessionFactory().getCurrentSession();
-            Dataset dataset = null;
-            try{
-                session.beginTransaction();
-                dataset = (Dataset) session
-                        .createQuery("from Dataset where code= :code")
-                        .setString("code", dsCode)
-                        .uniqueResult();
-                session.getTransaction().commit();
-            } catch (Exception e)
+            for (Iterator<Model> i = models.iterator(); i.hasNext(); )
             {
-                if(session.getTransaction() != null)
+                Model m = i.next();
+                m.setDataset(datasetRepository.findOne(m.getDataset().getCode()));
+                if(valid != m.getValid())
                 {
-                    session.getTransaction().rollback();
-                    throw e;
+                    i.remove();
                 }
             }
-
-            model.setDataset(dataset);
         }
 
         return new ResponseEntity<List<Model>>(HttpStatus.OK).ok(models);
+
     }
 
 
@@ -124,7 +99,7 @@ public class ModelsApi {
             @RequestBody @ApiParam(value = "Model to create", required = true) Model model
     )  {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
 
         model.setTitle(model.getConfig().getTitle().get("text"));
         model.setCreatedBy(user);
@@ -134,67 +109,54 @@ public class ModelsApi {
             model.setValid(false);
         }
 
-        Long count;
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try{
-            session.beginTransaction();
-
-            int i = 0;
-            do{
-                i++;
-                count = (Long) session
-                        .createQuery("select count(*) from Model where title= :title")
-                        .setString("title", model.getTitle())
-                        .uniqueResult();
+        long count = 1;
+        for(int i = 1; count > 0; i++)
+        {
+            count = modelRepository.countByTitle(model.getTitle());
 
-                if(count > 0)
-                {
-                    String title = model.getTitle();
-                    if(i > 1)
-                    {
-                        title = title.substring(0, title.length()-4);
-                    }
-                    model.setTitle(title + " (" + i + ")");
-                }
-            } while(count > 0);
-
-            String slug = new Slugify().slugify(model.getTitle());
-
-            i = 0;
-            do {
-                i++;
-                count = (Long) session
-                        .createQuery("select count(*) from Model where slug= :slug")
-                        .setString("slug", slug)
-                        .uniqueResult();
-                if(count > 0)
+            if(count > 0)
+            {
+                String title = model.getTitle();
+                if(i > 1)
                 {
-                    if(i > 1)
-                    {
-                        slug = slug.substring(0, slug.length()-2);
-                    }
-                    slug += "-"+i;
+                    title = title.substring(0, title.length()-4);
                 }
-                model.setSlug(slug);
-            } while(count > 0);
-
-            Map<String, String> map = new HashMap<>(model.getConfig().getTitle());
-            map.put("text", model.getTitle());
-            model.getConfig().setTitle(map);
+                model.setTitle(title + " (" + i + ")");
+            }
+        }
 
-            session.save(model);
-            session.getTransaction().commit();
+        String slug = null;
+        try {
+            slug = new Slugify().slugify(model.getTitle());
         } catch (IOException e) {
+            slug = "";
             LOGGER.trace(e);
-        } catch (Exception e)
+        }
+
+        boolean alreadyExists = true;
+        for(int i = 1; alreadyExists; i++)
         {
-            if(session.getTransaction() != null)
+            alreadyExists = modelRepository.exists(slug);
+            if(alreadyExists)
             {
-                session.getTransaction().rollback();
-                throw e;
+                if(i > 1)
+                {
+                    slug = slug.substring(0, slug.length()-2);
+                }
+                slug += "-"+i;
             }
+            model.setSlug(slug);
         }
 
+        Map<String, String> map = new HashMap<>(model.getConfig().getTitle());
+        map.put("text", model.getTitle());
+        model.getConfig().setTitle(map);
+
+        configRepository.save(model.getConfig());
+        queryRepository.save(model.getQuery());
+        datasetRepository.save(model.getDataset());
+        modelRepository.save(model);
+
         return new ResponseEntity<Model>(HttpStatus.CREATED).ok(model);
     }
 
@@ -205,100 +167,49 @@ public class ModelsApi {
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
     )  {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         Model model = null;
 
-        try {
-            session.beginTransaction();
-            model = (Model) session
-                    .createQuery("FROM Model WHERE slug= :slug")
-                    .setString("slug", slug)
-                    .uniqueResult();
-            session.getTransaction().commit();
-
-            if (!model.getValid() && !model.getCreatedBy().getUsername().equals(user.getUsername()))
-            {
-                return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-            }
-
-        } catch (Exception e)
+        model = modelRepository.findOne(slug);
+        if (!model.getValid() && !model.getCreatedBy().getUsername().equals(user.getUsername()))
         {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
+            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
         }
 
+        if(model != null)
+        {
+            List<String> yAxisVars = configRepository.findOne(model.getConfig().getId()).getyAxisVariables();
+            Collection<String> yAxisVarsColl = new LinkedHashSet<>(yAxisVars);
+            model.getConfig().setyAxisVariables(new LinkedList<>(yAxisVarsColl));
 
-        if(model != null) {
-            session = HibernateUtil.getSessionFactory().getCurrentSession();
-            org.hbp.mip.model.Query q = null;
-
-            try {
-                session.beginTransaction();
-                q = (org.hbp.mip.model.Query) session
-                        .createQuery("FROM Query WHERE id= :id")
-                        .setLong("id", model.getQuery().getId())
-                        .uniqueResult();
-                session.getTransaction().commit();
-            } catch (Exception e)
-            {
-                if(session.getTransaction() != null)
-                {
-                    session.getTransaction().rollback();
-                    throw e;
-                }
-            }
-
-            if(q != null) {
-
-                List<Variable> vars = new LinkedList<>();
-                for (Variable var : q.getVariables()) {
-                    Variable v = new Variable();
-                    v.setCode(var.getCode());
-                    vars.add(v);
-                }
-
-                List<Variable> covs = new LinkedList<>();
-                for (Variable cov : q.getCovariables()) {
-                    Variable v = new Variable();
-                    v.setCode(cov.getCode());
-                    covs.add(v);
-                }
+            List<Variable> varsQuery = queryRepository.findOne(model.getQuery().getId()).getVariables();
+            Collection<Variable> varsQueryColl = new LinkedHashSet<>(varsQuery);
+            model.getQuery().setVariables(new LinkedList<>(varsQueryColl));
 
-                List<Variable> grps = new LinkedList<>();
-                for (Variable grp : q.getGrouping()) {
-                    Variable v = new Variable();
-                    v.setCode(grp.getCode());
-                    grps.add(v);
-                }
+            List<Variable> grpgsQuery = queryRepository.findOne(model.getQuery().getId()).getGrouping();
+            Collection<Variable> grpgsQueryColl = new LinkedHashSet<>(grpgsQuery);
+            model.getQuery().setGrouping(new LinkedList<>(grpgsQueryColl));
 
-                List<Filter> fltrs = new LinkedList<>();
-                for (Filter fltr : q.getFilters()) {
-                    Filter f = new Filter();
-                    f.setId(fltr.getId());
-                    f.setOperator(fltr.getOperator());
-                    f.setValues(fltr.getValues());
-                    f.setVariable(fltr.getVariable());
-                    fltrs.add(f);
-                }
+            List<Variable> covarsQuery = queryRepository.findOne(model.getQuery().getId()).getCovariables();
+            Collection<Variable> covarsQueryColl = new LinkedHashSet<>(covarsQuery);
+            model.getQuery().setCovariables(new LinkedList<>(covarsQueryColl));
 
-                org.hbp.mip.model.Query myQuery = new org.hbp.mip.model.Query();
-                myQuery.setId(q.getId());
-                myQuery.setVariables(vars);
-                myQuery.setCovariables(covs);
-                myQuery.setGrouping(grps);
-                myQuery.setFilters(fltrs);
+            List<Filter> fltrs = queryRepository.findOne(model.getQuery().getId()).getFilters();
+            Collection<Filter> fltrsColl = new LinkedHashSet<>(fltrs);
+            model.getQuery().setFilters(new LinkedList<>(fltrsColl));
 
-                model.setQuery(myQuery);
-            }
+            List<String> varsDS = datasetRepository.findOne(model.getDataset().getCode()).getVariable();
+            Collection<String> varsDSColl = new LinkedHashSet<>(varsDS);
+            model.getDataset().setVariable(new LinkedList<>(varsDSColl));
 
-            Dataset ds = CSVUtil.parseValues(DATA_FILE, model.getQuery());
-            model.setDataset(ds);
+            List<String> grpgsDS = datasetRepository.findOne(model.getDataset().getCode()).getGrouping();
+            Collection<String> grpgsDSColl = new LinkedHashSet<>(grpgsDS);
+            model.getDataset().setGrouping(new LinkedList<>(grpgsDSColl));
 
+            List<String> headersDS = datasetRepository.findOne(model.getDataset().getCode()).getHeader();
+            Collection<String> headersDSColl = new LinkedHashSet<>(headersDS);
+            model.getDataset().setHeader(new LinkedList<>(headersDSColl));
         }
 
         return new ResponseEntity<>(HttpStatus.OK).ok(model);
@@ -313,66 +224,46 @@ public class ModelsApi {
             @RequestBody @ApiParam(value = "Model to update", required = true) Model model
     )  {
 
-        User user = mipApplication.getUser();
+        User user = securityConfiguration.getUser();
 
         model.setTitle(model.getConfig().getTitle().get("text"));
 
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        try{
-            session.beginTransaction();
-
-            String author = (String) session
-                    .createQuery("select U.username from User U, Model M where M.createdBy = U.username and M.slug = :slug")
-                    .setString("slug", slug)
-                    .uniqueResult();
+        Model oldModel = modelRepository.findOne(slug);
 
-            if(!user.getUsername().equals(author))
-            {
-                session.getTransaction().commit();
-                return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-            }
+        String author = oldModel.getCreatedBy().getUsername();
 
-            String oldTitle = (String) session
-                    .createQuery("select title from Model where slug= :slug")
-                    .setString("slug", slug)
-                    .uniqueResult();
-
-            String newTitle = model.getTitle();
-
-            if(!newTitle.equals(oldTitle)) {
-                Long count;
-                int i = 0;
-                do {
-                    i++;
-                    newTitle = model.getTitle();
-                    count = (Long) session
-                            .createQuery("select count(*) from Model where title= :title")
-                            .setString("title", newTitle)
-                            .uniqueResult();
-                    if (count > 0 && !newTitle.equals(oldTitle)) {
-                        if (i > 1) {
-                            newTitle = newTitle.substring(0, newTitle.length() - 4);
-                        }
-                        model.setTitle(newTitle + " (" + i + ")");
-                    }
-                } while (count > 0 && !newTitle.equals(oldTitle));
-            }
+        if(!user.getUsername().equals(author))
+        {
+            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
+        }
 
-            Map<String, String> map = new HashMap<>(model.getConfig().getTitle());
-            map.put("text", model.getTitle());
-            model.getConfig().setTitle(map);
+        String oldTitle = oldModel.getTitle();
+        String newTitle = model.getTitle();
 
-            session.update(model);
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
+        if(!newTitle.equals(oldTitle)) {
+            long count = 1;
+            for(int i = 1; count > 0 && !newTitle.equals(oldTitle); i++)
             {
-                session.getTransaction().rollback();
-                throw e;
+                newTitle = model.getTitle();
+                count = modelRepository.countByTitle(newTitle);
+                if (count > 0 && !newTitle.equals(oldTitle)) {
+                    if (i > 1) {
+                        newTitle = newTitle.substring(0, newTitle.length() - 4);
+                    }
+                    model.setTitle(newTitle + " (" + i + ")");
+                }
             }
         }
 
+        Map<String, String> map = new HashMap<>(model.getConfig().getTitle());
+        map.put("text", model.getTitle());
+        model.getConfig().setTitle(map);
+
+        configRepository.save(model.getConfig());
+        queryRepository.save(model.getQuery());
+        datasetRepository.save(model.getDataset());
+        modelRepository.save(model);
+
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
diff --git a/src/main/java/org/hbp/mip/controllers/RequestsApi.java b/src/main/java/org/hbp/mip/controllers/RequestsApi.java
index b60a53b558a33a205bb07ff404a25bba7e5af2d1..76527eba6de906c48a50823ed348c4388cfc2dc0 100644
--- a/src/main/java/org/hbp/mip/controllers/RequestsApi.java
+++ b/src/main/java/org/hbp/mip/controllers/RequestsApi.java
@@ -8,6 +8,7 @@ import io.swagger.annotations.*;
 import org.hbp.mip.model.Dataset;
 import org.hbp.mip.model.Query;
 import org.hbp.mip.utils.CSVUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -23,16 +24,16 @@ public class RequestsApi {
 
     private static final String DATA_FILE = "data/values.csv";
 
+    @Autowired
+    CSVUtil csvUtil;
+
     @ApiOperation(value = "Send a request", response = Dataset.class)
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(method = RequestMethod.POST)
     public ResponseEntity<Dataset> postRequests(
             @RequestBody @ApiParam(value = "Query to process", required = true) Query query
     )  {
-
-        Dataset dataset = CSVUtil.parseValues(DATA_FILE, query);
-
-        return ResponseEntity.ok(dataset);
+        return ResponseEntity.ok(csvUtil.parseValues(DATA_FILE, query));
     }
 
 }
diff --git a/src/main/java/org/hbp/mip/controllers/StatsApi.java b/src/main/java/org/hbp/mip/controllers/StatsApi.java
index e40a3becf1ee8715ecca6dea068dcc09cb855823..3f6883f28f9d19e7887519105e9a07bd58d5679d 100644
--- a/src/main/java/org/hbp/mip/controllers/StatsApi.java
+++ b/src/main/java/org/hbp/mip/controllers/StatsApi.java
@@ -9,9 +9,10 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import org.hbp.mip.model.GeneralStats;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Query;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.ArticleRepository;
+import org.hbp.mip.repositories.UserRepository;
+import org.hbp.mip.repositories.VariableRepository;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -24,44 +25,25 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/stats", description = "the stats API")
 public class StatsApi {
 
+    @Autowired
+    UserRepository userRepository;
+
+    @Autowired
+    ArticleRepository articleRepository;
+
+    @Autowired
+    VariableRepository variableRepository;
+
     @ApiOperation(value = "Get general statistics", response = GeneralStats.class)
     @ApiResponses(value = {@ApiResponse(code = 200, message = "Found"), @ApiResponse(code = 404, message = "Not found") })
     @RequestMapping(method = RequestMethod.GET)
     public ResponseEntity<GeneralStats> getGeneralStatistics()  {
 
         GeneralStats stats = new GeneralStats();
-        Long nbUsers = 0L;
-        Long nbArticles = 0L;
-        Long nbVariables = 0L;
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-
-        try{
-
-            session.beginTransaction();
-
-            Query countUsersQuery = session.createQuery("SELECT COUNT(*) FROM User");
-            Query countArticlesQuery = session.createQuery("SELECT COUNT(*) FROM Article");
-            Query countVariablesQuery = session.createQuery("SELECT COUNT(*) FROM Variable");
-
-            nbUsers = (Long) countUsersQuery.uniqueResult();
-            nbArticles = (Long) countArticlesQuery.uniqueResult();
-            nbVariables = (Long) countVariablesQuery.uniqueResult();
-
-            session.getTransaction().commit();
-
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
 
-        stats.setUsers(nbUsers);
-        stats.setArticles(nbArticles);
-        stats.setVariables(nbVariables);
+        stats.setUsers(userRepository.count());
+        stats.setArticles(articleRepository.count());
+        stats.setVariables(variableRepository.count());
 
         return ResponseEntity.ok(stats);
     }
diff --git a/src/main/java/org/hbp/mip/controllers/UsersApi.java b/src/main/java/org/hbp/mip/controllers/UsersApi.java
index bdd2e6745173a7fb9362ae31392ca157007d8231..eabeffca1e196a3201a9068b46c1dc395946f2fb 100644
--- a/src/main/java/org/hbp/mip/controllers/UsersApi.java
+++ b/src/main/java/org/hbp/mip/controllers/UsersApi.java
@@ -6,8 +6,8 @@ package org.hbp.mip.controllers;
 
 import io.swagger.annotations.*;
 import org.hbp.mip.model.User;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -21,6 +21,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/users", description = "the users API")
 public class UsersApi {
 
+    @Autowired
+    UserRepository userRepository;
 
     @ApiOperation(value = "Get a user", response = User.class)
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Found"), @ApiResponse(code = 404, message = "Not found") })
@@ -28,25 +30,6 @@ public class UsersApi {
     public ResponseEntity<User> getAUser(
             @ApiParam(value = "username", required = true) @PathVariable("username") String username
     )  {
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        User user = null;
-        try{
-            session.beginTransaction();
-            user = (User) session
-                    .createQuery("from User where username= :username")
-                    .setString("username", username)
-                    .uniqueResult();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(user);
+        return ResponseEntity.ok(userRepository.findOne(username));
     }
 }
diff --git a/src/main/java/org/hbp/mip/controllers/VariablesApi.java b/src/main/java/org/hbp/mip/controllers/VariablesApi.java
index f69f98dedd82c9eb8707b858e86e27a0fd55a2fb..b5f2d72f2f5ea151070fb2598007f22a49b475f6 100644
--- a/src/main/java/org/hbp/mip/controllers/VariablesApi.java
+++ b/src/main/java/org/hbp/mip/controllers/VariablesApi.java
@@ -8,12 +8,11 @@ package org.hbp.mip.controllers;
 import io.swagger.annotations.*;
 import org.hbp.mip.model.Value;
 import org.hbp.mip.model.Variable;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.VariableRepository;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.LinkedList;
 import java.util.List;
 
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@@ -23,10 +22,13 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/variables", description = "the variables API")
 public class VariablesApi {
 
+    @Autowired
+    VariableRepository variableRepository;
+
     @ApiOperation(value = "Get variables", response = Variable.class, responseContainer = "List")
     @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
     @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<List> getVariables(
+    public ResponseEntity<Iterable> getVariables(
             @ApiParam(value = "List of groups formatted like : (\"val1\", \"val2\", ...)") @RequestParam(value = "group", required = false) String group,
             @ApiParam(value = "List of subgroups formatted like : (\"val1\", \"val2\", ...)") @RequestParam(value = "subgroup", required = false) String subgroup,
             @ApiParam(value = "Boolean value formatted like : (\"0\") or (\"1\") or (\"false\") or (\"true\")") @RequestParam(value = "isVariable", required = false) String isVariable,
@@ -34,25 +36,7 @@ public class VariablesApi {
             @ApiParam(value = "Boolean value formatted like : (\"0\") or (\"1\") or (\"false\") or (\"true\")") @RequestParam(value = "isCovariable", required = false) String isCovariable,
             @ApiParam(value = "Boolean value formatted like : (\"0\") or (\"1\") or (\"false\") or (\"true\")") @RequestParam(value = "isFilter", required = false) String isFilter
     )  {
-
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        List variables = new LinkedList<>();
-        try{
-            session.beginTransaction();
-            variables = session
-                    .createQuery("from Variable")
-                    .list();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(variables);
+        return ResponseEntity.ok(variableRepository.findAll());
     }
 
     @ApiOperation(value = "Get a variable", response = Variable.class)
@@ -61,27 +45,7 @@ public class VariablesApi {
     public ResponseEntity<Variable> getAVariable(
             @ApiParam(value = "code of the variable ( multiple codes are allowed, separated by \",\" )", required = true) @PathVariable("code") String code
     )  {
-
-        // Query DB
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        Variable variable = null;
-        try{
-            session.beginTransaction();
-            variable = (Variable) session
-                    .createQuery("from Variable where code= :code")
-                    .setString("code", code)
-                    .uniqueResult();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(variable);
+        return ResponseEntity.ok(variableRepository.findOne(code));
     }
 
 
@@ -92,27 +56,7 @@ public class VariablesApi {
             @ApiParam(value = "code", required = true) @PathVariable("code") String code,
             @ApiParam(value = "Pattern to match") @RequestParam(value = "q", required = false) String q
     )  {
-
-        // Query DB
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        List values = new LinkedList<>();
-        try{
-            session.beginTransaction();
-            values = session
-                    .createQuery("select values from Variable where code= :code")
-                    .setString("code", code)
-                    .list();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
-        return ResponseEntity.ok(values);
+        return ResponseEntity.ok(variableRepository.findOne(code).getValues());
     }
 
 
diff --git a/src/main/java/org/hbp/mip/model/Experiment.java b/src/main/java/org/hbp/mip/model/Experiment.java
index d87949be04dc8da5d7080d4e20ace726e22ff267..f42ffbd6cbc11aa6e297bde4adfdc383b23ea5dd 100644
--- a/src/main/java/org/hbp/mip/model/Experiment.java
+++ b/src/main/java/org/hbp/mip/model/Experiment.java
@@ -6,15 +6,9 @@ import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import com.google.gson.annotations.Expose;
 import org.apache.log4j.Logger;
-import org.hbp.mip.utils.HibernateUtil;
-import org.hibernate.Session;
-import org.hibernate.Transaction;
-import org.hibernate.annotations.*;
-import org.hibernate.exception.DataException;
+import org.hibernate.annotations.Cascade;
 
 import javax.persistence.*;
-import javax.persistence.Entity;
-import javax.persistence.Table;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -145,21 +139,6 @@ public class Experiment {
         return new Gson().toJson(queryElements);
     }
 
-    public void finish() {
-        this.setFinished(new Date());
-
-        try {
-            Session session = HibernateUtil.getSessionFactory().openSession();
-            Transaction transaction = session.beginTransaction();
-            session.update(this);
-            transaction.commit();
-            session.close();
-        } catch (DataException e) {
-            LOGGER.trace(e);
-            throw e;
-        }
-    }
-
     public String getValidations() {
         return validations;
     }
diff --git a/src/main/java/org/hbp/mip/repositories/AppRepository.java b/src/main/java/org/hbp/mip/repositories/AppRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba00367afe2b6419d61f1a810b5f21acfb7596f6
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/AppRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.App;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface AppRepository extends CrudRepository<App, Integer> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/ArticleRepository.java b/src/main/java/org/hbp/mip/repositories/ArticleRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..b27ecfaa4d7d44a66d7f80e065f06df545a69dfd
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/ArticleRepository.java
@@ -0,0 +1,15 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Article;
+import org.hbp.mip.model.User;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface ArticleRepository extends CrudRepository<Article, String> {
+    Long countByTitle(String title);
+    Iterable<Article> findByCreatedBy(User user);
+    Iterable<Article> findByStatusOrCreatedBy(String status, User user);
+}
diff --git a/src/main/java/org/hbp/mip/repositories/ConfigRepository.java b/src/main/java/org/hbp/mip/repositories/ConfigRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..f54f379144b1769eda2bca8db2b9be623c98fd06
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/ConfigRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Config;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface ConfigRepository extends CrudRepository<Config, Long> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/DatasetRepository.java b/src/main/java/org/hbp/mip/repositories/DatasetRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..53883eb21f504b1fcd90178b44d1105785129fba
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/DatasetRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Dataset;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface DatasetRepository extends CrudRepository<Dataset, String> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/ExperimentRepository.java b/src/main/java/org/hbp/mip/repositories/ExperimentRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..3815879beab40747df7fba83f2a96d950af3ece9
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/ExperimentRepository.java
@@ -0,0 +1,16 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Experiment;
+import org.hbp.mip.model.User;
+import org.springframework.data.repository.CrudRepository;
+
+import java.util.UUID;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface ExperimentRepository extends CrudRepository<Experiment, UUID> {
+    Iterable<Experiment> findByCreatedBy(User user);
+    Iterable<Experiment> findByShared(Boolean shared);
+}
diff --git a/src/main/java/org/hbp/mip/repositories/FilterRepository.java b/src/main/java/org/hbp/mip/repositories/FilterRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f4a1556924d00bbd33fd92135169f176fe749e6
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/FilterRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Filter;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface FilterRepository extends CrudRepository<Filter, Long> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/GroupRepository.java b/src/main/java/org/hbp/mip/repositories/GroupRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..548653269f2c788bef529e1748b4b9fdca04126d
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/GroupRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Group;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface GroupRepository extends CrudRepository<Group, String> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/ModelRepository.java b/src/main/java/org/hbp/mip/repositories/ModelRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..9da1df5bd11936471fde140ce86b60689c5a499c
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/ModelRepository.java
@@ -0,0 +1,15 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Model;
+import org.hbp.mip.model.User;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface ModelRepository extends CrudRepository<Model, String> {
+    Long countByTitle(String Title);
+    Iterable<Model> findByCreatedByOrderByCreatedAt(User user);
+    Iterable<Model> findByValidOrCreatedByOrderByCreatedAt(Boolean valid, User user);
+}
diff --git a/src/main/java/org/hbp/mip/repositories/QueryRepository.java b/src/main/java/org/hbp/mip/repositories/QueryRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..44dc9527b480447e28205322e87e7a962f09f285
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/QueryRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Query;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface QueryRepository extends CrudRepository<Query, Long> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/TagRepository.java b/src/main/java/org/hbp/mip/repositories/TagRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..155d65d17170b6171170a3b41ae12f981cf9fbf0
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/TagRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Tag;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface TagRepository extends CrudRepository<Tag, String> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/UserRepository.java b/src/main/java/org/hbp/mip/repositories/UserRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..04338433fe84ada90f446232715c71d63ba904f4
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/UserRepository.java
@@ -0,0 +1,12 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.User;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface UserRepository extends CrudRepository<User, String> {
+
+}
diff --git a/src/main/java/org/hbp/mip/repositories/ValueRepository.java b/src/main/java/org/hbp/mip/repositories/ValueRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3b088462874f72489c507576aa9fb9ce5d221fc
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/ValueRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Value;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface ValueRepository extends CrudRepository<Value, String> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/VariableRepository.java b/src/main/java/org/hbp/mip/repositories/VariableRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac241ca7a16f06b75e7c2135724675bcafecefaa
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/VariableRepository.java
@@ -0,0 +1,11 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.Variable;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface VariableRepository extends CrudRepository<Variable, String> {
+}
diff --git a/src/main/java/org/hbp/mip/repositories/VoteRepository.java b/src/main/java/org/hbp/mip/repositories/VoteRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..78d760b9cb998b65a444d3472bbf3326a3052979
--- /dev/null
+++ b/src/main/java/org/hbp/mip/repositories/VoteRepository.java
@@ -0,0 +1,14 @@
+package org.hbp.mip.repositories;
+
+import org.hbp.mip.model.App;
+import org.hbp.mip.model.User;
+import org.hbp.mip.model.Vote;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Created by mirco on 11.07.16.
+ */
+
+public interface VoteRepository extends CrudRepository<Vote, Long> {
+    Iterable<Vote> findByUserAndApp(User user, App app);
+}
diff --git a/src/main/java/org/hbp/mip/utils/CSVUtil.java b/src/main/java/org/hbp/mip/utils/CSVUtil.java
index b3f6850be795983ec8728624da7dfcf733369dfe..a91d390ce42533abaef1f65f00aab7ca9e57a394 100644
--- a/src/main/java/org/hbp/mip/utils/CSVUtil.java
+++ b/src/main/java/org/hbp/mip/utils/CSVUtil.java
@@ -4,7 +4,8 @@ import org.apache.log4j.Logger;
 import org.hbp.mip.model.Dataset;
 import org.hbp.mip.model.Query;
 import org.hbp.mip.model.Variable;
-import org.hibernate.Session;
+import org.hbp.mip.repositories.VariableRepository;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -24,13 +25,10 @@ public class CSVUtil {
 
     private static final String SEPARATOR = ",";
 
-    private CSVUtil()
-    {
-        /* Hide implicit public constructor */
-        throw new IllegalAccessError("CSVUtil class");
-    }
+    @Autowired
+    VariableRepository variableRepository;
 
-    public static Dataset parseValues(String filename, Query query)
+    public Dataset parseValues(String filename, Query query)
     {
         List<String[]> rows = getRows(filename);
 
@@ -161,7 +159,7 @@ public class CSVUtil {
         return result;
     }
 
-    private static List<String[]> getRows(String filename) {
+    private List<String[]> getRows(String filename) {
         List<String[]> rows = new LinkedList<>();
         try {
             InputStream is = CSVUtil.class.getClassLoader().getResourceAsStream(filename);
@@ -183,7 +181,7 @@ public class CSVUtil {
         return rows;
     }
 
-    private static int find(String code, String[] firstRow) {
+    private int find(String code, String[] firstRow) {
         for (int i = 0; i < firstRow.length; i++) {
             if (firstRow[i].equals(code))
                 return i;
@@ -191,7 +189,7 @@ public class CSVUtil {
         return -1;
     }
 
-    private static String generateDSCode(Query query) {
+    private String generateDSCode(Query query) {
         String prefix = "DS";
         String queryStr = Integer.toString(query.hashCode());
         String memId;
@@ -206,24 +204,9 @@ public class CSVUtil {
         return prefix + memId;
     }
 
-    private static String getTypeFromDB(Variable v)
+    private String getTypeFromDB(Variable v)
     {
-        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-        String type = null;
-        try{
-            session.beginTransaction();
-            org.hibernate.Query q = session.createQuery("SELECT type FROM Variable where code= :code").setString("code", v.getCode());
-            type = (String) q.uniqueResult();
-            session.getTransaction().commit();
-        } catch (Exception e)
-        {
-            if(session.getTransaction() != null)
-            {
-                session.getTransaction().rollback();
-                throw e;
-            }
-        }
-
+        String type = variableRepository.findOne(v.getCode()).getType();
         if(type == null)
         {
             type = "unknown";
diff --git a/src/main/java/org/hbp/mip/utils/CustomLoginUrlAuthenticationEntryPoint.java b/src/main/java/org/hbp/mip/utils/CustomLoginUrlAuthenticationEntryPoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..437052aa882be5f901a312cd269b58578c2b4d0b
--- /dev/null
+++ b/src/main/java/org/hbp/mip/utils/CustomLoginUrlAuthenticationEntryPoint.java
@@ -0,0 +1,21 @@
+package org.hbp.mip.utils;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
+
+    public CustomLoginUrlAuthenticationEntryPoint(String url) {
+        super(url);
+    }
+
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+    }
+}
diff --git a/src/main/java/org/hbp/mip/utils/HibernateUtil.java b/src/main/java/org/hbp/mip/utils/HibernateUtil.java
deleted file mode 100644
index 87cde9618993e4070518b70d2bf6e4d058d54760..0000000000000000000000000000000000000000
--- a/src/main/java/org/hbp/mip/utils/HibernateUtil.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Created by mirco on 07.12.15.
- */
-
-package org.hbp.mip.utils;
-
-import org.apache.log4j.Logger;
-import org.hibernate.SessionFactory;
-import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
-import org.hibernate.cfg.Configuration;
-import org.hibernate.service.ServiceRegistry;
-
-public class HibernateUtil {
-
-    private static final Logger LOGGER = Logger.getLogger(CSVUtil.class);
-
-    private static ServiceRegistry serviceRegistry;
-
-    private static SessionFactory sessionFactory = buildSessionFactory();
-
-    private HibernateUtil() {
-        /* Hide implicit public constructor */
-        throw new IllegalAccessError("HibernateUtil class");
-    }
-
-    private static SessionFactory buildSessionFactory() {
-        try {
-            Configuration configuration = new Configuration();
-            configuration.configure();
-            serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
-                    configuration.getProperties()).build();
-            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
-            return sessionFactory;
-        } catch (RuntimeException ex) {
-            LOGGER.error("Initial SessionFactory creation failed." + ex);
-            throw new ExceptionInInitializerError(ex);
-        }
-    }
-
-    public static SessionFactory getSessionFactory() {
-        return sessionFactory;
-    }
-}
diff --git a/src/main/resources/db/migration/V1_1__Create.sql b/src/main/resources/db/migration/V1_1__Create.sql
index 777f0f39d32b319df4f56f30dcc85b2642c6bbcf..2dfa346e9efffbe82f6dd3fc6107601ae27918b9 100644
--- a/src/main/resources/db/migration/V1_1__Create.sql
+++ b/src/main/resources/db/migration/V1_1__Create.sql
@@ -66,7 +66,7 @@ ALTER TABLE app OWNER TO postgres;
 
 CREATE TABLE article (
     slug character varying(255) NOT NULL,
-    _abstract text,
+    abstract text,
     content text,
     createdat timestamp without time zone,
     publishedat timestamp without time zone,
diff --git a/src/main/resources/hibernate.cfg.xml b/src/main/resources/hibernate.cfg.xml
deleted file mode 100644
index e769d47db76d641651c9a209b8a98bdd18142625..0000000000000000000000000000000000000000
--- a/src/main/resources/hibernate.cfg.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!DOCTYPE hibernate-configuration PUBLIC
-        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
-        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
-
-<hibernate-configuration>
-    <session-factory>
-        <property name="connection.driver_class">${connection.driver_class}</property>
-        <property name="connection.url">${connection.url}</property>
-        <property name="connection.username">${connection.username}</property>
-        <property name="connection.password">${connection.password}</property>
-        <property name="hibernate.format_sql">true</property>
-        <property name="connection.pool_size">1</property>
-        <property name="hibernate.dialect">${hibernate.dialect}</property>
-        <property name="current_session_context_class">thread</property>
-        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
-        <property name="hibernate.show_sql">false</property>
-        <property name="hibernate.hbm2ddl.auto">update</property>
-
-        <mapping class="org.hbp.mip.model.Article"/>
-        <mapping class="org.hbp.mip.model.Dataset"/>
-        <mapping class="org.hbp.mip.model.Model"/>
-        <mapping class="org.hbp.mip.model.Experiment"/>
-        <mapping class="org.hbp.mip.model.Query"/>
-        <mapping class="org.hbp.mip.model.Tag"/>
-        <mapping class="org.hbp.mip.model.User"/>
-        <mapping class="org.hbp.mip.model.Value"/>
-        <mapping class="org.hbp.mip.model.Variable"/>
-        <mapping class="org.hbp.mip.model.Filter"/>
-        <mapping class="org.hbp.mip.model.Group"/>
-        <mapping class="org.hbp.mip.model.Config"/>
-        <mapping class="org.hbp.mip.model.App"/>
-        <mapping class="org.hbp.mip.model.Vote"/>
-
-    </session-factory>
-</hibernate-configuration>
diff --git a/src/main/resources/spring/application-context.xml b/src/main/resources/spring/application-context.xml
deleted file mode 100644
index 9d283991f37a1e72277f9b85d8905b9f45725da8..0000000000000000000000000000000000000000
--- a/src/main/resources/spring/application-context.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?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"
-	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-4.2.xsd">
-	
-	<context:component-scan base-package="org.hbp.mip" />
-
-	<bean id="httpSessionCsrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository">
-		<property name="headerName" value="X-XSRF-TOKEN" />
-	</bean>
-	
-	<bean id="hbpFilter" class="org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter">
-		<constructor-arg value="/login/hbp"></constructor-arg>
-		<property name="authenticationSuccessHandler">
-			<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
-				<property name="defaultTargetUrl" value="${frontend.redirect}" />
-			</bean>
-		</property>
-		<property name="restTemplate">
-			<bean class="org.springframework.security.oauth2.client.OAuth2RestTemplate">
-				<constructor-arg name="resource" ref="hbp" />
-				<constructor-arg name="context" ref="oauth2ClientContext" />
-			</bean>
-		</property>
-		<property name="tokenServices">
-			<bean class="org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices">
-				<constructor-arg name="clientId" value="996f97c5-a3ca-460e-b18b-00df3e2be89a" />
-				<constructor-arg name="userInfoEndpointUrl" value="https://services.humanbrainproject.eu/oidc/userinfo" />
-			</bean>
-		</property>
-	</bean>
-	
-
-</beans>
diff --git a/src/test/java/org/hbp/mip/MIPApplicationTests.java b/src/test/java/org/hbp/mip/MIPApplicationTests.java
index bfe9832163384494b33694d93d0223c35cba6c12..3beac4281a34611ace1b20b0fcc9c4822afe96d3 100644
--- a/src/test/java/org/hbp/mip/MIPApplicationTests.java
+++ b/src/test/java/org/hbp/mip/MIPApplicationTests.java
@@ -15,13 +15,20 @@
  */
 package org.hbp.mip;
 
+import org.junit.Assert;
+import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.context.support.GenericXmlContextLoader;
 
 @RunWith(SpringJUnit4ClassRunner.class)
-@WebAppConfiguration
-@SpringApplicationConfiguration(classes=MIPApplication.class, locations={"classpath:spring/application-context.xml"})
+@ContextConfiguration(loader = GenericXmlContextLoader.class)
 public class MIPApplicationTests {
+
+    @Test
+    public void testHello()
+    {
+        Assert.assertNotNull("test");
+    }
 }
diff --git a/start.bat b/start.bat
deleted file mode 100644
index af12a1b5207ddf687faaa0fd0f34405c1f966ed3..0000000000000000000000000000000000000000
--- a/start.bat
+++ /dev/null
@@ -1 +0,0 @@
-start java -jar target\backend-services-0.0.1-SNAPSHOT.jar  --spring.config.location=config\application.yml
\ No newline at end of file
diff --git a/stop.sh b/stop.sh
deleted file mode 100755
index 3bc6146acfc2c199f78ff4ceb66ae10aaf91ab51..0000000000000000000000000000000000000000
--- a/stop.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-if groups $USER | grep &>/dev/null '\bdocker\b'; then
-  DOCKER_COMPOSE="docker-compose"
-else
-  DOCKER_COMPOSE="sudo docker-compose"
-fi
-
-$DOCKER_COMPOSE rm -f