diff --git a/Dockerfile b/Dockerfile
index 458fbc8a353233f0bda3dbff9be8b421d7fbaf5b..866c01bf47a4cff2589e9298b166d5b374fbe62b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -43,17 +43,16 @@ WORKDIR /home/portal
 ENTRYPOINT ["/run.sh"]
 
 # 8080: Web service API, health checks on http://host:8080$CONTEXT_PATH/health
-# 4089: Akka cluster
-EXPOSE 4089 8080
+EXPOSE 8080
 
 HEALTHCHECK --start-period=60s CMD curl -v --silent http://localhost:8080$CONTEXT_PATH/health 2>&1 | grep UP
 
 LABEL org.label-schema.build-date=$BUILD_DATE \
       org.label-schema.name="hbpmip/portal-backend" \
-      org.label-schema.description="Java backend for the MIP portal" \
+      org.label-schema.description="Spring backend for the MIP portal" \
       org.label-schema.url="https://mip.humanbrainproject.eu" \
       org.label-schema.vcs-type="git" \
-      org.label-schema.vcs-url="https://github.com/LREN-CHUV/portal-backend" \
+      org.label-schema.vcs-url="https://github.com/HBPMedical/portal-backend" \
       org.label-schema.vcs-ref=$VCS_REF \
       org.label-schema.version="$VERSION" \
       org.label-schema.vendor="LREN CHUV" \
diff --git a/build.sh b/build.sh
index ef4f10565705b3eb3d0fae54b60de23671f356bf..6a18d98ecec05885651675049490ca44c990ec7f 100755
--- a/build.sh
+++ b/build.sh
@@ -26,7 +26,7 @@ else
   DOCKER="sudo docker"
 fi
 
-IMAGE="hbpmip/portal-backend"
+IMAGE="kfilippopolitis/portal-backend"
 VCS_REF=$(git describe --tags --dirty)
 VERSION=$(git describe --tags --dirty)
 
diff --git a/docker/README.md b/docker/README.md
index 3f3437aec65ab4cc28b6236bf31a305b79572ea5..9636ff324e43b29c67fa367165370bbbf5c3a5f7 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -7,69 +7,33 @@
 To use this image, you need a running instance of PostgreSQL and to configure the software using the following environment variables.
 
 
-### DATABASES
-
-* PORTAL_DB_URL: JDBC URL to connect to the portal database, default value is "jdbc:postgresql://172.22.0.1:5432/portal".
-* PORTAL_DB_SCHEMA: Database schema, default value is "public".
-* PORTAL_DB_USER: User to use when connecting to the portal database, default value is "postgres".
-* PORTAL_DB_PASSWORD: Password to use when connecting to the portal database.
-
-* META_DB_URL: JDBC URL to connect to the metadata database, default value is "jdbc:postgresql://172.22.0.1:5432/meta".
-* META_DB_SCHEMA: Database schema, default value is "public".
-* META_DB_USER: User to use when connecting to the metadata database.
-* META_DB_PASSWORD: Password to use when connecting to the metadata database.
-
-* FEATURES_DB_URL: JDBC URL to connect to the science database, default value is "jdbc:postgresql://172.22.0.1:5433/features".
-* FEATURES_DB_SCHEMA: Database schema, default value is "public".
-* FEATURES_DB_USER: User to use when connecting to the science database, default value is "postgres".
-* FEATURES_DB_PASSWORD: Password to use when connecting to the science database.
-* FEATURES_DB_MAIN_TABLE: Table that contains the scientific data to use, default value is "features".
-
-
-### OAUTH2 LOGIN
-
-* AUTHENTICATION: "0" to disable authentication or "1" to enable authentication, default value is "1".
-* CLIENT_ID: required when authentication is turned on, client ID for the [OpenID server of HBP](https://services.humanbrainproject.eu/oidc/).
-* CLIENT_SECRET: required when authentication is turned on, client secret for the [OpenID server of HBP](https://services.humanbrainproject.eu/oidc/).
-* TOKEN_URI: default to "https://services.humanbrainproject.eu/oidc/token".
-* AUTH_URI: default to "https://services.humanbrainproject.eu/oidc/authorize".
-* USER_INFO_URI: default to "https://services.humanbrainproject.eu/oidc/userinfo".
-* REVOKE_TOKEN_URI "https://services.humanbrainproject.eu/oidc/slo".
-
-
-### WEB FRONTEND
-
-* FRONTEND_LOGIN_URL: URL to redirect to when login is required. Default to "http://frontend/services/login/hbp".
-* FRONTEND_AFTER_LOGIN_URL: URL to redirect after login. Default to "http://frontend/home".
-* FRONTEND_AFTER_LOGOUT_URL: URL to redirect to after logout. Default to "http://frontend/services/login/hbp".
-
-
-### LOGGING
-
+### LOG LEVELS ###
 * LOG_LEVEL: log level for the developer added logs. Default is "ERROR".
 * LOG_LEVEL_FRAMEWORK: log level for all the framework logs. Default is "ERROR".
 
 
-### ENDPOINTS
+### AUTHENTICATION ###
+* AUTHENTICATION: true for production, false for development.
 
-* EXAREME_URL: URL to Exareme server, default value is "http://hbps2.chuv.ch:9090".
-* WORKFLOW_URL: URL to Workflow server
-* JWT_SECRET: "secret"
 
-### EMBEDDED SERVER CONFIGURATION
+### DATABASE CONFIGURATION ###
+* PORTAL_DB_URL: JDBC URL to connect to the portal database, default value is "jdbc:postgresql://127.0.0.1:5432/portal".
+* PORTAL_DB_SCHEMA: Database schema, default value is "public".
+* PORTAL_DB_USER: User to use when connecting to the portal database, default value is "postgres".
+* PORTAL_DB_PASSWORD: Password to use when connecting to the portal database.
 
-* CONTEXT_PATH:  context path appended to all services running in this container. Default to "/services".
-* SESSION_TIMEOUT: Timeout in milliseconds for session expiration. Default to 2592000.
 
-### PROXY
+### EXTERNAL SERVICES ###
+* EXAREME_URL: URL to Exareme server. Default is "http://localhost:9090" .
 
-* HTTP_PROXY_HOST: HTTP proxy host
-* HTTP_PROXY_PORT: HTTP proxy port
-* HTTPS_PROXY_HOST: HTTPS proxy host
-* HTTPS_PROXY_PORT: HTTPS proxy port
+* GALAXY_URL: URL to Workflow server. Default is "http://localhost:8090/" .
+* GALAXY_API_KEY: The api key to authorize galaxy requests.
+* GALAXY_USERNAME: The username of galaxy user to be able to embed the frame.
+* GALAXY_PASSWORD: The password of galaxy user.
 
-## ERROR REPORTING
 
-* RELEASE_STAGE: Release stage used when reporting errors to Bugsnag. Values are dev, staging, production
-* DATA_CENTER_LOCATION: Location of the datacenter, used when reporting errors to Bugsnag
-* CONTAINER_ORCHESTRATION: Container orchestration system used to execute the Docker containers. Values are mesos, docker-compose, kubernetes
+### KEYCLOAK ###
+* KEYCLOAK_AUTH_URL: Keycloak authentication URL.
+* KEYCLOAK_REALM: Keycloak realm user for authentication.
+* KEYCLOAK_CLIENT_ID: The keycloak client id.
+* KEYCLOAK_CLIENT_SECRET: The keycloak secret to be able to authenticate.
\ No newline at end of file
diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl
index 13fc6577970ede925089895265e8a3f6b0a409ae..ae10744aa2424e7421da83da173d6e662608e843 100644
--- a/docker/config/application.tmpl
+++ b/docker/config/application.tmpl
@@ -1,14 +1,27 @@
 # Configuration template for the portal running inside a Docker container
 
-# See http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+### LOG LEVELS ###
+logging:
+  level:
+    root: {{ default .Env.LOG_LEVEL_FRAMEWORK "ERROR" }}
+    org: {{ default .Env.LOG_LEVEL_FRAMEWORK "ERROR" }}
+    eu:
+      hbp: {{ default .Env.LOG_LEVEL "INFO" }}
+
+
+### AUTHENTICATION ###
+authentication:
+  enabled: {{ default .Env.AUTHENTICATION "true" }}
+
+
+### DATABASE CONFIGURATION ###
 spring:
-  portalDatasource:
-    url: {{ default .Env.PORTAL_DB_URL "jdbc:postgresql://172.22.0.1:5432/portal" }}
+  portal-datasource:
+    url: {{ default .Env.PORTAL_DB_URL "jdbc:postgresql://88.197.53.106:5432/portal" }}
     schema: {{ default .Env.PORTAL_DB_SCHEMA "public" }}
     username: {{ default .Env.PORTAL_DB_USER "postgres" }}
     password: {{ .Env.PORTAL_DB_PASSWORD }}
     driver-class-name: org.postgresql.Driver
-
   data:
     jpa:
       repositories:
@@ -16,60 +29,10 @@ spring:
   jpa:
     hibernate:
       dialect: org.hibernate.dialect.PostgreSQL9Dialect
-  # SPRING RESOURCES HANDLING
-  resources:
-    chain:
-      enabled: true # TODO: why is that enabled? Do we serve any resources from the backend?
+      ddl-auto: validate
 
-# HBP OAUTH2 LOGIN
-hbp:
-  authentication:
-    enabled: {{ default .Env.AUTHENTICATION "1" }}
-  client:
-    clientId: {{ default .Env.CLIENT_ID "996f97c5-a3ca-460e-b18b-00df3e2be89a" }}
-    clientSecret: {{ .Env.CLIENT_SECRET }}
-    accessTokenUri: {{ default .Env.TOKEN_URI "https://services.humanbrainproject.eu/oidc/token" }}
-    userAuthorizationUri: {{ default .Env.AUTH_URI "https://services.humanbrainproject.eu/oidc/authorize" }}
-    logoutUri: {{ .Env.LOGOUT_URI }}
-    tokenName: access_token
-    authenticationScheme: query
-    clientAuthenticationScheme: form
-    useCurrentUri: false
-    preEstablishedRedirectUri: {{ default .Env.FRONTEND_LOGIN_URL "http://frontend/services/login/hbp" }}
-  resource:
-    userInfoUri: {{ default .Env.USER_INFO_URI "https://services.humanbrainproject.eu/oidc/userinfo" }}
-    revokeTokenUri: {{ default .Env.REVOKE_TOKEN_URI "https://services.humanbrainproject.eu/oidc/slo" }}
-  sso:
-    login-path:
-
-# WEB FRONTEND
-frontend:
-  loginUrl: {{ default .Env.FRONTEND_LOGIN_URL "http://frontend/services/login/hbp" }}
-  redirectAfterLogoutUrl: {{ default .Env.FRONTEND_AFTER_LOGOUT_URL (default .Env.LOGIN_URI "http://frontend/services/login/hbp") }}
-  redirectAfterLoginUrl: {{ default .Env.FRONTEND_AFTER_LOGIN_URL "http://frontend/home" }}
-  
-logging:
-  level:
-    root: {{ default .Env.LOG_LEVEL_FRAMEWORK "ERROR" }}
-    eu:
-      hbp: {{ default .Env.LOG_LEVEL "INFO" }}
-
-# EMBEDDED SERVER CONFIGURATION
-server:
-  contextPath: {{ default .Env.CONTEXT_PATH "/services" }}
-  port: 8080
-  use-forward-headers: true
-  session:
-    timeout: {{ default .Env.SESSION_TIMEOUT "2592000" }}
-
-# ENDPOINTS
-endpoints:
-  enabled: true
-  health:
-    enabled: true
-    endpoint: /health
-    sensitive: false
 
+### EXTERNAL SERVICES ###
 services:
   exareme:
     queryExaremeUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/query
@@ -77,10 +40,43 @@ services:
 
   galaxy:
     galaxyUrl:      {{ default .Env.GALAXY_URL "http://localhost:8090/" }}
-    galaxyContext:  {{ default .Env.GALAXY_CONTEXT "nativeGalaxy/workflows/list" }}
+    galaxyContext:  "nativeGalaxy/workflows/list"
     galaxyApiKey:   {{ .Env.GALAXY_API_KEY }}
     galaxyUsername:  {{ default .Env.GALAXY_USERNAME "admin" }}
     galaxyPassword:  {{ default .Env.GALAXY_PASSWORD "password" }}
 
-  keycloak:
-    keycloakUrl: {{ .Env.KEYCLOAK_URL }}
+
+### KEYCLOAK ###
+keycloak:
+  enabled: true
+  auth-server-url: {{ .Env.KEYCLOAK_AUTH_URL }}
+  realm: {{ .Env.KEYCLOAK_REALM }}
+  resource: {{ .Env.KEYCLOAK_CLIENT_ID }}
+  enable-basic-auth: true
+  credentials:
+    secret: {{ .Env.KEYCLOAK_CLIENT_SECRET }}
+  principal-attribute: "preferred_username"
+  ssl-required: none
+
+### EXTERNAL FILES ###
+# Files are imported when building the docker image
+files:
+  pathologies_json: "file:/opt/portal/api/pathologies.json"
+  disabledAlgorithms_json: "file:/opt/portal/api/disabledAlgorithms.json"
+
+
+### EMBEDDED SERVER CONFIGURATION ###
+server:
+  servlet:
+    contextPath: "/services"
+  port: 8080
+  forward-headers-strategy: native
+
+
+### ENDPOINTS ###
+endpoints:
+  enabled: true
+  health:
+    enabled: true
+    endpoint: /health
+    sensitive: false
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 20a6f066122779eab771ca0d012dbcc4a8e8a208..d92ff1f2dd22cd477f702ec2486f675c117c39c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,27 +14,25 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>1.3.8.RELEASE</version>
-        <relativePath/>
-
+        <version>2.3.5.RELEASE</version>
     </parent>
 
     <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <sonar.host.url>https://hbps1.chuv.ch/sonarqube/</sonar.host.url>
-        <sonar.projectName>MIP portal-backend</sonar.projectName>
-        <sonar.sources>src/main/java/</sonar.sources>
         <java.version>1.8</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <keycloak-spring.version>11.0.2</keycloak-spring.version>
+        <springfox-swagger.version>2.5.0</springfox-swagger.version>
+        <spring-context.version>5.2.10.RELEASE</spring-context.version>
+        <springfox-boot-starter.version>3.0.0</springfox-boot-starter.version>
         <asciidoctor.maven.plugin.version>1.5.5</asciidoctor.maven.plugin.version>
         <asciidoctorj.pdf.version>1.5.0-alpha.15</asciidoctorj.pdf.version>
         <asciidoctorj.version>1.5.5</asciidoctorj.version>
-        <spring-data-commons.version>1.12.3.RELEASE</spring-data-commons.version>
         <angularjs.version>1.5.7</angularjs.version>
         <jquery.version>3.0.0</jquery.version>
         <bootstrap.version>3.3.7</bootstrap.version>
+        <webjars-locator.version>0.36</webjars-locator.version>
         <h2.version>1.4.192</h2.version>
         <postgresql.version>42.2.1</postgresql.version>
-        <springfox-swagger.version>2.5.0</springfox-swagger.version>
         <gson.version>2.7</gson.version>
         <slugify.version>2.1.5</slugify.version>
         <maven-resources-plugin.version>3.0.1</maven-resources-plugin.version>
@@ -42,15 +40,13 @@
         <swagger2markup-maven-plugin.version>1.0.0</swagger2markup-maven-plugin.version>
         <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
         <hibernate4-maven-plugin.version>1.1.1</hibernate4-maven-plugin.version>
+        <commons-dbcp.version>2.7.0</commons-dbcp.version>
         <flyway-core.version>4.2.0</flyway-core.version>
         <hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
-        <hibernate.version>4.3.11.Final</hibernate.version>
-        <spring-data-jpa.version>1.10.11.RELEASE</spring-data-jpa.version>
-        <spring-boot-starter-actuator.version>1.4.7.RELEASE</spring-boot-starter-actuator.version>
+        <hibernate.version>5.4.10.Final</hibernate.version>
+        <hibernate-validator.version>6.1.0.Final</hibernate-validator.version>
         <aspectjweaver.version>1.8.9</aspectjweaver.version>
         <javax-inject.version>1</javax-inject.version>
-        <akka.version>2.5.22</akka.version>
-        <spring-context.version>4.3.4.RELEASE</spring-context.version>
         <protobuf-java.version>3.1.0</protobuf-java.version>
     </properties>
 
@@ -66,32 +62,39 @@
     </repositories>
 
     <dependencies>
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-actuator</artifactId>
-            <version>${spring-boot-starter-actuator.version}</version>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-data-rest</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework.data</groupId>
-            <artifactId>spring-data-commons</artifactId>
-            <version>${spring-data-commons.version}</version>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-security</artifactId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework.security.oauth</groupId>
-            <artifactId>spring-security-oauth2</artifactId>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-spring-boot-starter</artifactId>
+            <version>${keycloak-spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-spring-security-adapter</artifactId>
+            <version>${keycloak-spring.version}</version>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
@@ -115,6 +118,7 @@
         <dependency>
             <groupId>org.webjars</groupId>
             <artifactId>webjars-locator</artifactId>
+            <version>${webjars-locator.version}</version>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -131,6 +135,11 @@
             <artifactId>hibernate-core</artifactId>
             <version>${hibernate.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>${hibernate-validator.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-entitymanager</artifactId>
@@ -148,13 +157,8 @@
         </dependency>
         <dependency>
             <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger2</artifactId>
-            <version>${springfox-swagger.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger-ui</artifactId>
-            <version>${springfox-swagger.version}</version>
+            <artifactId>springfox-boot-starter</artifactId>
+            <version>${springfox-boot-starter.version}</version>
         </dependency>
         <dependency>
             <groupId>com.google.code.gson</groupId>
@@ -169,11 +173,11 @@
         <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>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-dbcp2</artifactId>
+            <version>${commons-dbcp.version}</version>
         </dependency>
         <dependency>
             <groupId>org.flywaydb</groupId>
@@ -185,16 +189,15 @@
             <artifactId>aspectjweaver</artifactId>
             <version>${aspectjweaver.version}</version>
         </dependency>
-        
         <dependency>
             <groupId>javax.inject</groupId>
             <artifactId>javax.inject</artifactId>
             <version>${javax-inject.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
-            <version>${spring.version}</version>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-context</artifactId>
+        <version>${spring-context.version}</version>
         </dependency>
         <dependency>
             <groupId>com.google.protobuf</groupId>
@@ -209,60 +212,70 @@
         <dependency>
             <groupId>org.glassfish.jaxb</groupId>
             <artifactId>jaxb-runtime</artifactId>
-            <version>2.4.0-b180830.0438</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>com.auth0</groupId>
-            <artifactId>java-jwt</artifactId>
-            <version>3.8.3</version>
+            <version>3.0.0-M4</version>
         </dependency>
-
         <!-- https://mvnrepository.com/artifact/com.github.jmchilton.blend4j/blend4j -->
         <dependency>
             <groupId>com.github.jmchilton.blend4j</groupId>
             <artifactId>blend4j</artifactId>
             <version>0.2.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.squareup.retrofit2</groupId>
             <artifactId>retrofit</artifactId>
-            <version>2.5.0</version>
+            <version>2.9.0</version>
         </dependency>
-
         <!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/converter-gson -->
         <dependency>
             <groupId>com.squareup.retrofit2</groupId>
             <artifactId>converter-gson</artifactId>
-            <version>2.4.0</version>
+            <version>2.9.0</version>
         </dependency>
-
         <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/logging-interceptor -->
         <dependency>
             <groupId>com.squareup.okhttp3</groupId>
             <artifactId>logging-interceptor</artifactId>
-            <version>3.12.1</version>
         </dependency>
-
         <dependency>
             <groupId>com.auth0</groupId>
             <artifactId>java-jwt</artifactId>
-            <version>3.8.3</version>
+            <version>3.11.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.svenson</groupId>
+            <artifactId>svenson</artifactId>
+            <version>1.5.8</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.16</version>
+            <scope>provided</scope>
         </dependency>
+
     </dependencies>
 
-    <build>
-        <finalName>portal-backend</finalName>
-        <resources>
+   <build>
+       <finalName>portal-backend</finalName>
+       <resources>
+           <resource>
+               <directory>src/main/resources</directory>
+               <includes>
+                   <include>**/*.xml</include>
+                   <include>**/*.json</include>
+                   <include>**/*.csv</include>
+                   <include>**/*.sql</include>
+                   <include>**/*.conf</include>
+                   <include>**/*.yml</include>    <!--   Only for development -->
+                </includes>
+                <filtering>true</filtering>
+            </resource>
+
+            <!-- Used for development. Docker/config folder files added as resources -->
             <resource>
-                <directory>src/main/resources</directory>
+                <directory>config</directory>
                 <includes>
-                    <include>**/*.xml</include>
-                    <include>**/*.json</include>
-                    <include>**/*.csv</include>
-                    <include>**/*.sql</include>
-                    <include>**/*.conf</include>
+                    <include>*.json</include>
                 </includes>
                 <filtering>true</filtering>
             </resource>
diff --git a/src/main/java/eu/hbp/mip/MIPApplication.java b/src/main/java/eu/hbp/mip/MIPApplication.java
index 9af69bdd9cdc04e555a24f8a0ca4e7b3882206ed..f4001f93c477307cf0d464f76e8b22b2905af198 100644
--- a/src/main/java/eu/hbp/mip/MIPApplication.java
+++ b/src/main/java/eu/hbp/mip/MIPApplication.java
@@ -7,17 +7,12 @@ package eu.hbp.mip;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @SpringBootApplication
 public class MIPApplication {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(MIPApplication.class);
-
     public static void main(String[] args) {
         SpringApplication.run(MIPApplication.class, args);
     }
 
-
 }
diff --git a/src/main/java/eu/hbp/mip/configuration/CacheConfiguration.java b/src/main/java/eu/hbp/mip/configuration/CacheConfiguration.java
deleted file mode 100644
index b7300fc257fcef4afd29421d8ccef64aeb0a11dd..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/configuration/CacheConfiguration.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.hbp.mip.configuration;
-
-import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Created by mirco on 07.11.16.
- */
-
-@Configuration
-@EnableCaching
-public class CacheConfiguration {
-}
diff --git a/src/main/java/eu/hbp/mip/configuration/PortalErrorAttributes.java b/src/main/java/eu/hbp/mip/configuration/PortalErrorAttributes.java
deleted file mode 100644
index 352b1d156558ef42b9862b644ed5668070899708..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/configuration/PortalErrorAttributes.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package eu.hbp.mip.configuration;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;
-import org.springframework.stereotype.Component;
-import org.springframework.web.context.request.RequestAttributes;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Component
-public class PortalErrorAttributes extends DefaultErrorAttributes {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(PortalErrorAttributes.class);
-
-    @Override
-    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
-        Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
-
-        Throwable throwable = getError(requestAttributes);
-        StringBuilder sb = new StringBuilder("[");
-        for (String attr : requestAttributes.getAttributeNames(RequestAttributes.SCOPE_REQUEST)) {
-            Object v = requestAttributes.getAttribute(attr, RequestAttributes.SCOPE_REQUEST);
-            sb.append(attr).append(" = ").append(v).append('\n');
-        }
-        sb.append("]");
-        LOGGER.error("Reporting server error on request with attributes " + sb.toString(), throwable);
-
-        if (throwable != null) {
-
-            Throwable cause = throwable.getCause();
-            if (cause != null) {
-                Map<String, Object> causeErrorAttributes = new HashMap<>();
-                causeErrorAttributes.put("exception", cause.getClass().getName());
-                causeErrorAttributes.put("message", cause.getMessage());
-                errorAttributes.put("cause", causeErrorAttributes);
-            }
-        }
-
-        return errorAttributes;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
deleted file mode 100644
index 4ea52570fd3bde8c8b21253fe202aa3fc61363d4..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
+++ /dev/null
@@ -1,343 +0,0 @@
-package eu.hbp.mip.configuration;
-
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.utils.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
-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.*;
-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.GrantedAuthority;
-import org.springframework.security.core.authority.AuthorityUtils;
-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.BaseOAuth2ProtectedResourceDetails;
-import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
-import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
-import org.springframework.security.web.access.channel.ChannelProcessingFilter;
-import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-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.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.filter.OncePerRequestFilter;
-import org.springframework.web.util.WebUtils;
-
-import javax.net.ssl.*;
-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.net.URI;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-
-// See https://spring.io/guides/tutorials/spring-boot-oauth2/ for reference about configuring OAuth2 login
-// also http://cscarioni.blogspot.ch/2013/04/pro-spring-security-and-oauth-2.html
-
-@Configuration
-@EnableOAuth2Client
-public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
-
-    @Autowired
-    private OAuth2ClientContext oauth2ClientContext;
-
-    /**
-     * Enable HBP collab authentication (1) or disable it (0). Default is 1
-     */
-    @Value("#{'${hbp.authentication.enabled:1}'}")
-    private boolean authentication;
-
-    /**
-     * Absolute URL to redirect to when login is required
-     */
-    @Value("#{'${frontend.loginUrl:/login/hbp}'}")
-    private String loginUrl;
-
-    /**
-     * Absolute URL to redirect to when logout is required
-     */
-    @Value("#{'${hbp.client.logoutUri}'}")
-    private String logoutUri;
-
-    /**
-     * Absolute URL to redirect to after successful login
-     */
-    @Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}")
-    private String frontendRedirectAfterLogin;
-
-    /**
-     * Absolute URL to redirect to after logout has occurred
-     */
-    @Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}")
-    private String redirectAfterLogoutUrl;
-
-    /**
-     * URL to revoke auth token
-     */
-    @Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
-    private String revokeTokenURI;
-
-    @Override
-    protected void configure(HttpSecurity http) throws Exception {
-        disableCertificateValidation();
-        // @formatter:off
-        http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
-
-        if (authentication) {
-            http.antMatcher("/**")
-                    .authorizeRequests()
-                    .antMatchers(
-                            "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**"
-                    )
-                    .permitAll()
-                    .antMatchers("/galaxy*", "/galaxy/*").hasRole("Data Manager")
-                    //.anyRequest().authenticated()
-                    .anyRequest().hasRole("Researcher")
-                    .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
-                    .accessDeniedHandler(new CustomAccessDeniedHandler())
-                    .and().logout().addLogoutHandler(authLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl)
-                    .and().logout().permitAll()
-                    .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
-                    .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
-                    .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
-        } else {
-            http.antMatcher("/**")
-                    .authorizeRequests()
-                    .antMatchers("/**").permitAll().and().csrf().disable();
-        }
-    }
-
-    private Filter ssoFilter() {
-        OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
-        OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
-        hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin));
-        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")
-    public BaseOAuth2ProtectedResourceDetails hbp() {
-        return new AuthorizationCodeResourceDetails();
-    }
-
-    @Bean(name = "hbpResource")
-    @ConfigurationProperties("hbp.resource")
-    public ResourceServerProperties hbpResource() {
-        return new ResourceServerProperties();
-    }
-
-    public boolean isAuthentication() {
-        return authentication;
-    }
-
-    public String getFrontendRedirectAfterLogin() {
-        return frontendRedirectAfterLogin;
-    }
-
-    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;
-    }
-
-    private class CustomLogoutHandler implements LogoutHandler {
-        @Override
-        public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
-
-            // Hackish way of accessing to this information...
-            final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
-            if (userInfo != null) {
-                userInfo.setFakeAuth(false);
-            }
-
-            if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null) {
-                return;
-            }
-
-            String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
-
-            StringBuilder query = new StringBuilder();
-            query.append("{");
-            query.append("\"token\":");
-            query.append("\"").append(idToken).append("\"");
-            query.append("}");
-
-            try {
-                int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder());
-                if (responseCode != 200) {
-                    LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
-                } else {
-                    LOGGER.info("Should be logged out");
-                }
-            } catch (IOException e) {
-                LOGGER.warn("Cannot notify logout to OIDC server !");
-                LOGGER.trace("Cannot notify logout", e);
-            }
-
-        }
-    }
-
-    @Bean
-    public AuthoritiesExtractor keycloakAuthoritiesExtractor() {
-        return new KeycloakAuthoritiesExtractor();
-    }
-
-
-    public class KeycloakAuthoritiesExtractor
-            implements AuthoritiesExtractor {
-
-        @Override
-        public List<GrantedAuthority> extractAuthorities
-                (Map<String, Object> map) {
-            return AuthorityUtils
-                    .commaSeparatedStringToAuthorityList(asAuthorities(map));
-        }
-
-        private String asAuthorities(Map<String, Object> map) {
-            List<String> authorities = new ArrayList<>();
-//            authorities.add("BAELDUNG_USER");
-            List<LinkedHashMap<String, String>> authz;
-            authz = (List<LinkedHashMap<String, String>>) map.get("authorities");
-            for (LinkedHashMap<String, String> entry : authz) {
-                authorities.add(entry.get("authority"));
-            }
-            return String.join(",", authorities);
-        }
-    }
-
-
-    private LogoutHandler authLogoutHandler() {
-        return (request, response, authentication) -> {
-            logout();
-        };
-    }
-
-
-    public void logout() {
-        // POSTするリクエストパラメーターを作成
-        RestTemplate restTemplate = new RestTemplate();
-        MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
-        formParams.add("client_id", hbp().getClientId());
-        formParams.add("client_secret", hbp().getClientSecret());
-        formParams.add("refresh_token", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
-        // リクエストヘッダーを作成
-        HttpHeaders httpHeaders = new HttpHeaders();
-        httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
-        // リクエストを作成
-        RequestEntity<MultiValueMap<String, String>> requestEntity =
-                new RequestEntity<>(formParams, httpHeaders, HttpMethod.POST,
-                        URI.create(logoutUri));
-        // POSTリクエスト送信(ログアウト実行)
-
-        ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
-    }
-
-    @Value("#{'${services.keycloak.keycloakUrl}'}")
-    private String keycloakUrl;
-
-    // static {
-    // disableCertificateValidation();
-    // }
-
-    public void disableCertificateValidation() {
-        LOGGER.info("disabling certificate validation host : " + keycloakUrl);
-        // Create a trust manager that does not validate certificate chains
-        TrustManager[] trustAllCerts = new TrustManager[]{
-                new X509TrustManager() {
-                    public X509Certificate[] getAcceptedIssuers() {
-                        return new X509Certificate[0];
-                    }
-
-                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
-                    }
-
-                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
-                    }
-                }};
-
-
-        // Ignore differences between given hostname and certificate hostname
-        HostnameVerifier hv = new HostnameVerifier() {
-            public boolean verify(String hostname, SSLSession session) {
-
-                // System.out.println("Warning: URL Host: " + hostname + " vs. "
-                // + session.getPeerHost());
-                if (hostname.equals(keycloakUrl) && session.getPeerHost().equals(keycloakUrl)) {
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        };
-
-        // Install the all-trusting trust manager
-        try {
-            SSLContext sc = SSLContext.getInstance("SSL");
-            sc.init(null, trustAllCerts, new SecureRandom());
-            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
-            HttpsURLConnection.setDefaultHostnameVerifier(hv);
-        } catch (Exception e) {
-        }
-
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/configuration/WebConfiguration.java b/src/main/java/eu/hbp/mip/configurations/APIMetadataConfiguration.java
similarity index 61%
rename from src/main/java/eu/hbp/mip/configuration/WebConfiguration.java
rename to src/main/java/eu/hbp/mip/configurations/APIMetadataConfiguration.java
index a5b514dfb815c9df88c0475b7c3ce24df1f06803..7b9eab4563d9c71af0a0eac7d6bae42d798df93b 100644
--- a/src/main/java/eu/hbp/mip/configuration/WebConfiguration.java
+++ b/src/main/java/eu/hbp/mip/configurations/APIMetadataConfiguration.java
@@ -1,31 +1,18 @@
-package eu.hbp.mip.configuration;
+package eu.hbp.mip.configurations;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.DependsOn;
-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.service.Contact;
 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 swaggerUiConfig() {
-        return UiConfiguration.DEFAULT;
-    }
+public class APIMetadataConfiguration {
 
     @Bean
     public Docket swaggerDocumentation() {
@@ -40,10 +27,8 @@ public class WebConfiguration {
     private ApiInfo metadata() {
         return new ApiInfoBuilder()
                 .title("Medical Informatics Platform API")
-                .description("Serve the MIP Frontend")
-                .version("1.0")
-                .contact(new Contact("Mirco Nasuti", "https://www.unil.ch/lren/en/home.html", "mirco.nasuti@chuv.ch"))
+                .description("Serving the MIP Frontend")
+                .contact(new Contact("Kostas Filippopolitis", "https://github.com/KFilippopolitis", "kostasfilippop@gmail.com"))
                 .build();
     }
-
 }
diff --git a/src/main/java/eu/hbp/mip/configurations/GalaxyAuthentication.java b/src/main/java/eu/hbp/mip/configurations/GalaxyAuthentication.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8a5df4bc7311cc86683c546f27de0208a850d20
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/configurations/GalaxyAuthentication.java
@@ -0,0 +1,54 @@
+package eu.hbp.mip.configurations;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import eu.hbp.mip.services.ActiveUserService;
+import eu.hbp.mip.utils.Logger;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Base64;
+
+@RestController
+public class GalaxyAuthentication {
+
+    private final ActiveUserService activeUserService;
+
+    @Value("#{'${services.galaxy.galaxyUsername:admin}'}")
+    private String galaxyUsername;
+
+    @Value("#{'${services.galaxy.galaxyPassword:password}'}")
+    private String galaxyPassword;
+
+    @Value("#{'${services.galaxy.galaxpathoyContext:nativeGalaxy}'}")
+    private String galaxyContext;
+
+    public GalaxyAuthentication(ActiveUserService activeUserService) {
+        this.activeUserService = activeUserService;
+    }
+
+    /**
+     * Get Galaxy Reverse Proxy basic access token.
+     *
+     * @return Return a @{@link ResponseEntity} with the token.
+     */
+    @RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json")
+    @PreAuthorize("hasRole('WORKFLOW_ADMIN')")
+    @ResponseStatus(value = HttpStatus.OK)
+    public ResponseEntity getGalaxyConfiguration() {
+        Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /user/galaxy");
+        String stringEncoded = Base64.getEncoder().encodeToString((galaxyUsername + ":" + galaxyPassword).getBytes());
+        JsonObject object = new JsonObject();
+        object.addProperty("authorization", stringEncoded);
+        object.addProperty("context", galaxyContext);
+        logger.LogUserAction("Successfully Loaded galaxy information.");
+
+        return ResponseEntity.ok(new Gson().toJson(object));
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java b/src/main/java/eu/hbp/mip/configurations/PersistenceConfiguration.java
similarity index 62%
rename from src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java
rename to src/main/java/eu/hbp/mip/configurations/PersistenceConfiguration.java
index c8024e1bffa90604da6d13712bc07cbac815b3d7..181bc639c05ea4b3987459cf36a62664db6812cb 100644
--- a/src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java
+++ b/src/main/java/eu/hbp/mip/configurations/PersistenceConfiguration.java
@@ -1,10 +1,12 @@
-package eu.hbp.mip.configuration;
+package eu.hbp.mip.configurations;
 
 import org.flywaydb.core.Flyway;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
 import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.orm.jpa.EntityScan;
-import org.springframework.context.annotation.*;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.context.annotation.Primary;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.orm.jpa.JpaVendorAdapter;
 import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
@@ -18,25 +20,24 @@ import javax.sql.DataSource;
 
 @Configuration
 @EnableJpaRepositories("eu.hbp.mip.repositories")
-@EntityScan(basePackages = "eu.hbp.mip.model")
 public class PersistenceConfiguration {
 
     @Primary
-    @Bean(name = "portalDatasource")
-    @ConfigurationProperties(prefix = "spring.portalDatasource")
+    @Bean(name = "portal-datasource")
+    @ConfigurationProperties(prefix = "spring.portal-datasource")
     public DataSource portalDataSource() {
         return DataSourceBuilder.create().build();
     }
 
-
     @Bean(name = "entityManagerFactory")
     @DependsOn("flyway")
     public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
-        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
-        em.setDataSource(portalDataSource());
+        LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
+        emfb.setDataSource(portalDataSource());
         JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
-        em.setJpaVendorAdapter(vendorAdapter);
-        return em;
+        emfb.setJpaVendorAdapter(vendorAdapter);
+        emfb.setPackagesToScan("eu.hbp.mip.models.DAOs");
+        return emfb;
     }
 
     @Bean(name = "flyway", initMethod = "migrate")
diff --git a/src/main/java/eu/hbp/mip/configurations/SecurityConfiguration.java b/src/main/java/eu/hbp/mip/configurations/SecurityConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f583da4ef31205007e7467c63cfaf95645a5f28
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/configurations/SecurityConfiguration.java
@@ -0,0 +1,126 @@
+package eu.hbp.mip.configurations;
+
+import eu.hbp.mip.utils.CORSFilter;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
+import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
+import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
+import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
+import org.springframework.security.core.session.SessionRegistryImpl;
+import org.springframework.security.web.access.channel.ChannelProcessingFilter;
+import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
+import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
+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.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.WebUtils;
+
+import javax.servlet.*;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+
+@Controller
+@KeycloakConfiguration
+public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
+
+    // Upon logout, redirect to login page url
+    private static final String logoutRedirectURL = "/sso/login";
+
+    @Value("#{'${authentication.enabled}'}")
+    private boolean authenticationEnabled;
+
+    public SecurityConfiguration(HttpServletRequest request) {
+        this.request = request;
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        super.configure(http);
+
+        if (authenticationEnabled) {
+            http.authorizeRequests()
+                    .antMatchers(
+                            "/sso/login",
+                            "/v2/api-docs", "/swagger-ui/**", "/swagger-resources/**"  // Swagger URLs
+                    ).permitAll()
+                    .antMatchers("/galaxy*", "/galaxy/*").hasRole("WORKFLOW_ADMIN")
+                    .antMatchers("/**").authenticated()
+                    .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
+                    .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
+        } else {
+            http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
+            http.antMatcher("/**")
+                    .authorizeRequests()
+                    .antMatchers("/**").permitAll()
+                    .and().csrf().disable();
+        }
+    }
+
+    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;
+    }
+
+    private final HttpServletRequest request;
+
+    @GetMapping(value = "/logout")
+    public String logout() throws ServletException {
+        request.logout();
+        return String.format("redirect:%s", logoutRedirectURL);
+    }
+
+    @Bean
+    public KeycloakConfigResolver KeycloakConfigResolver() {
+        return new KeycloakSpringBootConfigResolver();
+    }
+
+    @Override
+    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
+        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
+    }
+
+    @Autowired
+    public void configureGlobal(AuthenticationManagerBuilder auth) {
+        SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
+        grantedAuthorityMapper.setConvertToUpperCase(true);
+
+        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
+        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
+        auth.authenticationProvider(keycloakAuthenticationProvider);
+    }
+
+}
diff --git a/src/main/java/eu/hbp/mip/controllers/ActiveUserAPI.java b/src/main/java/eu/hbp/mip/controllers/ActiveUserAPI.java
new file mode 100644
index 0000000000000000000000000000000000000000..aca62c4b6c2771e45ffa60a9cbc09040b1a3248a
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/controllers/ActiveUserAPI.java
@@ -0,0 +1,46 @@
+package eu.hbp.mip.controllers;
+
+import eu.hbp.mip.models.DAOs.UserDAO;
+import eu.hbp.mip.services.ActiveUserService;
+import eu.hbp.mip.utils.Logger;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+@RestController
+@RequestMapping(value = "/activeUser", produces = {APPLICATION_JSON_VALUE})
+@Api(value = "/activeUser")
+public class ActiveUserAPI {
+
+    private final ActiveUserService activeUserService;
+
+    public ActiveUserAPI(ActiveUserService activeUserService) {
+        this.activeUserService = activeUserService;
+    }
+
+    @ApiOperation(value = "Get the active user", response = UserDAO.class)
+    @RequestMapping(method = RequestMethod.GET)
+    public ResponseEntity<UserDAO> getTheActiveUser(HttpServletResponse response) {
+        Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /activeUser");
+        logger.LogUserAction("Loading the details of the activeUser");
+
+        return ResponseEntity.ok(activeUserService.getActiveUser());
+    }
+
+    @ApiOperation(value = "The active user agrees to the NDA", response = UserDAO.class)
+    @RequestMapping(value = "/agreeNDA", method = RequestMethod.POST)
+    public ResponseEntity<UserDAO> activeUserServiceAgreesToNDA(@RequestBody(required = false) UserDAO userDAO) {
+        Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /activeUser/agreeNDA");
+        logger.LogUserAction("The user agreed to the NDA");
+
+        return ResponseEntity.ok(activeUserService.agreeToNDA());
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java
similarity index 64%
rename from src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
rename to src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java
index 8310973a308ec810853519552dc48855f494e4d7..48500bb10470059f1fe7d37079dfb391ef395b31 100644
--- a/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java
@@ -8,15 +8,14 @@ import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients;
 import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance;
-import eu.hbp.mip.model.AlgorithmDTO;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.model.galaxy.WorkflowDTO;
+import eu.hbp.mip.models.DTOs.AlgorithmDTO;
+import eu.hbp.mip.models.galaxy.WorkflowDTO;
+import eu.hbp.mip.services.ActiveUserService;
 import eu.hbp.mip.utils.CustomResourceLoader;
 import eu.hbp.mip.utils.HTTPUtil;
-import eu.hbp.mip.utils.Logging;
+import eu.hbp.mip.utils.Logger;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.io.Resource;
 import org.springframework.http.ResponseEntity;
@@ -31,19 +30,17 @@ import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
-import static eu.hbp.mip.utils.ErrorMessages.disabledAlgorithmsCouldNotBeLoaded;
 import static eu.hbp.mip.utils.InputStreamConverter.convertInputStreamToString;
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 
 @RestController
 @RequestMapping(value = "/algorithms", produces = {APPLICATION_JSON_VALUE})
 @Api(value = "/algorithms")
-public class AlgorithmsApi {
+public class AlgorithmsAPI {
 
     private static final Gson gson = new Gson();
 
-    @Autowired
-    private UserInfo userInfo;
+    private final ActiveUserService activeUserService;
 
     @Value("#{'${services.exareme.algorithmsUrl}'}")
     private String exaremeAlgorithmsUrl;
@@ -54,36 +51,43 @@ public class AlgorithmsApi {
     @Value("#{'${services.galaxy.galaxyApiKey}'}")
     private String galaxyApiKey;
 
+    @Value("#{'${files.disabledAlgorithms_json}'}")
+    private String disabledAlgorithmsFilePath;
+
+    public AlgorithmsAPI(ActiveUserService activeUserService, CustomResourceLoader resourceLoader) {
+        this.activeUserService = activeUserService;
+        this.resourceLoader = resourceLoader;
+    }
+
     @ApiOperation(value = "List all algorithms", response = String.class)
     @RequestMapping(method = RequestMethod.GET)
     public ResponseEntity<List<AlgorithmDTO>> getAlgorithms() {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Executing...");
+        Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /algorithms");
+
+        logger.LogUserAction("Executing...");
 
-        LinkedList<AlgorithmDTO> exaremeAlgorithms = getExaremeAlgorithms();
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Loaded " + exaremeAlgorithms.size() + " exareme algorithms");
-        LinkedList<AlgorithmDTO> galaxyAlgorithms = getGalaxyWorkflows();
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Loaded " + galaxyAlgorithms.size() + " galaxy algorithms");
+        LinkedList<AlgorithmDTO> exaremeAlgorithms = getExaremeAlgorithms(logger);
+        logger.LogUserAction("Loaded " + exaremeAlgorithms.size() + " exareme algorithms");
+        LinkedList<AlgorithmDTO> galaxyAlgorithms = getGalaxyWorkflows(logger);
+        logger.LogUserAction("Loaded " + galaxyAlgorithms.size() + " galaxy algorithms");
 
         LinkedList<AlgorithmDTO> algorithms = new LinkedList<>();
         if (exaremeAlgorithms != null) {
             algorithms.addAll(exaremeAlgorithms);
         } else {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms",
-                    "Getting exareme algorithms failed and returned null");
+            logger.LogUserAction("Getting exareme algorithms failed and returned null");
         }
         if (galaxyAlgorithms != null) {
             algorithms.addAll(galaxyAlgorithms);
         } else {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms",
-                    "Getting galaxy workflows failed and returned null");
+            logger.LogUserAction("Getting galaxy workflows failed and returned null");
         }
 
         List<String> disabledAlgorithms = new ArrayList<>();
         try {
             disabledAlgorithms = getDisabledAlgorithms();
         } catch (IOException e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms",
-                    disabledAlgorithmsCouldNotBeLoaded);
+            logger.LogUserAction("The disabled algorithms could not be loaded.");
         }
 
         // Remove any disabled algorithm
@@ -93,8 +97,7 @@ public class AlgorithmsApi {
                 allowedAlgorithms.add(algorithm);
             }
         }
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms",
-                "Successfully listed " + allowedAlgorithms.size() + " algorithms");
+        logger.LogUserAction("Successfully listed " + allowedAlgorithms.size() + " algorithms");
         return ResponseEntity.ok(allowedAlgorithms);
     }
 
@@ -103,8 +106,8 @@ public class AlgorithmsApi {
      *
      * @return a list of AlgorithmDTOs or null if something fails
      */
-    public LinkedList<AlgorithmDTO> getExaremeAlgorithms() {
-        LinkedList<AlgorithmDTO> algorithms = new LinkedList<>();
+    public LinkedList<AlgorithmDTO> getExaremeAlgorithms(Logger logger) {
+        LinkedList<AlgorithmDTO> algorithms;
         // Get exareme algorithms
         try {
             StringBuilder response = new StringBuilder();
@@ -116,12 +119,11 @@ public class AlgorithmsApi {
                     }.getType()
             );
         } catch (IOException e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "An exception occurred: " + e.getMessage());
+            logger.LogUserAction("An exception occurred: " + e.getMessage());
             return null;
         }
 
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms",
-                "Completed, returned " + algorithms.size() + " algorithms.");
+        logger.LogUserAction("Completed, returned " + algorithms.size() + " algorithms.");
         return algorithms;
     }
 
@@ -130,8 +132,7 @@ public class AlgorithmsApi {
      *
      * @return a list of AlgorithmDTOs or null if something fails
      */
-    public LinkedList<AlgorithmDTO> getGalaxyWorkflows() {
-
+    public LinkedList<AlgorithmDTO> getGalaxyWorkflows(Logger logger) {
         List<Workflow> workflowList;
         try {
             // Get all the workflows with the galaxy client
@@ -140,8 +141,7 @@ public class AlgorithmsApi {
 
             workflowList = new ArrayList<>(workflowsClient.getWorkflows());
         } catch (Exception e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Error when calling list galaxy workflows: " + e.getMessage());
-
+            logger.LogUserAction("Error when calling list galaxy workflows: " + e.getMessage());
             return null;
         }
 
@@ -160,33 +160,31 @@ public class AlgorithmsApi {
 
                 } else {     // Something unexpected happened
                     String msgErr = gson.toJson(response.errorBody());
-                    Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Error Response: " + msgErr);
+                    logger.LogUserAction("Error Response: " + msgErr);
                     return null;
                 }
             } catch (Exception e) {
-                Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "An exception occurred: " + e.getMessage());
+                logger.LogUserAction("An exception occurred: " + e.getMessage());
                 return null;
             }
         }
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Workflows fetched: " + workflows.size());
+        logger.LogUserAction("Workflows fetched: " + workflows.size());
 
         // Convert the workflows to algorithms
         LinkedList<AlgorithmDTO> algorithms = new LinkedList<>();
         for (WorkflowDTO workflow : workflows) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Converting workflow: " + workflow);
+            logger.LogUserAction("Converting workflow: " + workflow);
 
             algorithms.add(workflow.convertToAlgorithmDTO());
 
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms",
-                    "Converted algorithm: " + algorithms.get(algorithms.size() - 1));
+            logger.LogUserAction("Converted algorithm: " + algorithms.get(algorithms.size() - 1));
         }
 
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /algorithms", "Completed!");
+        logger.LogUserAction("Completed!");
         return algorithms;
     }
 
-    @Autowired
-    private CustomResourceLoader resourceLoader;
+    private final CustomResourceLoader resourceLoader;
 
     /**
      * Fetches the disabled algorithms from a .json file
@@ -196,13 +194,12 @@ public class AlgorithmsApi {
      */
     List<String> getDisabledAlgorithms() throws IOException {
 
-        Resource resource = resourceLoader.getResource("file:/opt/portal/api/disabledAlgorithms.json");
+        Resource resource = resourceLoader.getResource(disabledAlgorithmsFilePath);
 
-        List<String> response = gson.fromJson(convertInputStreamToString(
+        return gson.fromJson(convertInputStreamToString(
                 resource.getInputStream()),
                 new TypeToken<List<String>>() {
                 }.getType()
         );
-        return response;
     }
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
deleted file mode 100644
index d4eb46e9f3d072255e23be8a37a4e956add16873..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.controllers;
-
-
-import com.github.slugify.Slugify;
-import eu.hbp.mip.model.Article;
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.repositories.ArticleRepository;
-import eu.hbp.mip.utils.Logging;
-import io.swagger.annotations.*;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Iterator;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-@RestController
-@RequestMapping(value = "/articles", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/articles", description = "the articles API")
-public class ArticlesApi {
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @Autowired
-    private ArticleRepository articleRepository;
-
-    @ApiOperation(value = "Get articles", response = Article.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET)
-    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 = "draft, published") @RequestParam(value = "status", required = false) String status
-    ) {
-        User user = userInfo.getUser();
-        Iterable<Article> articles;
-        Logging.LogUserAction(user.getUsername(), "(GET) /articles", "Loading articles...");
-
-        if (own != null && own) {
-            articles = articleRepository.findByCreatedBy(user);
-        } else {
-            articles = articleRepository.findByStatusOrCreatedBy("published", user);
-        }
-        int articlesSize = 0;
-        if (status != null) {
-            for (Iterator<Article> i = articles.iterator(); i.hasNext(); ) {
-                Article a = i.next();
-                if (!status.equals(a.getStatus())) {
-                    i.remove();
-                }
-                articlesSize++;
-            }
-        }
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /articles", "Successfully Loaded " + articlesSize + " articles");
-
-        return ResponseEntity.ok(articles);
-    }
-
-
-    @ApiOperation(value = "Create an article")
-    @ApiResponses(value = {@ApiResponse(code = 201, message = "Article created")})
-    @RequestMapping(method = RequestMethod.POST)
-    public ResponseEntity<Void> addAnArticle(
-            @RequestBody @ApiParam(value = "Article to create", required = true) @Valid Article article
-    ) {
-
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(POST) /articles", "Creating article...");
-
-        article.setCreatedAt(new Date());
-        if ("published".equals(article.getStatus())) {
-            article.setPublishedAt(new Date());
-        }
-        article.setCreatedBy(user);
-
-        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 + ")");
-            }
-        }
-
-        String slug;
-        try {
-            slug = new Slugify().slugify(article.getTitle());
-        } catch (IOException e) {
-            slug = "";
-            //LOGGER.trace("Cannot slugify title", e);
-        }
-
-        boolean alreadyExists = true;
-        for (int i = 1; alreadyExists; i++) {
-            alreadyExists = articleRepository.exists(slug);
-            if (alreadyExists) {
-                if (i > 1) {
-                    slug = slug.substring(0, slug.length() - 2);
-                }
-                slug += "-" + i;
-            }
-            article.setSlug(slug);
-        }
-        articleRepository.save(article);
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /articles", "Successfully created article with id : " + article.getSlug());
-        return new ResponseEntity<>(HttpStatus.CREATED);
-    }
-
-
-    @ApiOperation(value = "Get an article", response = Article.class)
-    @RequestMapping(value = "/{slug}", method = RequestMethod.GET)
-    public ResponseEntity<Article> getAnArticle(
-            @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
-    ) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /articles/{slug}", "Loading article with id : " + slug);
-
-        User user = userInfo.getUser();
-        Article article;
-        article = articleRepository.findOne(slug);
-
-        if (article == null) {
-            //LOGGER.warn("Cannot find article : " + slug);
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /articles/{slug}", "Article not found");
-            return ResponseEntity.badRequest().body(null);
-        }
-
-        if (!"published".equals(article.getStatus()) && !article.getCreatedBy().getUsername().equals(user.getUsername())) {
-            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-        }
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /articles/{slug}", "Successfully Loaded article with id : " + slug);
-
-        return ResponseEntity.ok(article);
-    }
-
-
-    @ApiOperation(value = "Update an article")
-    @ApiResponses(value = {@ApiResponse(code = 204, message = "Article updated")})
-    @RequestMapping(value = "/{slug}", method = RequestMethod.PUT)
-    public ResponseEntity<Void> updateAnArticle(
-            @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug,
-            @RequestBody @ApiParam(value = "Article to update", required = true) @Valid Article article
-    ) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(PUT) /articles/{slug}", "Updating article with id : " + slug);
-
-        User user = userInfo.getUser();
-
-        String author = articleRepository.findOne(slug).getCreatedBy().getUsername();
-
-        if (!user.getUsername().equals(author)) {
-            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-        }
-
-        String oldTitle = articleRepository.findOne(slug).getTitle();
-
-        String newTitle = article.getTitle();
-
-        if (!newTitle.equals(oldTitle)) {
-            long count = 1;
-            for (int i = 1; count > 0 && !newTitle.equals(oldTitle); i++) {
-                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);
-
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(PUT) /articles/{slug}", "Successfully pdated article with id : " + slug);
-
-        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java b/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5d0b04c54b0fd8652f5d284cb8690eaf14d3acf
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java
@@ -0,0 +1,109 @@
+package eu.hbp.mip.controllers;
+
+
+import eu.hbp.mip.models.DTOs.ExperimentDTO;
+import eu.hbp.mip.services.ActiveUserService;
+import eu.hbp.mip.services.ExperimentService;
+import eu.hbp.mip.utils.JsonConverters;
+import eu.hbp.mip.utils.Logger;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+/*
+    This api is creating experiments and running it's algorithm on the
+    exareme or galaxy clients.
+ */
+
+@RestController
+@RequestMapping(value = "/experiments", produces = {APPLICATION_JSON_VALUE})
+@Api(value = "/experiments")
+public class ExperimentAPI {
+
+    private final ExperimentService experimentService;
+    private final ActiveUserService activeUserService;
+    public ExperimentAPI(
+            ExperimentService experimentService,
+            ActiveUserService activeUserService
+    ) {
+        this.experimentService = experimentService;
+        this.activeUserService = activeUserService;
+    }
+
+    @ApiOperation(value = "Get experiments", response = Map.class, responseContainer = "List")
+    @RequestMapping(method = RequestMethod.GET)
+    public ResponseEntity<String> getExperiments(Authentication authentication,
+            @RequestParam(name = "name", required = false) String name,
+            @RequestParam(name = "algorithm", required = false) String algorithm,
+            @RequestParam(name = "shared", required = false) Boolean shared,
+            @RequestParam(name = "viewed", required = false) Boolean viewed,
+            @RequestParam(name = "includeShared", required = false, defaultValue = "true") boolean includeShared,
+            @RequestParam(name = "orderBy", required = false, defaultValue = "created") String orderBy,
+            @RequestParam(name = "descending", required = false, defaultValue = "true") Boolean descending,
+            @RequestParam(defaultValue = "0") int page,
+            @RequestParam(defaultValue = "10") int size
+    ) {
+        Map experiments = experimentService.getExperiments(authentication,
+                name,
+                algorithm,
+                shared,
+                viewed,
+                includeShared,
+                page,
+                size,
+                orderBy,
+                descending,
+                new Logger(activeUserService.getActiveUser().getUsername(),"(GET) /experiments"));
+        return new ResponseEntity(experiments, HttpStatus.OK);
+    }
+
+
+    @ApiOperation(value = "Get an experiment", response = ExperimentDTO.class)
+    @RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
+    public ResponseEntity<String> getExperiment(Authentication authentication,
+            @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
+        ExperimentDTO experimentDTO = experimentService.getExperiment(authentication, uuid, new Logger(activeUserService.getActiveUser().getUsername(),"(GET) /experiments/{uuid}"));
+        return new ResponseEntity<>(JsonConverters.convertObjectToJsonString(experimentDTO), HttpStatus.OK);
+    }
+
+
+    @ApiOperation(value = "Create an experiment", response = ExperimentDTO.class)
+    @RequestMapping(method = RequestMethod.POST)
+    public ResponseEntity<String> createExperiment(Authentication authentication, @RequestBody ExperimentDTO experimentDTO) {
+        experimentDTO = experimentService.createExperiment(authentication, experimentDTO, new Logger(activeUserService.getActiveUser().getUsername(),"(POST) /experiments"));
+        return new ResponseEntity<>(JsonConverters.convertObjectToJsonString(experimentDTO), HttpStatus.CREATED);
+    }
+
+
+    @ApiOperation(value = "Update an experiment", response = ExperimentDTO.class)
+    @RequestMapping(value = "/{uuid}", method = RequestMethod.PATCH)
+    public ResponseEntity<String> updateExperiment(@RequestBody ExperimentDTO experimentDTO, @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
+        experimentDTO = experimentService.updateExperiment(uuid, experimentDTO, new Logger(activeUserService.getActiveUser().getUsername(),"(PATCH) /experiments/{uuid}"));
+        return new ResponseEntity<>(JsonConverters.convertObjectToJsonString(experimentDTO), HttpStatus.OK);
+    }
+
+
+    @ApiOperation(value = "Delete an experiment", response = boolean.class)
+    @RequestMapping(value = "/{uuid}", method = RequestMethod.DELETE)
+    public ResponseEntity<String> deleteExperiment(
+            @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
+        experimentService.deleteExperiment(uuid, new Logger(activeUserService.getActiveUser().getUsername(), "(DELETE) /experiments/{uuid}"));
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
+
+
+    @ApiOperation(value = "Create a transient experiment", response = ExperimentDTO.class)
+    @RequestMapping(value = "/transient", method = RequestMethod.POST)
+    public ResponseEntity<String> createTransientExperiment(Authentication authentication, @RequestBody ExperimentDTO experimentDTO) {
+        experimentDTO = experimentService.createTransientExperiment(authentication, experimentDTO, new Logger(activeUserService.getActiveUser().getUsername(), "(POST) /experiments/transient"));
+        return new ResponseEntity<>(JsonConverters.convertObjectToJsonString(experimentDTO), HttpStatus.OK);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
deleted file mode 100644
index a54b93df5facaeaa98c7ad35eef44793ad91e899..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
+++ /dev/null
@@ -1,833 +0,0 @@
-package eu.hbp.mip.controllers;
-
-import com.github.jmchilton.blend4j.galaxy.GalaxyInstance;
-import com.github.jmchilton.blend4j.galaxy.GalaxyInstanceFactory;
-import com.github.jmchilton.blend4j.galaxy.WorkflowsClient;
-import com.github.jmchilton.blend4j.galaxy.beans.Workflow;
-import com.github.jmchilton.blend4j.galaxy.beans.WorkflowDetails;
-import com.github.jmchilton.blend4j.galaxy.beans.WorkflowInputDefinition;
-import com.google.common.collect.Lists;
-import com.google.gson.*;
-import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients;
-import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance;
-import eu.hbp.mip.model.*;
-import eu.hbp.mip.model.ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmExecutionParamDTO;
-import eu.hbp.mip.model.galaxy.ErrorResponse;
-import eu.hbp.mip.model.galaxy.GalaxyWorkflowResult;
-import eu.hbp.mip.model.galaxy.PostWorkflowToGalaxyDtoResponse;
-import eu.hbp.mip.repositories.ExperimentRepository;
-import eu.hbp.mip.repositories.ModelRepository;
-import eu.hbp.mip.utils.ClaimUtils;
-import eu.hbp.mip.utils.HTTPUtil;
-import eu.hbp.mip.utils.Logging;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import org.codehaus.jettison.json.JSONException;
-import org.codehaus.jettison.json.JSONObject;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.web.bind.annotation.*;
-import retrofit2.Call;
-import retrofit2.Response;
-
-import java.io.IOException;
-import java.util.*;
-
-import static java.lang.Thread.sleep;
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-/*
-    This api is creating experiments and running it's algorithm on the
-    exareme or galaxy clients.
- */
-
-@RestController
-@RequestMapping(value = "/experiments", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/experiments")
-public class ExperimentApi {
-
-    private static final Gson gson = new Gson();
-
-    @Autowired
-    private UserInfo userInfo;
-
-    private static final Gson gsonOnlyExposed = new GsonBuilder().serializeNulls()
-            .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").excludeFieldsWithoutExposeAnnotation().create();
-
-    @Value("#{'${services.exareme.queryExaremeUrl}'}")
-    private String queryExaremeUrl;
-
-    @Value("#{'${services.workflows.workflowUrl}'}")
-    private String workflowUrl;
-
-    @Value("#{'${services.workflows.jwtSecret}'}")
-    private String jwtSecret;
-
-    @Value("#{'${services.galaxy.galaxyUrl}'}")
-    private String galaxyUrl;
-
-    @Value("#{'${services.galaxy.galaxyApiKey}'}")
-    private String galaxyApiKey;
-
-    // Enable HBP collab authentication (1) or disable it (0). Default is 1
-    @Value("#{'${hbp.authentication.enabled:1}'}")
-    private boolean authenticationIsEnabled;
-
-    @Autowired
-    private ModelRepository modelRepository;
-
-    @Autowired
-    private ExperimentRepository experimentRepository;
-
-    @ApiOperation(value = "get an experiment", response = Experiment.class)
-    @RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
-    public ResponseEntity<String> getExperiment(
-            @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-
-        Experiment experiment;
-        UUID experimentUuid;
-        User user = userInfo.getUser();
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}", "Loading Experiment with uuid : " + uuid);
-
-        try {
-            experimentUuid = UUID.fromString(uuid);
-        } catch (IllegalArgumentException iae) {
-            Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}", "Invalid Experiment UUID.");
-            return ResponseEntity.badRequest().body("Invalid Experiment UUID");
-        }
-
-        experiment = experimentRepository.findOne(experimentUuid);
-
-        if (experiment == null) {
-            Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}", "Experiment Not found.");
-            return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
-        }
-
-        if (!experiment.isShared() && !experiment.getCreatedBy().getUsername().equals(user.getUsername())) {
-            Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}", "Accessing Experiment is unauthorized.");
-            return new ResponseEntity<>("You don't have access to the experiment.", HttpStatus.UNAUTHORIZED);
-        }
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}", "Experiment was Loaded with uuid : " + uuid + ".");
-
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
-
-    @ApiOperation(value = "Create an experiment", response = Experiment.class)
-    @RequestMapping(value = "/runAlgorithm", method = RequestMethod.POST)
-    public ResponseEntity<String> runExperiment(Authentication authentication, @RequestBody ExperimentExecutionDTO experimentExecutionDTO) {
-        User user = userInfo.getUser();
-        // Get the type and name of algorithm
-        String algorithmType = experimentExecutionDTO.getAlgorithms().get(0).getType();
-        String algorithmName = experimentExecutionDTO.getAlgorithms().get(0).getName();
-
-        StringBuilder parametersLogMessage = new StringBuilder(", Parameters:\n");
-        for (ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmExecutionParamDTO params : experimentExecutionDTO.getAlgorithms().get(0).getParameters()) {
-            parametersLogMessage
-                    .append("  ")
-                    .append(params.getLabel())
-                    .append(" -> ")
-                    .append(params.getValue())
-                    .append("\n");
-        }
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Executing " + algorithmName + parametersLogMessage);
-
-        if (authenticationIsEnabled) {
-            // Getting the dataset from the experiment parameters
-            String experimentDatasets = null;
-            for (ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmExecutionParamDTO parameter : experimentExecutionDTO.getAlgorithms().get(0).getParameters()) {
-                if (parameter.getLabel().equals("dataset")) {
-                    experimentDatasets = parameter.getValue();
-                    break;
-                }
-            }
-
-            if (experimentDatasets == null || experimentDatasets.equals("")) {
-                Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm",
-                        "A dataset should be specified to run an algorithm.");
-                return ResponseEntity.badRequest().body("Please provide at least one dataset to run the algorithm.");
-            }
-
-            // --- Validating proper access rights on the datasets  ---
-            if (!ClaimUtils.userHasDatasetsAuthorization(user.getUsername(), authentication.getAuthorities(), experimentDatasets)) {
-                return ResponseEntity.badRequest().body("You are not authorized to use these datasets.");
-            }
-        }
-
-        // Run with the appropriate engine
-        if (algorithmType.equals("workflow")) {
-            Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Algorithm runs on Galaxy.");
-            return runGalaxyWorkflow(experimentExecutionDTO);
-        } else {
-            Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Algorithm runs on Exareme.");
-            return runExaremeAlgorithm(experimentExecutionDTO);
-        }
-    }
-
-    @ApiOperation(value = "Mark an experiment as viewed", response = Experiment.class)
-    @RequestMapping(value = "/{uuid}/markAsViewed", method = RequestMethod.GET)
-    public ResponseEntity<String> markExperimentAsViewed(
-            @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-
-        Experiment experiment;
-        UUID experimentUuid;
-        User user = userInfo.getUser();
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}/markAsViewed", "Marking as viewed the experiment with uuid : " + uuid + ".");
-
-        try {
-            experimentUuid = UUID.fromString(uuid);
-        } catch (IllegalArgumentException iae) {
-            Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}/markAsViewed", "Invalid Experiment UUID" + uuid + ".");
-            return ResponseEntity.badRequest().body("Invalid Experiment UUID");
-        }
-
-        experiment = experimentRepository.findOne(experimentUuid);
-        if (!experiment.getCreatedBy().getUsername().equals(user.getUsername())) {
-            Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}/markAsViewed", "You're not the owner of this experiment");
-            return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.UNAUTHORIZED);
-        }
-        experiment.setResultsViewed(true);
-        experimentRepository.save(experiment);
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{uuid}/markAsViewed", "Experiment with uuid: " + uuid + " was marked as viewed.");
-
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "Mark an experiment as shared", response = Experiment.class)
-    @RequestMapping(value = "/{uuid}/markAsShared", method = RequestMethod.GET)
-    public ResponseEntity<String> markExperimentAsShared(
-            @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /experiments/{uuid}/markAsShared", "Marking as shared the experiment with uuid : " + uuid + ".");
-
-        return doMarkExperimentAsShared(uuid, true);
-    }
-
-    @ApiOperation(value = "Mark an experiment as unshared", response = Experiment.class)
-    @RequestMapping(value = "/{uuid}/markAsUnshared", method = RequestMethod.GET)
-    public ResponseEntity<String> markExperimentAsUnshared(
-            @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /experiments/{uuid}/markAs/Unshared", "Marking as unshared the experiment with uuid : " + uuid + ".");
-
-        return doMarkExperimentAsShared(uuid, false);
-    }
-
-    @ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET, params = {"maxResultCount"})
-    public ResponseEntity<String> listExperiments(
-            @ApiParam(value = "maxResultCount") @RequestParam int maxResultCount) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{maxResultCount}", "Listing experiments with a maximum amount of : " + maxResultCount + ".");
-
-        List<Experiment> expList = doListExperiments(false, null);
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{maxResultCount}", "Successfully listed experiments.");
-
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(expList), HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET, params = {"slug", "maxResultCount"})
-    public ResponseEntity<String> listExperiments(@ApiParam(value = "slug") @RequestParam("slug") String modelSlug,
-                                                  @ApiParam(value = "maxResultCount") @RequestParam("maxResultCount") int maxResultCount) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{slug}/{maxResultCount}", "Listing experiments with a maximum amount of :" + maxResultCount + "with modelSlug : " + modelSlug + ".");
-
-        if (maxResultCount <= 0 || modelSlug == null || "".equals(modelSlug)) {
-            return new ResponseEntity<>("You must provide at least a slug or a limit of result",
-                    HttpStatus.BAD_REQUEST);
-        }
-
-        List<Experiment> expList = doListExperiments(false, null);
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{slug}/{maxResultCount}", "Successfully listed my experiments.");
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(expList), HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "list my experiments", response = Experiment.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET, params = {"mine"})
-    public ResponseEntity<String> listMyExperiments(Authentication authentication, @ApiParam(value = "mine") @RequestParam("mine") boolean mine) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{mine}", "Listing my experiments.");
-        List<Experiment> expList = doListExperiments(true, null);
-        Logging.LogUserAction(user.getUsername(), "(GET) /experiments/{mine}", "Successfully listed my experiments.");
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(expList), HttpStatus.OK);
-    }
-
-    private List<Experiment> doListExperiments(boolean mine, String modelSlug) {
-        User user = userInfo.getUser();
-
-        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);
-        }
-
-        if (modelSlug != null && !"".equals(modelSlug)) {
-            for (Iterator<Experiment> it = expList.iterator(); it.hasNext(); ) {
-                Experiment e = it.next();
-                e.setResult(null);
-                e.setAlgorithms(null);
-                e.setValidations(null);
-                if (!e.getModel().getSlug().equals(modelSlug)) {
-                    it.remove();
-                }
-            }
-        }
-        return expList;
-    }
-
-    private ResponseEntity<String> doMarkExperimentAsShared(String uuid, boolean shared) {
-        Experiment experiment;
-        UUID experimentUuid;
-        User user = userInfo.getUser();
-
-        try {
-            experimentUuid = UUID.fromString(uuid);
-        } catch (IllegalArgumentException iae) {
-            //LOGGER.trace("Invalid UUID", iae);
-            //LOGGER.warn("An invalid Experiment UUID was received !");
-            Logging.LogUserAction(user.getUsername(), "List my experiments", "Listing my experiments.");
-            return ResponseEntity.badRequest().body("Invalid Experiment UUID");
-        }
-
-        experiment = experimentRepository.findOne(experimentUuid);
-
-        if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
-            return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.UNAUTHORIZED);
-
-        experiment.setShared(shared);
-        experimentRepository.save(experiment);
-
-        Logging.LogUserAction(user.getUsername(), "Experiment updated (marked as shared)", "");
-
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
-    /* -------------------------------  EXPERIMENT MODEL METHODS  ----------------------------------------------------*/
-
-    public Experiment createExperiment(ExperimentExecutionDTO experimentExecutionDTO) {
-        User user = userInfo.getUser();
-
-        Experiment experiment = new Experiment();
-        experiment.setUuid(UUID.randomUUID());
-        experiment.setCreatedBy(user);
-        experiment.setAlgorithms(gson.toJson(experimentExecutionDTO.getAlgorithms()));
-        Model model = modelRepository.findOne(experimentExecutionDTO.getModel());
-        experiment.setModel(model);
-        experiment.setName(experimentExecutionDTO.getName());
-        experimentRepository.save(experiment);
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " id : " + experiment.getUuid());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " algorithms : " + experiment.getAlgorithms());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " model : " + experiment.getModel().getSlug());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " name : " + experiment.getName());
-        return experiment;
-    }
-
-    private void saveExperiment(Experiment experiment) {
-        User user = userInfo.getUser();
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " id : " + experiment.getUuid());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " algorithms : " + experiment.getAlgorithms());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " model : " + experiment.getModel().getSlug());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " name : " + experiment.getName());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " historyId : " + experiment.getWorkflowHistoryId());
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", " status : " + experiment.getWorkflowStatus());
-
-        experimentRepository.save(experiment);
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Saved experiment");
-    }
-
-    private void finishExperiment(Experiment experiment) {
-        experiment.setFinished(new Date());
-        experimentRepository.save(experiment);
-    }
-
-    /* --------------------------------------  EXAREME CALLS ---------------------------------------------------------*/
-
-    /**
-     * The runExaremeExperiment will POST the algorithm to the exareme client
-     *
-     * @param experimentExecutionDTO is the request with the experiment information
-     * @return the response to be returned
-     */
-    public ResponseEntity<String> runExaremeAlgorithm(ExperimentExecutionDTO experimentExecutionDTO) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Running the algorithm...");
-
-        Experiment experiment = createExperiment(experimentExecutionDTO);
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Created experiment with uuid :" + experiment.getUuid());
-
-        // Run the 1st algorithm from the list
-        String algorithmName = experimentExecutionDTO.getAlgorithms().get(0).getName();
-
-        // Get the parameters
-        List<ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmExecutionParamDTO> algorithmParameters
-                = experimentExecutionDTO.getAlgorithms().get(0).getParameters();
-
-        String body = gson.toJson(algorithmParameters);
-        String url = queryExaremeUrl + "/" + algorithmName;
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "url: " + url + ", body: " + body);
-
-        ResponseEntity<String> response = new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm",
-                "Completed, returning: " + experiment.toString());
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm",
-                "Starting exareme execution thread");
-        new Thread(() -> {
-            // ATTENTION: Inside the Thread only LogExperimentAction should be used, not LogUserAction!
-            Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Thread named :" + Thread.currentThread().getName() + " with id :" + Thread.currentThread().getId() + " started!");
-
-            try {
-                StringBuilder results = new StringBuilder();
-                int code = HTTPUtil.sendPost(url, body, results);
-
-                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Algorithm finished with code: " + code);
-
-                // Results are stored in the experiment object
-                experiment.setResult("[" + results.toString() + "]");
-                experiment.setHasError(code >= 400);
-                experiment.setHasServerError(code >= 500);
-            } catch (Exception e) {
-                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "There was an exception: " + e.getMessage());
-
-                experiment.setHasError(true);
-                experiment.setHasServerError(true);
-                experiment.setResult(e.getMessage());
-            }
-
-            finishExperiment(experiment);
-            Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Finished the experiment: " + experiment.toString());
-        }).start();
-
-        return response;
-    }
-
-    /* ---------------------------------------  GALAXY CALLS ---------------------------------------------------------*/
-
-
-    /**
-     * The runWorkflow will POST the algorithm to the galaxy client
-     *
-     * @param experimentExecutionDTO is the request with the experiment information
-     * @return the response to be returned
-     */
-    public ResponseEntity<String> runGalaxyWorkflow(ExperimentExecutionDTO experimentExecutionDTO) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Running a workflow...");
-
-        Experiment experiment = createExperiment(experimentExecutionDTO);
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Created experiment with uuid :" + experiment.getUuid());
-
-
-        // Run the 1st algorithm from the list
-        String workflowId = experimentExecutionDTO.getAlgorithms().get(0).getName();
-
-        // Get the parameters
-        List<AlgorithmExecutionParamDTO> algorithmParameters
-                = experimentExecutionDTO.getAlgorithms().get(0).getParameters();
-
-        // Convert the parameters to workflow parameters
-        HashMap<String, String> algorithmParamsIncludingEmpty = new HashMap<>();
-        if (algorithmParameters != null) {
-            for (AlgorithmExecutionParamDTO param : algorithmParameters) {
-                algorithmParamsIncludingEmpty.put(param.getName(), param.getValue());
-            }
-        }
-
-        // Get all the algorithm parameters because the frontend provides only the non-null
-        final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey);
-        final WorkflowsClient workflowsClient = instance.getWorkflowsClient();
-        Workflow workflow = null;
-        for (Workflow curWorkflow : workflowsClient.getWorkflows()) {
-            if (curWorkflow.getId().equals(workflowId)) {
-                workflow = curWorkflow;
-                break;
-            }
-        }
-        if (workflow == null) {
-            Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm",
-                    "Could not find algorithm code: " + workflowId);
-            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
-                    .body(new ErrorResponse("Could not find galaxy algorithm.").toString());
-        }
-        final WorkflowDetails workflowDetails = workflowsClient.showWorkflow(workflow.getId());
-        for (Map.Entry<String, WorkflowInputDefinition> workflowParameter : workflowDetails.getInputs().entrySet()) {
-            if (!(algorithmParamsIncludingEmpty.containsKey(workflowParameter.getValue().getUuid()))) {
-                algorithmParamsIncludingEmpty.put(workflowParameter.getValue().getUuid(), "");
-            }
-        }
-
-        // Create the body of the request
-        HashMap<String, HashMap<String, String>> requestBody = new HashMap<>();
-        requestBody.put("inputs", algorithmParamsIncludingEmpty);
-        JsonObject requestBodyJson = new JsonParser().parse(gson.toJson(requestBody)).getAsJsonObject();
-
-        // Create the request client
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Running Galaxy workflow with id: " + workflow.getId());
-
-        // Call Galaxy to run the workflow
-        Call<PostWorkflowToGalaxyDtoResponse> call = service.postWorkflowToGalaxy(workflow.getId(), galaxyApiKey, requestBodyJson);
-        try {
-            Response<PostWorkflowToGalaxyDtoResponse> response = call.execute();
-
-            if (response.code() == 200) {       // Call succeeded
-                String responseBody = gson.toJson(response.body());
-                Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Response: " + responseBody);
-
-                String historyId = (String) new JSONObject(responseBody).get("history_id");
-                experiment.setWorkflowHistoryId(historyId);
-                experiment.setWorkflowStatus("running");
-                experiment.setHasError(false);
-                experiment.setHasServerError(response.code() >= 500);
-
-            } else {     // Something unexpected happened
-                String msgErr = gson.toJson(response.errorBody());
-                Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Error Response: " + msgErr);
-
-                // Values are read from streams.
-                JSONObject jObjectError = new JSONObject(msgErr);
-                String errMsg = jObjectError.get("err_msg").toString();
-
-                experiment.setResult("[" + new ErrorResponse(errMsg).toString() + "]");
-                experiment.setHasError(response.code() >= 400);
-                experiment.setHasServerError(response.code() >= 500);
-            }
-
-        } catch (Exception e) {
-            Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "An exception occurred: " + e.getMessage());
-            experiment.setHasError(true);
-            experiment.setHasServerError(true);
-            experiment.setResult(e.getMessage());
-        }
-        saveExperiment(experiment);
-
-        // Start the process of fetching the status
-        updateWorkflowExperiment(experiment);
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Run workflow completed!");
-
-        return new ResponseEntity(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
-
-    /**
-     * This method creates a thread that will fetch the workflow result when it is ready
-     *
-     * @param experiment will be used to fetch it's workflow status, it should have the workflowHistoryId initialized
-     *                   and the result should not already be fetched
-     * @return nothing, just updates the experiment
-     */
-    public void updateWorkflowExperiment(Experiment experiment) {
-        User user = userInfo.getUser();
-
-        if (experiment == null) {
-            Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "The experiment does not exist.");
-            return;
-        }
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm",
-                " Experiment id : " + experiment.getUuid());
-        if (experiment.getWorkflowHistoryId() == null) {
-            Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "History Id does not exist.");
-            return;
-        }
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /experiments/runAlgorithm", "Starting Thread...");
-        new Thread(() -> {
-            while (true) {
-                // ATTENTION: Inside the Thread only LogExperimentAction should be used, not LogExperimentAction!
-                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Thread is running...");
-
-                try {
-                    sleep(2000);
-                } catch (InterruptedException e) {
-                    Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Sleep was disrupted: " + e.getMessage());
-                }
-
-                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Fetching status for experiment Id: " + experiment.getUuid());
-
-                String state = getWorkflowStatus(experiment);
-                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "State is: " + state);
-
-                switch (state) {
-                    case "running":
-                        // Do nothing, when the experiment is created the status is set to running
-                        Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Workflow is still running.");
-                        break;
-
-                    case "completed":
-                        // Get only the job result that is visible
-                        List<GalaxyWorkflowResult> workflowJobsResults = getWorkflowResults(experiment);
-                        Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Results are: " + workflowJobsResults.toString());
-
-                        boolean resultFound = false;
-                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
-                            if (jobResult.getVisible()) {
-                                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Visible result are: " + jobResult.getId());
-
-                                String result = getWorkflowResultBody(experiment, jobResult.getId());
-
-                                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Result: " + result);
-                                if (result == null) {
-                                    experiment.setHasError(true);
-                                    experiment.setHasServerError(true);
-                                }
-                                experiment.setResult(result);
-                                experiment.setWorkflowStatus("completed");
-                                resultFound = true;
-                            }
-                        }
-
-                        if (!resultFound) {      // If there is no visible result
-                            Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "No visible result");
-                            experiment.setResult("[" + new ErrorResponse("The workflow has no visible result.").toString() + "]");
-                            experiment.setHasError(true);
-                            experiment.setHasServerError(true);
-                        }
-
-                        finishExperiment(experiment);
-                        break;
-
-                    case "error":
-                        // Get the job result that failed
-                        workflowJobsResults = getWorkflowResults(experiment);
-                        Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Error results are: " + workflowJobsResults.toString());
-
-                        boolean failedJobFound = false;
-                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
-                            if (jobResult.getState().equals("error")) {
-                                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Failed job is: " + jobResult.getId());
-
-                                String result = getWorkflowJobError(jobResult.getId(), experiment);
-
-                                Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Job result: " + result);
-                                if (result == null) {
-                                    experiment.setHasError(true);
-                                    experiment.setHasServerError(true);
-                                }
-                                experiment.setResult("[" + result + "]");
-                                experiment.setWorkflowStatus("error");
-                                failedJobFound = true;
-                            }
-                        }
-
-                        if (!failedJobFound) {      // If there is no visible failed job
-                            Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "No failed result");
-                            experiment.setResult("[" + new ErrorResponse("The workflow has no failed result.").toString() + "]");
-                            experiment.setHasError(true);
-                            experiment.setHasServerError(true);
-                        }
-                        finishExperiment(experiment);
-                        break;
-
-                    default:        // InternalError or unexpected result
-                        experiment.setResult("[" + new ErrorResponse("An unexpected error occurred.").toString() + "]");
-                        experiment.setHasError(true);
-                        experiment.setHasServerError(true);
-                        finishExperiment(experiment);
-                        break;
-                }
-
-                // If result exists return
-                if (experiment.getResult() != null) {
-                    Logging.LogExperimentAction(experiment.getName(), experiment.getUuid(), "Result exists: " + experiment.getResult());
-                    return;
-                }
-            }
-        }).start();
-    }
-
-
-    /**
-     * @param experiment The experiment of the workflow
-     * @return "running"           ->      When the workflow is still running
-     * "internalError"     ->      When an exception or a bad request occurred
-     * "error"             ->      When the workflow produced an error
-     * "completed"         ->      When the workflow completed successfully
-     */
-    public String getWorkflowStatus(Experiment experiment) {
-        String historyId = experiment.getWorkflowHistoryId();
-        String experimentName = experiment.getName();
-        UUID experimentId = experiment.getUuid();
-
-        // ATTENTION: This function is used from a Thread. Only LogExperimentAction should be used, not LogUserAction!
-        Logging.LogExperimentAction(experimentName, experimentId, " History Id : " + historyId);
-
-        // Create the request client
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<Object> call = service.getWorkflowStatusFromGalaxy(historyId, galaxyApiKey);
-
-        String result = null;
-        try {
-            Response<Object> response = call.execute();
-            if (response.code() >= 400) {
-                Logging.LogExperimentAction(experimentName, experimentId, " Response code: "
-                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return "internalError";
-            }
-            result = new Gson().toJson(response.body());
-            Logging.LogExperimentAction(experimentName, experimentId, " Result: " + result);
-
-        } catch (IOException e) {
-            Logging.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
-            return "internalError";
-        }
-
-        String state = null;
-        try {
-            JSONObject resultJson = new JSONObject(result);
-            state = resultJson.getString("state");
-        } catch (JSONException e) {
-            Logging.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
-            return "internalError";
-        }
-
-        Logging.LogExperimentAction(experimentName, experimentId, " Completed!");
-        switch (state) {
-            case "ok":
-                return "completed";
-            case "error":
-                return "error";
-            case "running":
-            case "new":
-            case "waiting":
-            case "queued":
-                return "running";
-            default:
-                return "internalError";
-        }
-    }
-
-    /**
-     * @param experiment The experiment of the workflow
-     * @return a List<GalaxyWorkflowResult>   or null when an error occurred
-     */
-    public List<GalaxyWorkflowResult> getWorkflowResults(Experiment experiment) {
-
-        String historyId = experiment.getWorkflowHistoryId();
-        String experimentName = experiment.getName();
-        UUID experimentId = experiment.getUuid();
-        Logging.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
-
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<List<GalaxyWorkflowResult>> call = service.getWorkflowResultsFromGalaxy(historyId, galaxyApiKey);
-
-        List<GalaxyWorkflowResult> getGalaxyWorkflowResultList = null;
-        try {
-            Response<List<GalaxyWorkflowResult>> response = call.execute();
-            if (response.code() >= 400) {
-                Logging.LogExperimentAction(experimentName, experimentId, " Response code: "
-                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return null;
-            }
-            getGalaxyWorkflowResultList = response.body();
-            Logging.LogExperimentAction(experimentName, experimentId, " Result: " + response.body());
-
-        } catch (IOException e) {
-            Logging.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
-            return null;
-        }
-
-        Logging.LogExperimentAction(experimentName, experimentId, " Completed!");
-        return getGalaxyWorkflowResultList;
-
-    }
-
-    /**
-     * @param experiment The experiment of the workflow
-     * @param contentId  the id of the job result that we want
-     * @return the result of the specific workflow job, null if there was an error
-     */
-    public String getWorkflowResultBody(Experiment experiment, String contentId) {
-
-        String historyId = experiment.getWorkflowHistoryId();
-        String experimentName = experiment.getName();
-        UUID experimentId = experiment.getUuid();
-
-        Logging.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
-
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<Object> call =
-                service.getWorkflowResultsBodyFromGalaxy(historyId, contentId, galaxyApiKey);
-
-        String resultJson = null;
-        try {
-            Response<Object> response = call.execute();
-            if (response.code() >= 400) {
-                Logging.LogExperimentAction(experimentName, experimentId, " Response code: "
-                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return null;
-            }
-            resultJson = new Gson().toJson(response.body());
-            Logging.LogExperimentAction(experimentName, experimentId, " Result: " + resultJson);
-
-        } catch (IOException e) {
-            Logging.LogExperimentAction(experimentName, experimentId,
-                    " An exception happened: " + e.getMessage());
-            return null;
-        }
-
-        Logging.LogExperimentAction(experimentName, experimentId, " Completed!");
-        return resultJson;
-    }
-
-
-    /**
-     * @param jobId the id of the workflow job that failed
-     * @return the error that was produced or null if an error occurred
-     */
-    public String getWorkflowJobError(String jobId, Experiment experiment) {
-        String experimentName = experiment.getName();
-        UUID experimentId = experiment.getUuid();
-
-        Logging.LogExperimentAction(experimentName, experimentId, " jobId : " + jobId);
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<Object> callError = service.getErrorMessageOfWorkflowFromGalaxy(jobId, galaxyApiKey);
-
-        String fullError = null;
-        String returnError = null;
-        try {
-            Response<Object> response = callError.execute();
-            if (response.code() >= 400) {
-                Logging.LogExperimentAction(experimentName, experimentId, "Response code: "
-                        + response.code() + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return null;
-            }
-
-            // Parsing the stderr of the job that failed
-            String jsonString = new Gson().toJson(response.body());
-            JsonElement jsonElement = new JsonParser().parse(jsonString);
-            JsonObject rootObject = jsonElement.getAsJsonObject();
-            fullError = rootObject.get("stderr").getAsString();
-            Logging.LogExperimentAction(experimentName, experimentId, "Error: " + fullError);
-
-            String[] arrOfStr = fullError.split("ValueError", 0);
-            String specError = arrOfStr[arrOfStr.length - 1];
-            returnError = specError.substring(1);
-            Logging.LogExperimentAction(experimentName, experimentId, "Parsed Error: " + returnError);
-
-        } catch (IOException e) {
-            Logging.LogExperimentAction(experimentName, experimentId, "Exception: " + e.getMessage());
-            return null;
-        }
-
-        Logging.LogExperimentAction(experimentName, experimentId, "Completed successfully!");
-
-        return returnError;
-    }
-
-
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
deleted file mode 100644
index 69e7f3ba94702ee9b5465920d3234ca4dcac0248..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package eu.hbp.mip.controllers;
-
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-import eu.hbp.mip.utils.Logging;
-
-/**
- * Created by mirco on 08.05.17.
- */
-
-@RestController
-@RequestMapping(value = "/protected")
-@Api(value = "/protected", description = "the protected files API")
-public class FilesAPI {
-
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @ApiOperation(value = "Get protected files")
-    @RequestMapping(value = "/{filename:.+}", method = RequestMethod.GET)
-    public ResponseEntity<Void> getProtectedFile(
-            @ApiParam(value = "filename", required = true) @PathVariable("filename") String filename
-    ) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(GET) /protected/{filename:.+}", "Loading protected file with filename : " + filename);
-
-        String filepath = "/protected/" + filename;
-        Logging.LogUserAction(user.getUsername(), "(GET) /protected/{filename:.+}" + filepath, "Downloaded protected file");
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("X-Accel-Redirect", filepath);
-
-        return new ResponseEntity<>(headers, HttpStatus.OK);
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/MiningApi.java b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
deleted file mode 100644
index 6a198cc0d4571c58b1ff424e590bc418893a39f1..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/MiningApi.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package eu.hbp.mip.controllers;
-
-import eu.hbp.mip.utils.HTTPUtil;
-
-import com.google.gson.Gson;
-
-import eu.hbp.mip.model.UserInfo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import eu.hbp.mip.utils.Logging;
-
-
-import java.util.*;
-import java.io.IOException;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-/**
- * Created by mirco on 06.01.17.
- */
-@RestController
-@RequestMapping(value = "/mining", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/mining", description = "the mining API")
-public class MiningApi {
-
-    private static final Gson gson = new Gson();
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @Value("#{'${services.exareme.queryExaremeUrl:http://localhost:9090/mining/query}'}")
-    public String queryExaremeUrl;
-
-    @ApiOperation(value = "Create a histogram on Exareme", response = String.class)
-    @RequestMapping(value = "/histograms", method = RequestMethod.POST)
-    public ResponseEntity runExaremeHistograms(@RequestBody List<HashMap<String, String>> queryList) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /mining/histogram", "Executing histogram...");
-
-        String query = gson.toJson(queryList);
-        String url = queryExaremeUrl + "/" + "MULTIPLE_HISTOGRAMS";
-
-        try {
-            StringBuilder results = new StringBuilder();
-            int code = HTTPUtil.sendPost(url, query, results);
-
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /mining/histogram", "Executed histogram with result :" + results.toString());
-            return ResponseEntity.ok(gson.toJson(results.toString()));
-        } catch (IOException e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /mining/histogram", "Histogram algorithm was not found");
-            return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
-        }
-    }
-
-    @ApiOperation(value = "Create a descriptive statistic on Exareme", response = String.class)
-    @RequestMapping(value = "/descriptive_stats", method = RequestMethod.POST)
-    public ResponseEntity runExaremeDescriptiveStats(@RequestBody List<HashMap<String, String>> queryList) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/descriptive_stats", "Executing Exareme descriptive stats...");
-
-        String query = gson.toJson(queryList);
-        String url = queryExaremeUrl + "/" + "DESCRIPTIVE_STATS";
-
-        try {
-            StringBuilder results = new StringBuilder();
-            int code = HTTPUtil.sendPost(url, query, results);
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/descriptive_stats", "Executed descriptive stats with result : " + results.toString());
-            return ResponseEntity.ok(gson.toJson(results.toString()));
-        } catch (IOException e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/descriptive_stats", "Descriptive stats algorithm was not found");
-            return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
-        }
-    }
-
-    @ApiOperation(value = "Create a descriptive statistic on Exareme", response = String.class)
-    @RequestMapping(value = "/descriptive_stats_v2", method = RequestMethod.POST)
-    public ResponseEntity runExaremeDescriptiveStatsV2(@RequestBody List<HashMap<String, String>> queryList) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/descriptive_stats_v2", "Executing an Exareme descriptive stats v2");
-
-        String query = gson.toJson(queryList);
-        String url = queryExaremeUrl + "/" + "DESCRIPTIVE_STATS_v2";
-
-        try {
-            StringBuilder results = new StringBuilder();
-            int code = HTTPUtil.sendPost(url, query, results);
-
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/descriptive_stats_v2", "Successfully executed descriptive stats v2 with results : " + results.toString());
-            return ResponseEntity.ok(gson.toJson(results.toString()));
-        } catch (IOException e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/descriptive_stats_v2", "Descriptive stats v2 algorithm was not found");
-            return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
-        }
-    }
-
-    @ApiOperation(value = "Check if a formula is valid", response = String.class)
-    @RequestMapping(value = "/checkFormula", method = RequestMethod.POST)
-    public ResponseEntity checkFormulaValidity(String formula) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /experiments/checkFormula", "Executing  checkFormula ...");
-
-        return ResponseEntity.ok("");
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
deleted file mode 100644
index 6f013ee336815bbb25514b37cdb764fe7710e8fd..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.controllers;
-
-import com.github.slugify.Slugify;
-import eu.hbp.mip.model.Model;
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.model.Variable;
-import eu.hbp.mip.repositories.*;
-import io.swagger.annotations.*;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-import eu.hbp.mip.utils.Logging;
-
-import java.io.IOException;
-import java.util.*;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-@RestController
-@RequestMapping(value = "/models", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/models", description = "the models API")
-public class ModelsApi {
-
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @Autowired
-    private DatasetRepository datasetRepository;
-
-    @Autowired
-    private ModelRepository modelRepository;
-
-    @Autowired
-    private QueryRepository queryRepository;
-
-    @Autowired
-    private ConfigRepository configRepository;
-
-    @Autowired
-    private VariableRepository variableRepository;
-
-    @ApiOperation(value = "get models", response = Model.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<List> getModels(
-            @ApiParam(value = "Only ask own models") @RequestParam(value = "own", required = false) Boolean own,
-            @ApiParam(value = "Only ask published models") @RequestParam(value = "valid", required = false) Boolean valid
-    ) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /models", "Loading models ...");
-
-        User user = userInfo.getUser();
-
-        Iterable<Model> models;
-        if (own != null && own) {
-            models = modelRepository.findByCreatedByOrderByCreatedAt(user);
-        } else {
-            models = modelRepository.findByValidOrCreatedByOrderByCreatedAt(true, user);
-        }
-
-        if (valid != null && models != null) {
-            for (Iterator<Model> i = models.iterator(); i.hasNext(); ) {
-                Model m = i.next();
-                if (valid != m.getValid()) {
-                    i.remove();
-                }
-            }
-        }
-
-        List<Object> modelsList = new LinkedList<>();
-        models = models != null ? models : new LinkedList<>();
-        for (Model m : models) {
-            m.setDataset(datasetRepository.findOne(m.getDataset().getCode()));
-            modelsList.add(m);
-        }
-
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /models", "Successfully loaded " + modelsList.size() + " models.");
-
-        return ResponseEntity.ok(modelsList);
-    }
-
-
-    @ApiOperation(value = "Create a model", response = Model.class)
-    @ApiResponses(value = {@ApiResponse(code = 201, message = "Model created")})
-    @RequestMapping(method = RequestMethod.POST)
-    public ResponseEntity<Model> addAModel(
-            @RequestBody @ApiParam(value = "Model to create", required = true) Model model
-    ) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(POST) /models", "Creating a model");
-
-        model.setTitle(model.getConfig().getTitle().get("text"));
-        model.setCreatedBy(user);
-        model.setCreatedAt(new Date());
-        if (model.getValid() == null) {
-            model.setValid(false);
-        }
-
-        ensureTitleUniqueness(model);
-        ensureSlugUniqueness(model);
-
-        Map<String, String> map = new HashMap<>(model.getConfig().getTitle());
-        map.put("text", model.getTitle());
-        model.getConfig().setTitle(map);
-
-        saveVariables(model.getQuery().getVariables());
-        saveVariables(model.getQuery().getCovariables());
-        saveVariables(model.getQuery().getGrouping());
-        saveVariables(model.getQuery().getTrainingDatasets());
-
-        configRepository.save(model.getConfig());
-        queryRepository.save(model.getQuery());
-        if (model.getDataset() != null) {
-            datasetRepository.save(model.getDataset());
-        }
-        modelRepository.save(model);
-
-        Logging.LogUserAction(user.getUsername(), "(POST) /models", "Created model with id : " + model.getSlug() + ", model.config and model.query");
-
-        return ResponseEntity.status(HttpStatus.CREATED).body(model);
-    }
-
-    private void saveVariables(@RequestBody @ApiParam(value = "Model to create", required = true) List<Variable> variables) {
-        for (Variable var : variables) {
-            variableRepository.save(var);
-        }
-    }
-
-    private void ensureSlugUniqueness(@RequestBody @ApiParam(value = "Model to create", required = true) Model model) {
-        String slug = createSlug(model.getTitle());
-        boolean slugExists = true;
-        for (int i = 1; slugExists; i++) {
-            slugExists = modelRepository.exists(slug);
-            if (slugExists) {
-                if (i > 1) {
-                    slug = slug.substring(0, slug.length() - 2);
-                }
-                slug += "-" + i;
-            }
-            model.setSlug(slug);
-        }
-    }
-
-    private String createSlug(@RequestBody @ApiParam(value = "Model to create", required = true) String title) {
-        String slug;
-        try {
-            slug = new Slugify().slugify(title);
-        } catch (IOException e) {
-            slug = "";  // Should never happen
-            //LOGGER.trace("Cannot slugify title", e);
-        }
-        return slug;
-    }
-
-    private void ensureTitleUniqueness(@RequestBody @ApiParam(value = "Model to create", required = true) Model model) {
-        boolean titleExists = true;
-        for (int i = 1; titleExists; i++) {
-            String title = model.getTitle();
-            titleExists = modelRepository.countByTitle(title) > 0;
-            if (titleExists) {
-                if (i > 1) {
-                    title = title.substring(0, title.length() - 4);
-                }
-                model.setTitle(title + " (" + i + ")");
-            }
-        }
-    }
-
-    @ApiOperation(value = "Get a model", response = Model.class)
-    @RequestMapping(value = "/{slug}", method = RequestMethod.GET)
-    public ResponseEntity<Model> getAModel(
-            @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
-    ) {
-
-        User user = userInfo.getUser();
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /models/{slug}", "Loading model with id : " + slug);
-
-        Model model = modelRepository.findOne(slug);
-        if (model == null) {
-            //LOGGER.warn("Cannot find model : " + slug);
-            Logging.LogUserAction(user.getUsername(), "(GET) /models/{slug}", "Model was not found");
-            return ResponseEntity.badRequest().body(null);
-        }
-
-        if (!model.getValid() && !model.getCreatedBy().getUsername().equals(user.getUsername())) {
-            Logging.LogUserAction(user.getUsername(), "(GET) /models/{slug}", "You are not authorized to retrieve models. ");
-            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-        }
-
-        List<String> yAxisVars = configRepository.findOne(model.getConfig().getId()).getyAxisVariables();
-        Collection<String> yAxisVarsColl = new LinkedHashSet<>(yAxisVars);
-        model.getConfig().setyAxisVariables(new LinkedList<>(yAxisVarsColl));
-
-        Logging.LogUserAction(user.getUsername(), "(GET) /models/{slug}", "Loaded model with id : " + slug);
-        return ResponseEntity.ok(model);
-    }
-
-
-    @ApiOperation(value = "Update a model", response = Void.class)
-    @ApiResponses(value = {@ApiResponse(code = 204, message = "Model updated")})
-    @RequestMapping(value = "/{slug}", method = RequestMethod.PUT)
-    public ResponseEntity<Void> updateAModel(
-            @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug,
-            @RequestBody @ApiParam(value = "Model to update", required = true) Model model
-    ) {
-        User user = userInfo.getUser();
-        Logging.LogUserAction(user.getUsername(), "(PUT) /models/{slug}", "Updating model with id : " + slug);
-        Model oldModel = modelRepository.findOne(slug);
-
-        if (!user.getUsername().equals(oldModel.getCreatedBy().getUsername())) {
-            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
-        }
-
-        model.setTitle(model.getConfig().getTitle().get("text"));
-
-        String oldTitle = oldModel.getTitle();
-        String newTitle = model.getTitle();
-
-        // If title has been updated, ensure it is unique
-        if (!newTitle.equals(oldTitle)) {
-            boolean newTitleExists = true;
-            for (int i = 1; newTitleExists && !newTitle.equals(oldTitle); i++) {
-                newTitle = model.getTitle();
-                newTitleExists = modelRepository.countByTitle(newTitle) > 0;
-                if (newTitleExists && !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);
-
-        saveVariables(model.getQuery().getVariables());
-        saveVariables(model.getQuery().getCovariables());
-        saveVariables(model.getQuery().getGrouping());
-        saveVariables(model.getQuery().getTrainingDatasets());
-
-        configRepository.save(model.getConfig());
-        queryRepository.save(model.getQuery());
-        datasetRepository.save(model.getDataset());
-        modelRepository.save(model);
-
-        Logging.LogUserAction(user.getUsername(), "(PUT) /models/{slug}", "Updated model and saved/updated model.config and model.query");
-
-        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java b/src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java
similarity index 58%
rename from src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
rename to src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java
index 77916981465827ae4e0806366663a16c7ad1e70b..5e9a9d34452f81ff5293bccaf3a5a5aca0624057 100644
--- a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java
@@ -1,19 +1,15 @@
-/**
- * Created by mirco on 04.12.15.
- */
-
 package eu.hbp.mip.controllers;
 
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
-import eu.hbp.mip.model.PathologyDTO;
-import eu.hbp.mip.model.UserInfo;
+import eu.hbp.mip.models.DTOs.PathologyDTO;
+import eu.hbp.mip.services.ActiveUserService;
 import eu.hbp.mip.utils.ClaimUtils;
 import eu.hbp.mip.utils.CustomResourceLoader;
+import eu.hbp.mip.utils.Exceptions.BadRequestException;
 import eu.hbp.mip.utils.InputStreamConverter;
-import eu.hbp.mip.utils.Logging;
+import eu.hbp.mip.utils.Logger;
 import io.swagger.annotations.Api;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.io.Resource;
 import org.springframework.http.ResponseEntity;
@@ -25,49 +21,55 @@ import org.springframework.web.bind.annotation.RestController;
 import java.io.IOException;
 import java.util.List;
 
-import static eu.hbp.mip.utils.ErrorMessages.pathologiesCouldNotBeLoaded;
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 
 @RestController
 @RequestMapping(value = "/pathologies", produces = {APPLICATION_JSON_VALUE})
 @Api(value = "/pathologies")
-public class PathologiesApi {
+public class PathologiesAPI {
 
     private static final Gson gson = new Gson();
 
-    @Autowired
-    private UserInfo userInfo;
 
     // Enable HBP collab authentication (1) or disable it (0). Default is 1
-    @Value("#{'${hbp.authentication.enabled:1}'}")
+    @Value("#{'${authentication.enabled}'}")
     private boolean authenticationIsEnabled;
 
-    @Autowired
-    private CustomResourceLoader resourceLoader;
+    @Value("#{'${files.pathologies_json}'}")
+    private String pathologiesFilePath;
+
+    private final ActiveUserService activeUserService;
+
+    private final CustomResourceLoader resourceLoader;
+
+    public PathologiesAPI(ActiveUserService activeUserService, CustomResourceLoader resourceLoader) {
+        this.activeUserService = activeUserService;
+        this.resourceLoader = resourceLoader;
+    }
 
     @RequestMapping(name = "/pathologies", method = RequestMethod.GET)
     public ResponseEntity<String> getPathologies(Authentication authentication) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /pathologies", "Loading pathologies ...");
+        Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /pathologies");
+        logger.LogUserAction("Loading pathologies ...");
 
         // Load pathologies from file
-        Resource resource = resourceLoader.getResource("file:/opt/portal/api/pathologies.json");
+        Resource resource = resourceLoader.getResource(pathologiesFilePath);
         List<PathologyDTO> allPathologies;
         try {
             allPathologies = gson.fromJson(InputStreamConverter.convertInputStreamToString(resource.getInputStream()), new TypeToken<List<PathologyDTO>>() {
             }.getType());
         } catch (IOException e) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /pathologies", "Unable to load pathologies");
-            return ResponseEntity.badRequest().body(pathologiesCouldNotBeLoaded);
+            logger.LogUserAction("Unable to load pathologies");
+            throw new BadRequestException("The pathologies could not be loaded.");
         }
 
         // If authentication is disabled return everything
         if (!authenticationIsEnabled) {
-            Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /pathologies", "Successfully loaded " + allPathologies.size() + " pathologies");
+            logger.LogUserAction("Successfully loaded " + allPathologies.size() + " pathologies");
             return ResponseEntity.ok().body(gson.toJson(allPathologies));
         }
 
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /pathologies", "Successfully loaded all authorized pathologies");
-        return ResponseEntity.ok().body(ClaimUtils.getAuthorizedPathologies(
-                userInfo.getUser().getUsername(), authentication.getAuthorities(), allPathologies));
+        logger.LogUserAction("Successfully loaded all authorized pathologies");
+        return ResponseEntity.ok().body(ClaimUtils.getAuthorizedPathologies(logger,  authentication, allPathologies));
     }
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
deleted file mode 100644
index 4e412aea08da5612f47d60baafd4bac791f2fc6e..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package eu.hbp.mip.controllers;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import eu.hbp.mip.configuration.SecurityConfiguration;
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.repositories.UserRepository;
-import eu.hbp.mip.utils.Logging;
-import io.swagger.annotations.ApiParam;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.security.Principal;
-import java.util.Base64;
-
-@RestController
-public class SecurityApi {
-
-    private static final Gson gson = new Gson();
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @Autowired
-    private UserRepository userRepository;
-
-    @Autowired
-    private SecurityConfiguration securityConfiguration;
-
-    @RequestMapping(path = "/user", method = RequestMethod.GET)
-    public Object user(Principal principal, HttpServletResponse response) {
-        ObjectMapper mapper = new ObjectMapper();
-
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /user", "Loading user : " + userInfo.getUser().getUsername());
-        try {
-            String userJSON = mapper.writeValueAsString(userInfo.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("Cannot read user json", e);
-        }
-
-        if (!securityConfiguration.isAuthentication()) {
-            if (userInfo.isFakeAuth()) {
-                response.setStatus(401);
-            }
-            String principalJson = "{\"principal\": \"anonymous\", \"name\": \"anonymous\", \"userAuthentication\": {"
-                    + "\"details\": {\"preferred_username\": \"anonymous\"}}}";
-            return new Gson().fromJson(principalJson, Object.class);
-        }
-
-        return principal;
-    }
-
-    @RequestMapping(path = "/user", method = RequestMethod.POST)
-    public ResponseEntity<Void> postUser(
-            @ApiParam(value = "Has the user agreed on the NDA") @RequestParam(value = "agreeNDA") Boolean agreeNDA) {
-        User user = userInfo.getUser();
-        if (user != null) {
-            user.setAgreeNDA(agreeNDA);
-            userRepository.save(user);
-        }
-
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(POST) /user", "User has agreed on the NDA");
-
-        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-    }
-
-    @RequestMapping(path = "/login/hbp", method = RequestMethod.GET)
-    @ConditionalOnExpression("${hbp.authentication.enabled:0}")
-    public void noLogin(HttpServletResponse httpServletResponse) throws IOException {
-        userInfo.setFakeAuth(true);
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /user/login/hbp", "Unathorized login.");
-
-        httpServletResponse.sendRedirect(securityConfiguration.getFrontendRedirectAfterLogin());
-    }
-
-    @Value("#{'${services.galaxy.galaxyUsername:admin}'}")
-    private String galaxyUsername;
-
-    @Value("#{'${services.galaxy.galaxyPassword:password}'}")
-    private String galaxyPassword;
-
-    @Value("#{'${services.galaxy.galaxyContext:nativeGalaxy}'}")
-    private String galaxyContext;
-
-    /**
-     * Get Galaxy Reverse Proxy basic access token.
-     *
-     * @return Return a @{@link ResponseEntity} with the token.
-     */
-
-    @RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json")
-    @PreAuthorize("hasRole('Data Manager')")
-    @ResponseStatus(value = HttpStatus.OK)
-    public ResponseEntity getGalaxyConfiguration() {
-        String stringEncoded = Base64.getEncoder().encodeToString((galaxyUsername + ":" + galaxyPassword).getBytes());
-        JsonObject object = new JsonObject();
-        object.addProperty("authorization", stringEncoded);
-        object.addProperty("context", galaxyContext);
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /user/galaxy", "Successfully Loaded galaxy information.");
-
-        return ResponseEntity.ok(gson.toJson(object));
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/StatsApi.java b/src/main/java/eu/hbp/mip/controllers/StatsApi.java
deleted file mode 100644
index 8bd109e535b7c29b5dac96b68b2ba59329ca6a59..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/StatsApi.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Created by mirco on 18.01.16.
- */
-
-package eu.hbp.mip.controllers;
-
-import eu.hbp.mip.model.GeneralStats;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.repositories.ArticleRepository;
-import eu.hbp.mip.repositories.UserRepository;
-import eu.hbp.mip.utils.Logging;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-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;
-import org.springframework.web.bind.annotation.RestController;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-@RestController
-@RequestMapping(value = "/stats", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/stats", description = "the stats API")
-public class StatsApi {
-    @Autowired
-    private UserRepository userRepository;
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @Autowired
-    private ArticleRepository articleRepository;
-
-
-    @ApiOperation(value = "Get general statistics", response = GeneralStats.class)
-    @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<GeneralStats> getGeneralStatistics() {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /stats", "Loading general statistics");
-
-        GeneralStats stats = new GeneralStats();
-
-        stats.setUsers(userRepository.count());
-        stats.setArticles(articleRepository.count());
-
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /stats", "Loaded " + userRepository.count() + " user statistics and " + articleRepository.count() + " artcle statistics.");
-        return ResponseEntity.ok(stats);
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/UsersApi.java b/src/main/java/eu/hbp/mip/controllers/UsersApi.java
deleted file mode 100644
index b791a7858e216d8ce0f8cd36610763c5c123e66a..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/UsersApi.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Created by mirco on 14.01.16.
- */
-
-package eu.hbp.mip.controllers;
-
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.repositories.UserRepository;
-import eu.hbp.mip.utils.Logging;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-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;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-@RestController
-@RequestMapping(value = "/users", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/users", description = "the users API")
-public class UsersApi {
-
-    @Autowired
-    private UserRepository userRepository;
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @ApiOperation(value = "Get a user", response = User.class)
-    @RequestMapping(value = "/{username}", method = RequestMethod.GET)
-    public ResponseEntity<User> getAUser(
-            @ApiParam(value = "username", required = true) @PathVariable("username") String username
-    ) {
-        Logging.LogUserAction(userInfo.getUser().getUsername(), "(GET) /users/{username}", "Loaded a user with username : " + userInfo.getUser().getUsername());
-
-        return ResponseEntity.ok(userRepository.findOne(username));
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetroFitGalaxyClients.java b/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetroFitGalaxyClients.java
index 612dce6ca5b557f23deafdf873978c0f442eb1d9..609163e8920ad3443e908c36aea6143ba69533c1 100644
--- a/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetroFitGalaxyClients.java
+++ b/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetroFitGalaxyClients.java
@@ -1,9 +1,9 @@
 package eu.hbp.mip.controllers.galaxy.retrofit;
 
 import com.google.gson.JsonObject;
-import eu.hbp.mip.model.galaxy.GalaxyWorkflowResult;
-import eu.hbp.mip.model.galaxy.PostWorkflowToGalaxyDtoResponse;
-import eu.hbp.mip.model.galaxy.WorkflowDTO;
+import eu.hbp.mip.models.galaxy.GalaxyWorkflowResult;
+import eu.hbp.mip.models.galaxy.PostWorkflowToGalaxyDtoResponse;
+import eu.hbp.mip.models.galaxy.WorkflowDTO;
 import retrofit2.Call;
 import retrofit2.http.*;
 
diff --git a/src/main/java/eu/hbp/mip/model/AlgorithmDTO.java b/src/main/java/eu/hbp/mip/model/AlgorithmDTO.java
deleted file mode 100644
index ed0ef2a15606ef09f139bad65c90c3cf436c2474..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/AlgorithmDTO.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package eu.hbp.mip.model;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-
-public class AlgorithmDTO {
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDesc() {
-        return desc;
-    }
-
-    public void setDesc(String desc) {
-        this.desc = desc;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public List<AlgorithmParamDTO> getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(List<AlgorithmParamDTO> parameters) {
-        this.parameters = parameters;
-    }
-
-    @SerializedName("name")
-    private String name;
-
-    @SerializedName("desc")
-    private String desc;
-
-    @SerializedName("label")
-    private String label;
-
-    @SerializedName("type")
-    private String type;
-
-    @SerializedName("parameters")
-    private List<AlgorithmParamDTO> parameters;
-
-    public static class AlgorithmParamDTO {
-        @SerializedName("name")
-        private String name;
-
-        @SerializedName("desc")
-        private String desc;
-
-        @SerializedName("label")
-        private String label;
-
-        @SerializedName("type")
-        private String type;
-
-        @SerializedName("columnValuesSQLType")
-        private String columnValuesSQLType;
-
-        @SerializedName("columnValuesIsCategorical")
-        private String columnValuesIsCategorical;
-
-        @SerializedName("value")
-        private String value;
-
-        @SerializedName("defaultValue")
-        private String defaultValue;
-
-        @SerializedName("valueType")
-        private String valueType;
-
-        @SerializedName("valueNotBlank")
-        private String valueNotBlank;
-
-        @SerializedName("valueMultiple")
-        private String valueMultiple;
-
-        @SerializedName("valueMin")
-        private String valueMin;
-
-        @SerializedName("valueMax")
-        private String valueMax;
-
-        @SerializedName("valueEnumerations")
-        private List<String> valueEnumerations;
-
-        public String getName() {
-            return name;
-        }
-
-        public void setName(String name) {
-            this.name = name;
-        }
-
-        public String getDesc() {
-            return desc;
-        }
-
-        public void setDesc(String desc) {
-            this.desc = desc;
-        }
-
-        public String getLabel() {
-            return label;
-        }
-
-        public void setLabel(String label) {
-            this.label = label;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        public void setType(String type) {
-            this.type = type;
-        }
-
-        public String getColumnValuesSQLType() {
-            return columnValuesSQLType;
-        }
-
-        public void setColumnValuesSQLType(String columnValuesSQLType) {
-            this.columnValuesSQLType = columnValuesSQLType;
-        }
-
-        public String getColumnValuesIsCategorical() {
-            return columnValuesIsCategorical;
-        }
-
-        public void setColumnValuesIsCategorical(String columnValuesIsCategorical) {
-            this.columnValuesIsCategorical = columnValuesIsCategorical;
-        }
-
-        public String getValue() {
-            return value;
-        }
-
-        public void setValue(String value) {
-            this.value = value;
-        }
-
-        public String getDefaultValue() {
-            return defaultValue;
-        }
-
-        public void setDefaultValue(String defaultValue) {
-            this.defaultValue = defaultValue;
-        }
-
-        public String getValueType() {
-            return valueType;
-        }
-
-        public void setValueType(String valueType) {
-            this.valueType = valueType;
-        }
-
-        public String getValueNotBlank() {
-            return valueNotBlank;
-        }
-
-        public void setValueNotBlank(String valueNotBlank) {
-            this.valueNotBlank = valueNotBlank;
-        }
-
-        public String getValueMultiple() {
-            return valueMultiple;
-        }
-
-        public void setValueMultiple(String valueMultiple) {
-            this.valueMultiple = valueMultiple;
-        }
-
-        public String getValueMin() {
-            return valueMin;
-        }
-
-        public void setValueMin(String valueMin) {
-            this.valueMin = valueMin;
-        }
-
-        public String getValueMax() {
-            return valueMax;
-        }
-
-        public void setValueMax(String valueMax) {
-            this.valueMax = valueMax;
-        }
-
-        public List<String> getValueEnumerations() {
-            return valueEnumerations;
-        }
-
-        public void setValueEnumerations(List<String> valueEnumerations) {
-            this.valueEnumerations = valueEnumerations;
-        }
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Article.java b/src/main/java/eu/hbp/mip/model/Article.java
deleted file mode 100644
index 95c7cbbae0701558b249dec7a5cf0b9a07bd3e92..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Article.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import io.swagger.annotations.ApiModel;
-import org.springframework.validation.annotation.Validated;
-
-import javax.persistence.*;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-@Entity
-@Table(name = "`article`")
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Validated
-public class Article {
-
-    @Id
-    private String slug = null;
-
-    @NotNull
-    @Size(min = 1, max = 255)
-    private String title;
-
-    private String status = null;
-
-    @Column(columnDefinition = "text", name = "abstract")
-    private String abstractText = null;
-
-    @Column(columnDefinition = "text")
-    private String content = null;
-
-    private Date publishedAt = null;
-
-    private Date createdAt = null;
-
-    private Date updatedAt = null;
-
-    @ManyToOne
-    @JoinColumn(name = "createdby_username")
-    private User createdBy = null;
-
-    @ManyToOne
-    @JoinColumn(name = "updatedby_username")
-    private User updatedBy = null;
-
-    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
-    private List<Tag> tags = new LinkedList<>();
-
-
-    public Article() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-        title = "";
-    }
-
-
-    public String getStatus() {
-        return status;
-    }
-
-    public void setStatus(String status) {
-        this.status = status;
-    }
-
-
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-
-    public String getSlug() {
-        return slug;
-    }
-
-    public void setSlug(String slug) {
-        this.slug = slug;
-    }
-
-
-    @JsonProperty("abstract")
-    public String getAbstract() {
-        return abstractText;
-    }
-
-    public void setAbstract(String abstractText) {
-        this.abstractText = abstractText;
-    }
-
-
-    public String getContent() {
-        return content;
-    }
-
-    public void setContent(String content) {
-        this.content = content;
-    }
-
-
-    public Date getPublishedAt() {
-        return publishedAt;
-    }
-
-    public void setPublishedAt(Date publishedAt) {
-        this.publishedAt = publishedAt;
-    }
-
-
-    public Date getCreatedAt() {
-        return createdAt;
-    }
-
-    public void setCreatedAt(Date createdAt) {
-        this.createdAt = createdAt;
-    }
-
-
-    public Date getUpdatedAt() {
-        return updatedAt;
-    }
-
-    public void setUpdatedAt(Date updatedAt) {
-        this.updatedAt = updatedAt;
-    }
-
-
-    public User getCreatedBy() {
-        return createdBy;
-    }
-
-    public void setCreatedBy(User createdBy) {
-        this.createdBy = createdBy;
-    }
-
-
-    public User getUpdatedBy() {
-        return updatedBy;
-    }
-
-    public void setUpdatedBy(User updatedBy) {
-        this.updatedBy = updatedBy;
-    }
-
-
-    public List<Tag> getTags() {
-        return tags;
-    }
-
-    public void setTags(List<Tag> tags) {
-        this.tags = tags;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Config.java b/src/main/java/eu/hbp/mip/model/Config.java
deleted file mode 100644
index 2362194b2b8338d7ab7a0b781c7891e88acfd293..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Config.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * Created by mirco on 25.02.16.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.*;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-@Entity
-@Table(name = "`config`")
-@ApiModel
-@JsonIgnoreProperties(value = {"id"})
-public class Config {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.SEQUENCE)
-    private Long id = null;
-
-    private String type = null;
-
-    private Integer height = null;
-
-    @ElementCollection(fetch = FetchType.EAGER)
-    @CollectionTable(name = "config_yAxisVariables", joinColumns = @JoinColumn(name = "config_id"))
-    private List<String> yAxisVariables = new LinkedList<>();
-
-    private String xAxisVariable = null;
-
-    private Boolean hasXAxis = null;
-
-    @ElementCollection(fetch = FetchType.EAGER)
-    @CollectionTable(name = "config_title", joinColumns = @JoinColumn(name = "config_id"))
-    private Map<String, String> title = new HashMap<>();
-
-
-    public Config() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-
-    public Integer getHeight() {
-        return height;
-    }
-
-    public void setHeight(Integer height) {
-        this.height = height;
-    }
-
-
-    public List<String> getyAxisVariables() {
-        return yAxisVariables;
-    }
-
-    public void setyAxisVariables(List<String> yAxisVariables) {
-        this.yAxisVariables = yAxisVariables;
-    }
-
-
-    public String getxAxisVariable() {
-        return xAxisVariable;
-    }
-
-    public void setxAxisVariable(String xAxisVariable) {
-        this.xAxisVariable = xAxisVariable;
-    }
-
-
-    public Boolean getHasXAxis() {
-        return hasXAxis;
-    }
-
-    public void setHasXAxis(Boolean hasXAxis) {
-        this.hasXAxis = hasXAxis;
-    }
-
-
-    public Map<String, String> getTitle() {
-        return title;
-    }
-
-    public void setTitle(Map<String, String> title) {
-        this.title = title;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Dataset.java b/src/main/java/eu/hbp/mip/model/Dataset.java
deleted file mode 100644
index d920571d9526dca8d29316d8d56578dc3d0b3b9b..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Dataset.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.*;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-// TODO: deprecate
-
-@Entity
-@Table(name = "`dataset`")
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Dataset {
-
-    @Id
-    private String code = null;
-
-    private Date date = null;
-
-    // Aka covariables
-    @ElementCollection
-    @CollectionTable(name = "dataset_header", joinColumns = @JoinColumn(name = "dataset_code"))
-    private List<String> header = new LinkedList<>();
-
-    @ElementCollection
-    @CollectionTable(name = "dataset_grouping", joinColumns = @JoinColumn(name = "dataset_code"))
-    private List<String> grouping = new LinkedList<>();
-
-    @ElementCollection
-    @CollectionTable(name = "dataset_variable", joinColumns = @JoinColumn(name = "dataset_code"))
-    private List<String> variable = new LinkedList<>();
-
-    // TODO:
-    @Transient
-    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
-    private Object data = null;
-
-
-    public Dataset() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-
-    public Date getDate() {
-        return date;
-    }
-
-    public void setDate(Date date) {
-        this.date = date;
-    }
-
-
-    public List<String> getHeader() {
-        return header;
-    }
-
-    public void setHeader(List<String> header) {
-        this.header = header;
-    }
-
-
-    public List<String> getGrouping() {
-        return grouping;
-    }
-
-    public void setGrouping(List<String> grouping) {
-        this.grouping = grouping;
-    }
-
-
-    public List<String> getVariable() {
-        return variable;
-    }
-
-    public void setVariable(List<String> variable) {
-        this.variable = variable;
-    }
-
-    public Object getData() {
-        return data;
-    }
-
-    public void setData(Object data) {
-        this.data = data;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/DatasetDescription.java b/src/main/java/eu/hbp/mip/model/DatasetDescription.java
deleted file mode 100644
index c77c50aeab3a4256ecadf78aa2f25f89a05a0b92..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/DatasetDescription.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class DatasetDescription {
-
-    private String code;
-    private String label;
-    private String description;
-    private String anonymisationLevel;
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getAnonymisationLevel() {
-        return anonymisationLevel;
-    }
-
-    public void setAnonymisationLevel(String anonymisationLevel) {
-        this.anonymisationLevel = anonymisationLevel;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/Experiment.java b/src/main/java/eu/hbp/mip/model/Experiment.java
deleted file mode 100644
index c40d91d3441ce131e45e5dbda0934c4a3ab0c30b..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Experiment.java
+++ /dev/null
@@ -1,232 +0,0 @@
-package eu.hbp.mip.model;
-
-import com.google.gson.*;
-import com.google.gson.annotations.Expose;
-import org.hibernate.annotations.Cascade;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.persistence.*;
-import java.util.*;
-
-/**
- * Created by habfast on 21/04/16.
- */
-@Entity
-@Table(name = "`experiment`")
-public class Experiment {
-
-    private static final Gson gson = new Gson();
-
-    @Id
-    @Column(columnDefinition = "uuid")
-    @org.hibernate.annotations.Type(type = "pg-uuid")
-    @Expose
-    private UUID uuid;
-
-    @Column(columnDefinition = "TEXT")
-    @Expose
-    private String name;
-
-    @Expose
-    @ManyToOne
-    @JoinColumn(name = "createdby_username")
-    private User createdBy;
-
-    @ManyToOne
-    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
-    @Expose
-    private Model model;
-
-    @Column(columnDefinition = "TEXT")
-    @Expose
-    private String algorithms;
-
-    @Column(columnDefinition = "TEXT")
-    private String validations;
-
-    @Column(columnDefinition = "TEXT")
-    @Expose
-    private String workflowHistoryId;
-
-    @Column(columnDefinition = "TEXT")
-    @Expose
-    private String workflowStatus;
-
-    @Column(columnDefinition = "TEXT")
-    @Expose
-    private String result;
-
-    @Expose
-    private Date created = new Date();
-
-    @Expose
-    private Date finished;
-
-    @Expose
-    private boolean hasError = false;
-
-    @Expose
-    private boolean hasServerError = false;
-
-    @Expose
-    private boolean shared = false;
-
-    // whether or not the experiment's result have been resultsViewed by its owner
-    @Expose
-    private boolean resultsViewed = false;
-
-    public Experiment() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public JsonObject jsonify() {
-        JsonObject exp = gson.toJsonTree(this).getAsJsonObject();
-        JsonParser parser = new JsonParser();
-
-        if (this.algorithms != null) {
-            exp.remove("algorithms");
-            JsonArray jsonAlgorithms = parser.parse(this.algorithms).getAsJsonArray();
-            exp.add("algorithms", jsonAlgorithms);
-        }
-
-        if (this.validations != null) {
-            exp.remove("validations");
-            JsonArray jsonValidations = parser.parse(this.validations).getAsJsonArray();
-            exp.add("validations", jsonValidations);
-        }
-
-        if (this.result != null && !this.hasServerError) {
-            exp.remove("result");
-
-            JsonElement jsonResult = parser.parse(this.result);
-            exp.add("result", jsonResult);
-
-        }
-
-        return exp;
-    }
-
-    public String getValidations() {
-        return validations;
-    }
-
-    public void setValidations(String validations) {
-        this.validations = validations;
-    }
-
-    public String getAlgorithms() {
-        return algorithms;
-    }
-
-    public void setAlgorithms(String algorithms) {
-        this.algorithms = algorithms;
-    }
-
-    public Model getModel() {
-        return model;
-    }
-
-    public void setModel(Model model) {
-        this.model = model;
-    }
-
-    public boolean isHasError() {
-        return hasError;
-    }
-
-    public void setHasError(boolean hasError) {
-        this.hasError = hasError;
-    }
-
-    public String getWorkflowHistoryId() {
-        return workflowHistoryId;
-    }
-
-    public void setWorkflowHistoryId(String workflowHistoryId) {
-        this.workflowHistoryId = workflowHistoryId;
-    }
-
-    public String getWorkflowStatus() {
-        return workflowStatus;
-    }
-
-    public void setWorkflowStatus(String workflowStatus) {
-        this.workflowStatus = workflowStatus;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(String result) {
-        this.result = result;
-    }
-
-    public Date getFinished() {
-        return finished;
-    }
-
-    public void setFinished(Date finished) {
-        this.finished = finished;
-    }
-
-    public Date getCreated() {
-        return created;
-    }
-
-    public void setCreated(Date created) {
-        this.created = created;
-    }
-
-    public UUID getUuid() {
-        return uuid;
-    }
-
-    public void setUuid(UUID uuid) {
-        this.uuid = uuid;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public User getCreatedBy() {
-        return createdBy;
-    }
-
-    public void setCreatedBy(User createdBy) {
-        this.createdBy = createdBy;
-    }
-
-    public boolean isResultsViewed() {
-        return resultsViewed;
-    }
-
-    public void setResultsViewed(boolean resultsViewed) {
-        this.resultsViewed = resultsViewed;
-    }
-
-    public boolean isHasServerError() {
-        return hasServerError;
-    }
-
-    public void setHasServerError(boolean hasServerError) {
-        this.hasServerError = hasServerError;
-    }
-
-    public boolean isShared() {
-        return shared;
-    }
-
-    public void setShared(boolean shared) {
-        this.shared = shared;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/ExperimentExecutionDTO.java b/src/main/java/eu/hbp/mip/model/ExperimentExecutionDTO.java
deleted file mode 100644
index a68cd9121d852503bc01eb6b2f0d23dd8af525dd..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/ExperimentExecutionDTO.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package eu.hbp.mip.model;
-
-import java.util.List;
-
-public class ExperimentExecutionDTO {
-
-    private String name;
-    private String model;
-    private List<AlgorithmExecutionDTO> algorithms;
-
-    public String getModel() {
-        return model;
-    }
-
-    public void setModel(String model) {
-        this.model = model;
-    }
-
-    public List<AlgorithmExecutionDTO> getAlgorithms() {
-        return algorithms;
-    }
-
-    public void setAlgorithms(List<AlgorithmExecutionDTO> algorithms) {
-        this.algorithms = algorithms;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public static class AlgorithmExecutionDTO {
-
-        private String name;
-        private String label;
-        private String type;
-
-        private List<AlgorithmExecutionParamDTO> parameters;
-
-        public String getName() {
-            return name;
-        }
-
-        public void setName(String name) {
-            this.name = name;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        public void setType(String type) {
-            this.type = type;
-        }
-
-        public List<AlgorithmExecutionDTO.AlgorithmExecutionParamDTO> getParameters() {
-            return parameters;
-        }
-
-        public void setParameters(List<AlgorithmExecutionDTO.AlgorithmExecutionParamDTO> parameters) {
-            this.parameters = parameters;
-        }
-
-        public String getLabel() {
-            return label;
-        }
-
-        public void setLabel(String label) {
-            this.label = label;
-        }
-
-        public static class AlgorithmExecutionParamDTO {
-
-            private String name;
-            private String label;
-            private String value;
-
-            public String getName() {
-                return this.name;
-            }
-
-            public void setName(String name) {
-                this.name = name;
-            }
-
-            public String getValue() {
-                return value;
-            }
-
-            public void setValue(String value) {
-                this.value = value;
-            }
-
-            public String getLabel() {
-                return label;
-            }
-
-            public void setLabel(String label) {
-                this.label = label;
-            }
-        }
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/GeneralStats.java b/src/main/java/eu/hbp/mip/model/GeneralStats.java
deleted file mode 100644
index 4253ae7dd859ed63a47ffba68a9bcafc5646302c..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/GeneralStats.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Created by mirco on 03.02.16.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class GeneralStats {
-
-    private Long users = null;
-    private Long articles = null;
-
-
-    public GeneralStats() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public Long getUsers() {
-        return users;
-    }
-
-    public void setUsers(Long users) {
-        this.users = users;
-    }
-
-
-    public Long getArticles() {
-        return articles;
-    }
-
-    public void setArticles(Long articles) {
-        this.articles = articles;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/Group.java b/src/main/java/eu/hbp/mip/model/Group.java
deleted file mode 100644
index abb195a932669d28785b407ad3738ab8087cffe7..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Group.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "`group`")
-@ApiModel
-@JsonIgnoreProperties(value = {"parent"})
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Group {
-
-    @Id
-    private String code = null;
-
-
-    public Group() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public String getCode() {
-        return code;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Mining.java b/src/main/java/eu/hbp/mip/model/Mining.java
deleted file mode 100644
index 46cfd6c3ec64b0a7e552cd4f6e210a24a746fc1e..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Mining.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package eu.hbp.mip.model;
-
-import com.google.gson.*;
-
-import java.util.Date;
-
-public class Mining {
-
-    private static final Gson gson = new Gson();
-
-    private final String jobId;
-    private final String node;
-    private final String function;
-    private final String shape;
-    private final Date timestamp;
-    private final String data;
-
-    public Mining(String jobId, String node, String function, String shape, Date timestamp, String data) {
-        this.jobId = jobId;
-        this.node = node;
-        this.function = function;
-        this.shape = shape;
-        this.timestamp = timestamp;
-        this.data = data;
-    }
-
-    public String getJobId() {
-        return jobId;
-    }
-
-    public String getNode() {
-        return node;
-    }
-
-    public String getFunction() {
-        return function;
-    }
-
-    public String getShape() {
-        return shape;
-    }
-
-    public Date getTimestamp() {
-        return timestamp;
-    }
-
-    public String getData() {
-        return data;
-    }
-
-    public JsonObject jsonify() {
-        JsonObject exp = gson.toJsonTree(this).getAsJsonObject();
-        JsonParser parser = new JsonParser();
-
-        if (this.data != null) {
-            exp.remove("data");
-            JsonElement jsonResult = parser.parse(this.data);
-            exp.add("data", jsonResult);
-        }
-
-        return exp;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/MiningQuery.java b/src/main/java/eu/hbp/mip/model/MiningQuery.java
deleted file mode 100644
index 171c55032eee4b3c5f63d636c137d6ae41bfe051..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/MiningQuery.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package eu.hbp.mip.model;
-
-import com.google.gson.Gson;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Created by mirco on 06.01.17.
- */
-public class MiningQuery {
-
-    private List<Variable> variables;
-    private List<Variable> covariables;
-    private List<Variable> grouping;
-    private List<Variable> datasets;
-    private String filters;
-    private ExperimentExecutionDTO.AlgorithmExecutionDTO algorithm;
-
-    public MiningQuery() {
-        this.variables = new LinkedList<>();
-        this.covariables = new LinkedList<>();
-        this.grouping = new LinkedList<>();
-        this.datasets = new LinkedList<>();
-        this.filters = "";
-    }
-
-    public List<Variable> getVariables() {
-        return variables;
-    }
-
-    public void setVariables(List<Variable> variables) {
-        this.variables = variables;
-    }
-
-    public void addVariable(Variable variable) {
-        this.variables.add(variable);
-    }
-
-    public List<Variable> getCovariables() {
-        return covariables;
-    }
-
-    public void setCovariables(List<Variable> covariables) {
-        this.covariables = covariables;
-    }
-
-    public void addCovariable(Variable variable) {
-        this.covariables.add(variable);
-    }
-
-    public List<Variable> getGrouping() {
-        return grouping;
-    }
-
-    public void setGrouping(List<Variable> grouping) {
-        this.grouping = grouping;
-    }
-
-    public List<Variable> getDatasets() {
-        return datasets;
-    }
-
-    public void setDataset(List<Variable> datasets) {
-        this.datasets = datasets;
-    }
-
-    public void addDataset(Variable variable) {
-        this.datasets.add(variable);
-    }
-
-    public void addGrouping(Variable variable) {
-        this.grouping.add(variable);
-    }
-
-    public String getFilters() {
-        return filters;
-    }
-
-    public void setFilters(String filters) {
-        this.filters = filters;
-    }
-
-    public ExperimentExecutionDTO.AlgorithmExecutionDTO getAlgorithm() {
-        return algorithm;
-    }
-
-    public void setAlgorithm(ExperimentExecutionDTO.AlgorithmExecutionDTO algorithm) {
-        this.algorithm = algorithm;
-    }
-
-    @Override
-    public String toString() {
-        return new Gson().toJson(this);
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/Model.java b/src/main/java/eu/hbp/mip/model/Model.java
deleted file mode 100644
index b1590803720c5a0c38538667ef48c940d644399c..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Model.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.google.gson.annotations.Expose;
-import io.swagger.annotations.ApiModel;
-import org.hibernate.annotations.Cascade;
-import org.hibernate.annotations.CascadeType;
-
-import javax.persistence.*;
-import java.util.Date;
-
-@Entity
-@Table(name = "`model`")
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Model {
-
-    @Id
-    @Expose
-    private String slug = null;
-
-    @Expose
-    private String title = null;
-
-    private String description = null;
-
-    private Boolean valid = null;
-
-    private Date createdAt = null;
-
-    private Date updatedAt = null;
-
-    @ManyToOne
-    @Cascade(CascadeType.SAVE_UPDATE)
-    private eu.hbp.mip.model.Query query = null;
-
-    @ManyToOne
-    @Cascade(CascadeType.SAVE_UPDATE)
-    private Dataset dataset = null;
-
-    @ManyToOne
-    @Cascade(CascadeType.SAVE_UPDATE)
-    private Config config = null;
-
-    @ManyToOne
-    @JoinColumn(name = "createdby_username")
-    private User createdBy = null;
-
-    @ManyToOne
-    @JoinColumn(name = "updatedby_username")
-    private User updatedBy = null;
-
-
-    public Model() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-
-    public String getSlug() {
-        return slug;
-    }
-
-    public void setSlug(String slug) {
-        this.slug = slug;
-    }
-
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-
-    public eu.hbp.mip.model.Query getQuery() {
-        return query;
-    }
-
-    public void setQuery(eu.hbp.mip.model.Query query) {
-        this.query = query;
-    }
-
-
-    public Dataset getDataset() {
-        return dataset;
-    }
-
-    public void setDataset(Dataset dataset) {
-        this.dataset = dataset;
-    }
-
-
-    public Boolean getValid() {
-        return valid;
-    }
-
-    public void setValid(Boolean valid) {
-        this.valid = valid;
-    }
-
-
-    public Config getConfig() {
-        return config;
-    }
-
-    public void setConfig(Config config) {
-        this.config = config;
-    }
-
-
-    public Date getCreatedAt() {
-        return createdAt;
-    }
-
-    public void setCreatedAt(Date createdAt) {
-        this.createdAt = createdAt;
-    }
-
-
-    public Date getUpdatedAt() {
-        return updatedAt;
-    }
-
-    public void setUpdatedAt(Date updatedAt) {
-        this.updatedAt = updatedAt;
-    }
-
-
-    public User getCreatedBy() {
-        return createdBy;
-    }
-
-    public void setCreatedBy(User createdBy) {
-        this.createdBy = createdBy;
-    }
-
-
-    public User getUpdatedBy() {
-        return updatedBy;
-    }
-
-    public void setUpdatedBy(User updatedBy) {
-        this.updatedBy = updatedBy;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/PathologyDTO.java b/src/main/java/eu/hbp/mip/model/PathologyDTO.java
deleted file mode 100644
index c58238b623e18aa5f7942d9e4816f905ce48f3f8..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/PathologyDTO.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package eu.hbp.mip.model;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-
-public class PathologyDTO {
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-    public Object getMetadataHierarchy() {
-        return metadataHierarchy;
-    }
-
-    public void setMetadataHierarchy(Object metadataHierarchy) {
-        this.metadataHierarchy = metadataHierarchy;
-    }
-
-    public List<PathologyDatasetDTO> getDatasets() {
-        return datasets;
-    }
-
-    public void setDatasets(List<PathologyDatasetDTO> datasets) {
-        this.datasets = datasets;
-    }
-
-    @SerializedName("code")
-    private String code;
-
-    @SerializedName("label")
-    private String label;
-
-    @SerializedName("metadataHierarchy")
-    private Object metadataHierarchy;
-
-    @SerializedName("datasets")
-    private List<PathologyDatasetDTO> datasets;
-
-    public static class PathologyDatasetDTO {
-        @SerializedName("code")
-        private String code;
-
-        @SerializedName("label")
-        private String label;
-
-        public String getCode() {
-            return code;
-        }
-
-        public void setCode(String code) {
-            this.code = code;
-        }
-
-        public String getLabel() {
-            return label;
-        }
-
-        public void setLabel(String label) {
-            this.label = label;
-        }
-
-        public String toString() {
-            return code;
-        }
-    }
-
-    public String toString() {
-        return code;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Query.java b/src/main/java/eu/hbp/mip/model/Query.java
deleted file mode 100644
index 8e4d78dcbb1534052e9108aa9cf6d35be6ffa26e..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Query.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.*;
-import java.util.LinkedList;
-import java.util.List;
-
-@Entity
-@ApiModel
-@Table(name = "`query`")
-@JsonIgnoreProperties(value = {"id"})
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Query {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.SEQUENCE)
-    private Long id = null;
-
-    @ManyToMany
-    @JoinTable(name = "query_variable", joinColumns = {
-            @JoinColumn(name = "id", nullable = false, updatable = false)},
-            inverseJoinColumns = {@JoinColumn(name = "code",
-                    nullable = false, updatable = false)})
-    private List<Variable> variables = new LinkedList<>();
-
-    @ManyToMany
-    @JoinTable(name = "query_covariable", joinColumns = {
-            @JoinColumn(name = "id", nullable = false, updatable = false)},
-            inverseJoinColumns = {@JoinColumn(name = "code",
-                    nullable = false, updatable = false)})
-    private List<Variable> covariables = new LinkedList<>();
-
-    @ManyToMany
-    @JoinTable(name = "query_grouping", joinColumns = {
-            @JoinColumn(name = "id", nullable = false, updatable = false)},
-            inverseJoinColumns = {@JoinColumn(name = "code",
-                    nullable = false, updatable = false)})
-    private List<Variable> grouping = new LinkedList<>();
-
-    @ManyToMany
-    @JoinTable(name = "query_training_datasets", joinColumns = {
-            @JoinColumn(name = "id", nullable = false, updatable = false)},
-            inverseJoinColumns = {@JoinColumn(name = "code",
-                    nullable = false, updatable = false)})
-    private List<Variable> trainingDatasets = new LinkedList<>();
-
-    @ManyToMany
-    @JoinTable(name = "query_testing_datasets", joinColumns = {
-            @JoinColumn(name = "id", nullable = false, updatable = false)},
-            inverseJoinColumns = {@JoinColumn(name = "code",
-                    nullable = false, updatable = false)})
-    private List<Variable> testingDatasets = new LinkedList<>();
-
-    @ManyToMany
-    @JoinTable(name = "query_validation_datasets", joinColumns = {
-            @JoinColumn(name = "id", nullable = false, updatable = false)},
-            inverseJoinColumns = {@JoinColumn(name = "code",
-                    nullable = false, updatable = false)})
-    private List<Variable> validationDatasets = new LinkedList<>();
-
-    @Column(columnDefinition = "text")
-    private String filters = "";
-
-    @Column(columnDefinition = "text")
-    private String pathology = "";
-
-
-    public Query() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-
-    @JsonProperty("variables")
-    public List<Variable> getVariables() {
-        return variables;
-    }
-
-    public void setVariables(List<Variable> variables) {
-        this.variables = variables;
-    }
-
-
-    @JsonProperty("coVariables")
-    public List<Variable> getCovariables() {
-        return covariables;
-    }
-
-    public void setCovariables(List<Variable> covariables) {
-        this.covariables = covariables;
-    }
-
-
-    @JsonProperty("groupings")
-    public List<Variable> getGrouping() {
-        return grouping;
-    }
-
-    public void setGrouping(List<Variable> grouping) {
-        this.grouping = grouping;
-    }
-
-    @JsonProperty("trainingDatasets")
-    public List<Variable> getTrainingDatasets() {
-        return trainingDatasets;
-    }
-
-    public void setTrainingDatasets(List<Variable> trainingDatasets) {
-        this.trainingDatasets = trainingDatasets;
-    }
-
-    @JsonProperty("testingDatasets")
-    public List<Variable> getTestingDatasets() {
-        return testingDatasets;
-    }
-
-    public void setTestingDatasets(List<Variable> testingDatasets) {
-        this.testingDatasets = testingDatasets;
-    }
-
-    @JsonProperty("validationDatasets")
-    public List<Variable> getValidationDatasets() {
-        return validationDatasets;
-    }
-
-    public void setValidationDatasets(List<Variable> validationDatasets) {
-        this.validationDatasets = validationDatasets;
-    }
-
-    public String getFilters() {
-        return filters;
-    }
-
-    public void setFilters(String filters) {
-        this.filters = filters;
-    }
-
-    public String getPathology() {
-        return pathology;
-    }
-
-    public void setPathology(String pathology) {
-        this.pathology = pathology;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Tag.java b/src/main/java/eu/hbp/mip/model/Tag.java
deleted file mode 100644
index 693c9865602ace72de50d067e3dd5e3eaac97526..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Tag.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "`tag`")
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Tag {
-
-    @Id
-    private String name = null;
-
-
-    public Tag() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/User.java b/src/main/java/eu/hbp/mip/model/User.java
deleted file mode 100644
index 64fee4b670e6285a0e06ada431975fd5c17cf50e..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/User.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.google.gson.annotations.Expose;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.*;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-@Entity
-@Table(name = "`user`")
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonIgnoreProperties(value = {"appsVotes"})
-public class User {
-
-    @Id
-    @Expose
-    private String username = null;
-
-    @Expose
-    private String fullname = null;
-
-    @Expose
-    private String firstname = null;
-
-    @Expose
-    private String lastname = null;
-
-    @Expose
-    private String picture = null;
-
-    @Expose
-    private String web = null;
-
-    @Expose
-    private String phone = null;
-
-    @Expose
-    private String birthday = null;
-
-    @Expose
-    private String gender = null;
-
-    @Expose
-    private String city = null;
-
-    @Expose
-    private String country = null;
-
-    @Expose
-    private String password = null;
-
-    @Expose
-    private String email = null;
-
-    @Expose
-    private String apikey = null;
-
-    @Expose
-    private String team = null;
-
-    @Expose
-    private Boolean isActive = null;
-
-    @ElementCollection(fetch = FetchType.EAGER)
-    @CollectionTable(name = "user_languages", joinColumns = @JoinColumn(name = "user_username"))
-    @Expose
-    private List<String> languages = new LinkedList<>();
-
-    @ElementCollection(fetch = FetchType.EAGER)
-    @CollectionTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_username"))
-    @Expose
-    private List<String> roles = new LinkedList<>();
-
-    private Boolean agreeNDA = null;
-
-
-    public User() {
-        /*
-         *  Empty constructor is needed by Hibernate
-         */
-    }
-
-
-    /**
-     * Create a user using OpenID user profile
-     *
-     * @param userInfo info from OpenID UserInfo endpoint
-     */
-    public User(String userInfo) {
-
-        Pattern p;
-        Matcher m;
-
-        p = Pattern.compile("preferred_username=([\\w- ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.username = m.group(1);
-        }
-
-        p = Pattern.compile("name=([\\w ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.fullname = m.group(1);
-        }
-
-        p = Pattern.compile("given_name=([\\w ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.firstname = m.group(1);
-        }
-
-        p = Pattern.compile("family_name=([\\w ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.lastname = m.group(1);
-        }
-
-        p = Pattern.compile("email=([\\w.]+@[\\w.]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.email = m.group(1);
-        }
-
-        p = Pattern.compile("title=([\\w ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            if ("Mr".equals(m.group(1))) {
-                this.gender = "Male";
-            } else {
-                this.gender = "Female";
-            }
-        }
-
-        p = Pattern.compile("contractor=([\\w ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.team = m.group(1);
-        }
-
-        p = Pattern.compile("picture=([-a-zA-Z0-9+&@#/%=~_|.: ]+)");
-        m = p.matcher(userInfo);
-        if (m.find()) {
-            this.picture = m.group(1);
-        }
-
-        if (this.picture == null || this.picture.isEmpty()) {
-            this.picture = "images/users/default_user.png";
-        }
-
-    }
-
-
-    public String getFullname() {
-        return fullname;
-    }
-
-    public void setFullname(String fullname) {
-        this.fullname = fullname;
-    }
-
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-
-    public String getFirstname() {
-        return firstname;
-    }
-
-    public void setFirstname(String firstname) {
-        this.firstname = firstname;
-    }
-
-
-    public String getLastname() {
-        return lastname;
-    }
-
-    public void setLastname(String lastname) {
-        this.lastname = lastname;
-    }
-
-
-    public String getPicture() {
-        return picture;
-    }
-
-    public void setPicture(String picture) {
-        this.picture = picture;
-    }
-
-
-    public String getWeb() {
-        return web;
-    }
-
-    public void setWeb(String web) {
-        this.web = web;
-    }
-
-
-    public String getPhone() {
-        return phone;
-    }
-
-    public void setPhone(String phone) {
-        this.phone = phone;
-    }
-
-
-    public String getBirthday() {
-        return birthday;
-    }
-
-    public void setBirthday(String birthday) {
-        this.birthday = birthday;
-    }
-
-
-    public String getGender() {
-        return gender;
-    }
-
-    public void setGender(String gender) {
-        this.gender = gender;
-    }
-
-
-    public String getCity() {
-        return city;
-    }
-
-    public void setCity(String city) {
-        this.city = city;
-    }
-
-
-    public String getCountry() {
-        return country;
-    }
-
-    public void setCountry(String country) {
-        this.country = country;
-    }
-
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-
-    public String getEmail() {
-        return email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-    }
-
-
-    public String getApikey() {
-        return apikey;
-    }
-
-    public void setApikey(String apikey) {
-        this.apikey = apikey;
-    }
-
-
-    public String getTeam() {
-        return team;
-    }
-
-    public void setTeam(String team) {
-        this.team = team;
-    }
-
-
-    public Boolean getIsActive() {
-        return isActive;
-    }
-
-    public void setIsActive(Boolean isActive) {
-        this.isActive = isActive;
-    }
-
-
-    public List<String> getLanguages() {
-        return languages;
-    }
-
-    public void setLanguages(List<String> languages) {
-        this.languages = languages;
-    }
-
-
-    public List<String> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(List<String> roles) {
-        this.roles = roles;
-    }
-
-
-    public Boolean getAgreeNDA() {
-        return agreeNDA;
-    }
-
-    public void setAgreeNDA(Boolean agreeNDA) {
-        this.agreeNDA = agreeNDA;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/UserInfo.java b/src/main/java/eu/hbp/mip/model/UserInfo.java
deleted file mode 100644
index 71eee3573b485d690c810b42c1344cc2170fb9f5..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/UserInfo.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package eu.hbp.mip.model;
-
-import eu.hbp.mip.repositories.UserRepository;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Scope;
-import org.springframework.context.annotation.ScopedProxyMode;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.provider.OAuth2Authentication;
-import org.springframework.stereotype.Component;
-
-import javax.inject.Named;
-
-@Component
-@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
-@Named("userInfo")
-public class UserInfo {
-
-    @Autowired
-    private UserRepository userRepository;
-
-    /**
-     * Enable HBP collab authentication (1) or disable it (0). Default is 1
-     */
-    @Value("#{'${hbp.authentication.enabled:1}'}")
-    private boolean authentication;
-
-    private User user;
-
-    /**
-     * Set to true if using no-auth mode and user has clicked on the login button
-     */
-    private boolean fakeAuth = false;
-
-    /**
-     * 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 the user for the current session
-     */
-    public User getUser() {
-        if (user == null) {
-
-            if (!authentication) {
-                user = new User();
-                user.setUsername("anonymous");
-                user.setFullname("anonymous");
-                user.setEmail("anonymous@anonymous.com");
-                user.setPicture("images/users/default_user.png");
-            } else {
-                user = new User(getUserInfos());
-            }
-            User foundUser = userRepository.findOne(user.getUsername());
-            if (foundUser != null) {
-                user.setAgreeNDA(foundUser.getAgreeNDA());
-            }
-            userRepository.save(user);
-        }
-
-        return user;
-    }
-
-    public boolean isFakeAuth() {
-        return fakeAuth;
-    }
-
-    public void setFakeAuth(boolean fakeAuth) {
-        this.fakeAuth = fakeAuth;
-    }
-
-    private String getUserInfos() {
-        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
-        Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();
-        return userAuthentication.getDetails().toString();
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Value.java b/src/main/java/eu/hbp/mip/model/Value.java
deleted file mode 100644
index 784452e591ffc8eb1f62ff5cc0c7f82694c78a3c..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Value.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "`value`")
-@ApiModel
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Value {
-
-    @Id
-    private String code = null;
-
-    private String label = null;
-
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-
-    public String getLabel() {
-        return label;
-    }
-
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/Variable.java b/src/main/java/eu/hbp/mip/model/Variable.java
deleted file mode 100644
index 596be8d775673af068235dabed39323a4440de49..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Variable.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.google.gson.annotations.Expose;
-import io.swagger.annotations.ApiModel;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import java.util.List;
-
-@Entity
-@Table(name = "`variable`")
-@ApiModel
-@JsonIgnoreProperties(value = {"queries"})
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Variable {
-
-    @Id
-    @Expose
-    private String code = null;
-
-    /**
-     * Empty constructor is needed by Hibernate
-     */
-    public Variable() {
-    }
-
-    public Variable(String code) {
-        this.code = code;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public static String stringFromVariables(List<Variable> variables, String operator) {
-        StringBuilder sb = new StringBuilder();
-        int i = 0;
-        for (Variable s : variables) {
-            i++;
-            sb.append(s.getCode());
-            if (i < variables.size()) {
-                sb.append(operator);
-            }
-        }
-        return sb.toString();
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java b/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..585bd8bd6694275d341fe1aea19f82f3105d97ea
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java
@@ -0,0 +1,116 @@
+package eu.hbp.mip.models.DAOs;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.google.gson.Gson;
+import com.google.gson.annotations.Expose;
+import eu.hbp.mip.models.DTOs.AlgorithmDTO;
+import eu.hbp.mip.models.DTOs.ExperimentDTO;
+import eu.hbp.mip.utils.JsonConverters;
+import io.swagger.annotations.ApiModel;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.*;
+import java.util.*;
+
+/**
+ * Created by habfast on 21/04/16.
+ */
+@Entity
+@Getter
+@Setter
+@Table(name = "`experiment`")
+@ApiModel
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ExperimentDAO {
+
+    private static final Gson gson = new Gson();
+
+    @Expose
+    @Id
+    @Column(columnDefinition = "uuid", updatable = false)
+    @org.hibernate.annotations.Type(type = "pg-uuid")
+    private UUID uuid;
+
+    @Expose
+    @Column(columnDefinition = "TEXT")
+    private String name;
+
+    @Expose
+    @ManyToOne
+    @JoinColumn(name = "created_by_username",columnDefinition = "CHARACTER VARYING")
+    private UserDAO createdBy;
+
+    @Expose
+    @Column(name="workflow_history_id", columnDefinition = "TEXT")
+    private String workflowHistoryId;
+
+    @Expose
+    @Column(columnDefinition = "TEXT")
+    @Enumerated(EnumType.STRING)
+    private Status status;
+
+    @Expose
+    @Column(columnDefinition = "TEXT")
+    private String result;
+
+    @Expose
+    @Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE")
+    private Date finished;
+
+    @Expose
+    @Column(columnDefinition = "TEXT")
+    private String algorithm;
+
+    @Expose
+    @Column(columnDefinition = "TEXT")
+    private String algorithmId;
+
+    @Expose
+    @Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE")
+    private Date created = new Date();
+    
+    @Expose
+    @Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE")
+    private Date updated;
+
+    @Expose
+    @Column(columnDefinition = "BOOLEAN")
+    private boolean shared = false;
+
+    // whether or not the experiment's result have been viewed by its owner
+    @Expose
+    @Column(columnDefinition = "BOOLEAN")
+    private boolean viewed = false;
+
+    public enum Status {
+        error,
+        pending,
+        success
+    }
+
+    public ExperimentDAO() {
+        /*
+         *  Empty constructor is needed by Hibernate
+         */
+    }
+
+    public ExperimentDTO convertToDTO(boolean includeResult)
+    {
+        ExperimentDTO experimentDTO = new ExperimentDTO();
+        experimentDTO.setAlgorithm(JsonConverters.convertJsonStringToObject(this.algorithm, AlgorithmDTO.class));
+        experimentDTO.setCreated(this.created);
+        experimentDTO.setUpdated(this.updated);
+        experimentDTO.setFinished(this.finished);
+        experimentDTO.setCreatedBy(this.createdBy.getUsername());
+        experimentDTO.setName(this.name);
+        if(includeResult){
+            experimentDTO.setResult(JsonConverters.convertJsonStringToObject(String.valueOf(this.result),  new ArrayList<>().getClass()));
+        }
+        experimentDTO.setStatus(this.status);
+        experimentDTO.setShared(this.shared);
+        experimentDTO.setUuid(this.uuid);
+        experimentDTO.setViewed(this.viewed);
+        return experimentDTO;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java b/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..9279b3793c44c449302c083b823da674d7e4d46f
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java
@@ -0,0 +1,53 @@
+/*
+ * Created by mirco on 04.12.15.
+ */
+
+package eu.hbp.mip.models.DAOs;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.google.gson.annotations.Expose;
+import io.swagger.annotations.ApiModel;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Getter
+@Setter
+@Table(name = "`user`")
+@ApiModel
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class UserDAO {
+
+    @Id
+    @Expose
+    private String username;
+
+    @Expose
+    private String subjectId;
+
+    @Expose
+    private String fullname;
+
+    @Expose
+    private String email;
+
+    @Expose
+    private Boolean agreeNDA;
+
+    public UserDAO() {
+        // Empty constructor is needed by Hibernate
+    }
+
+    public UserDAO(String username, String fullname, String email, String subjectId) {
+        this.username = username;
+        this.fullname = fullname;
+        this.email = email;
+        this.agreeNDA = false;
+        this.subjectId = subjectId;
+
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/AlgorithmDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/AlgorithmDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..52db979d5ddd7b043572be8fc9255c45fa0e9c98
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/models/DTOs/AlgorithmDTO.java
@@ -0,0 +1,73 @@
+package eu.hbp.mip.models.DTOs;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class AlgorithmDTO {
+
+    @SerializedName("name")
+    private String name;
+
+    @SerializedName("desc")
+    private String desc;
+
+    @SerializedName("label")
+    private String label;
+
+    @SerializedName("type")
+    private String type;
+
+    @SerializedName("parameters")
+    private List<AlgorithmParamDTO> parameters;
+
+    @Getter
+    @Setter
+    public static class AlgorithmParamDTO {
+        @SerializedName("name")
+        private String name;
+
+        @SerializedName("desc")
+        private String desc;
+
+        @SerializedName("label")
+        private String label;
+
+        @SerializedName("type")
+        private String type;
+
+        @SerializedName("columnValuesSQLType")
+        private String columnValuesSQLType;
+
+        @SerializedName("columnValuesIsCategorical")
+        private String columnValuesIsCategorical;
+
+        @SerializedName("value")
+        private String value;
+
+        @SerializedName("defaultValue")
+        private String defaultValue;
+
+        @SerializedName("valueType")
+        private String valueType;
+
+        @SerializedName("valueNotBlank")
+        private String valueNotBlank;
+
+        @SerializedName("valueMultiple")
+        private String valueMultiple;
+
+        @SerializedName("valueMin")
+        private String valueMin;
+
+        @SerializedName("valueMax")
+        private String valueMax;
+
+        @SerializedName("valueEnumerations")
+        private List<String> valueEnumerations;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e64c6f75e7d7a4d7aafa8ba93d38f9d3edf6bf19
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java
@@ -0,0 +1,31 @@
+package eu.hbp.mip.models.DTOs;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import eu.hbp.mip.models.DAOs.ExperimentDAO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ExperimentDTO {
+
+    private UUID uuid;
+    private String name;
+    private String createdBy;
+    private Date created;
+    private Date updated;
+    private Date finished;
+    private Boolean shared;
+    private Boolean viewed;
+    private List<Object> result;
+    private ExperimentDAO.Status status;
+    private AlgorithmDTO algorithm;
+
+    public ExperimentDTO() {
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa78ef8b0e315a2f71261dc1fed480cb8617ccb2
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java
@@ -0,0 +1,42 @@
+package eu.hbp.mip.models.DTOs;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class PathologyDTO {
+
+    @SerializedName("code")
+    private String code;
+
+    @SerializedName("label")
+    private String label;
+
+    @SerializedName("metadataHierarchy")
+    private Object metadataHierarchy;
+
+    @SerializedName("datasets")
+    private List<PathologyDatasetDTO> datasets;
+
+    @Getter
+    @Setter
+    public static class PathologyDatasetDTO {
+        @SerializedName("code")
+        private String code;
+
+        @SerializedName("label")
+        private String label;
+
+        public String toString() {
+            return code;
+        }
+    }
+
+    public String toString() {
+        return code;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/ErrorResponse.java b/src/main/java/eu/hbp/mip/models/galaxy/ErrorResponse.java
similarity index 96%
rename from src/main/java/eu/hbp/mip/model/galaxy/ErrorResponse.java
rename to src/main/java/eu/hbp/mip/models/galaxy/ErrorResponse.java
index 77a171358b54561e3492dcb317acd835aeaa645f..2703e742541faf9f715ed19485076d397697059e 100644
--- a/src/main/java/eu/hbp/mip/model/galaxy/ErrorResponse.java
+++ b/src/main/java/eu/hbp/mip/models/galaxy/ErrorResponse.java
@@ -3,7 +3,7 @@
  * Copyright (c) 2019. MIT License
  */
 
-package eu.hbp.mip.model.galaxy;
+package eu.hbp.mip.models.galaxy;
 
 import com.google.gson.annotations.SerializedName;
 
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/GalaxyWorkflowResult.java b/src/main/java/eu/hbp/mip/models/galaxy/GalaxyWorkflowResult.java
similarity index 99%
rename from src/main/java/eu/hbp/mip/model/galaxy/GalaxyWorkflowResult.java
rename to src/main/java/eu/hbp/mip/models/galaxy/GalaxyWorkflowResult.java
index 089a6a626ed1e0d38306c911b515edd3fa8fa5f0..ca7d98fe51e55cd60914893283f2c30b6fcf90be 100644
--- a/src/main/java/eu/hbp/mip/model/galaxy/GalaxyWorkflowResult.java
+++ b/src/main/java/eu/hbp/mip/models/galaxy/GalaxyWorkflowResult.java
@@ -3,7 +3,7 @@
  * Copyright (c) 2019. MIT License
  */
 
-package eu.hbp.mip.model.galaxy;
+package eu.hbp.mip.models.galaxy;
 
 import com.google.gson.annotations.SerializedName;
 
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/PostWorkflowToGalaxyDtoResponse.java b/src/main/java/eu/hbp/mip/models/galaxy/PostWorkflowToGalaxyDtoResponse.java
similarity index 98%
rename from src/main/java/eu/hbp/mip/model/galaxy/PostWorkflowToGalaxyDtoResponse.java
rename to src/main/java/eu/hbp/mip/models/galaxy/PostWorkflowToGalaxyDtoResponse.java
index edefd63266a8d1678bf82d057882e4eccab112cc..96d8aa8efa089599093fed13ac8e0d0a4be81f42 100644
--- a/src/main/java/eu/hbp/mip/model/galaxy/PostWorkflowToGalaxyDtoResponse.java
+++ b/src/main/java/eu/hbp/mip/models/galaxy/PostWorkflowToGalaxyDtoResponse.java
@@ -3,7 +3,7 @@
  * Copyright (c) 2019. MIT License
  */
 
-package eu.hbp.mip.model.galaxy;
+package eu.hbp.mip.models.galaxy;
 
 import com.google.gson.annotations.SerializedName;
 
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/WorkflowDTO.java b/src/main/java/eu/hbp/mip/models/galaxy/WorkflowDTO.java
similarity index 95%
rename from src/main/java/eu/hbp/mip/model/galaxy/WorkflowDTO.java
rename to src/main/java/eu/hbp/mip/models/galaxy/WorkflowDTO.java
index fa0cb4b336ef2f8276db39c1a03097f51a5c8ea7..496ee2dfebf50324b1443774cc48edd4e32c2de0 100644
--- a/src/main/java/eu/hbp/mip/model/galaxy/WorkflowDTO.java
+++ b/src/main/java/eu/hbp/mip/models/galaxy/WorkflowDTO.java
@@ -1,8 +1,8 @@
-package eu.hbp.mip.model.galaxy;
+package eu.hbp.mip.models.galaxy;
 
 import com.google.gson.Gson;
 import com.google.gson.annotations.SerializedName;
-import eu.hbp.mip.model.AlgorithmDTO;
+import eu.hbp.mip.models.DTOs.AlgorithmDTO;
 
 import java.util.*;
 
diff --git a/src/main/java/eu/hbp/mip/repositories/ArticleRepository.java b/src/main/java/eu/hbp/mip/repositories/ArticleRepository.java
deleted file mode 100644
index 1a93186ff064bf5833246d82b2cb0d35bf838312..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/ArticleRepository.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.hbp.mip.model.Article;
-import eu.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/eu/hbp/mip/repositories/ConfigRepository.java b/src/main/java/eu/hbp/mip/repositories/ConfigRepository.java
deleted file mode 100644
index deb286150c0ba9c7833b4dfa66a61d3890c011c4..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/ConfigRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.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/eu/hbp/mip/repositories/DatasetRepository.java b/src/main/java/eu/hbp/mip/repositories/DatasetRepository.java
deleted file mode 100644
index 7c6da1e9745b8a144296d51a5d85434111213b96..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/DatasetRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.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/eu/hbp/mip/repositories/ExperimentRepository.java b/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java
index 2f6ae857d49018c5d9a3cb429f17cf3d2b80d313..9ac54cada906b78ad5ab5ac41d77d05562bedc4e 100644
--- a/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java
+++ b/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java
@@ -1,17 +1,17 @@
 package eu.hbp.mip.repositories;
 
-import eu.hbp.mip.model.Experiment;
-import eu.hbp.mip.model.User;
+import eu.hbp.mip.models.DAOs.ExperimentDAO;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.repository.CrudRepository;
 
+import java.util.Optional;
 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);
+public interface ExperimentRepository extends CrudRepository<ExperimentDAO, UUID>, JpaSpecificationExecutor<ExperimentDAO>
+{
+    ExperimentDAO findByUuid(UUID experimentUuid);
 }
diff --git a/src/main/java/eu/hbp/mip/repositories/ModelRepository.java b/src/main/java/eu/hbp/mip/repositories/ModelRepository.java
deleted file mode 100644
index c25b1e5bb6c4a5e888851b08ae3f0a801d5a4553..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/ModelRepository.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.hbp.mip.model.Model;
-import eu.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/eu/hbp/mip/repositories/QueryRepository.java b/src/main/java/eu/hbp/mip/repositories/QueryRepository.java
deleted file mode 100644
index f0b95d39c4c3a480fe2bec20ce75e46361889e71..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/QueryRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.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/eu/hbp/mip/repositories/TagRepository.java b/src/main/java/eu/hbp/mip/repositories/TagRepository.java
deleted file mode 100644
index 4edb4090e0336ac034daf245d5ca3bb084a6f5ae..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/TagRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.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/eu/hbp/mip/repositories/UserRepository.java b/src/main/java/eu/hbp/mip/repositories/UserRepository.java
index 3a0db7ee31cf9c56cdd68397d641f4a71e8c37a2..99ae0b1dcfc237e875e7ba458175ae8441ec8c8e 100644
--- a/src/main/java/eu/hbp/mip/repositories/UserRepository.java
+++ b/src/main/java/eu/hbp/mip/repositories/UserRepository.java
@@ -1,12 +1,13 @@
 package eu.hbp.mip.repositories;
 
-import eu.hbp.mip.model.User;
+import eu.hbp.mip.models.DAOs.UserDAO;
 import org.springframework.data.repository.CrudRepository;
 
 /**
  * Created by mirco on 11.07.16.
  */
 
-public interface UserRepository extends CrudRepository<User, String> {
+public interface UserRepository extends CrudRepository<UserDAO, String> {
 
+    UserDAO findByUsername(String username);
 }
diff --git a/src/main/java/eu/hbp/mip/repositories/ValueRepository.java b/src/main/java/eu/hbp/mip/repositories/ValueRepository.java
deleted file mode 100644
index b41574d6082542ec1539f8e14203e61eb27e0614..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/ValueRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.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/eu/hbp/mip/repositories/VariableRepository.java b/src/main/java/eu/hbp/mip/repositories/VariableRepository.java
deleted file mode 100644
index 3ded949436f345143bb9e60a51bc0ee2ab20019b..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/repositories/VariableRepository.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package eu.hbp.mip.repositories;
-
-import eu.hbp.mip.model.Variable;
-import org.springframework.data.repository.CrudRepository;
-
-/**
- * Created by mirco on 13.09.16.
- */
-public interface VariableRepository extends CrudRepository<Variable, String> {
-}
diff --git a/src/main/java/eu/hbp/mip/services/ActiveUserService.java b/src/main/java/eu/hbp/mip/services/ActiveUserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc3c8ced7fc3a573a8fe67bd87abaf1dcf19246c
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/services/ActiveUserService.java
@@ -0,0 +1,85 @@
+package eu.hbp.mip.services;
+
+import eu.hbp.mip.models.DAOs.UserDAO;
+import eu.hbp.mip.repositories.UserRepository;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.representations.IDToken;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Named;
+import java.util.Objects;
+
+@Component
+@Named("ActiveUserService")
+@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
+public class ActiveUserService {
+
+    @Value("#{'${authentication.enabled}'}")
+    private boolean authenticationIsEnabled;
+
+    private UserDAO user;
+
+    private final UserRepository userRepository;
+
+    public ActiveUserService(UserRepository userRepository) {
+        this.userRepository = userRepository;
+    }
+
+    /**
+     * Fetches the details of the active user.
+     * If the user doesn't exist, it's created on the fly from the auth token.
+     *
+     * @return the userDAO
+     */
+    public UserDAO getActiveUser() {
+
+        // User already loaded
+        if (user != null)
+            return user;
+
+        // If Authentication is OFF, create anonymous user with accepted NDA
+        if (!authenticationIsEnabled) {
+            user = new UserDAO("anonymous", "anonymous", "anonymous@anonymous.com", "anonymousId");
+            user.setAgreeNDA(true);
+            userRepository.save(user);
+            return user;
+        }
+
+        // If authentication is ON get user info from Token
+        KeycloakPrincipal keycloakPrincipal =
+                (KeycloakPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        IDToken idToken = keycloakPrincipal.getKeycloakSecurityContext().getIdToken();
+        user = new UserDAO(idToken.getPreferredUsername(), idToken.getName(), idToken.getEmail(), idToken.getId());
+
+        UserDAO userInDatabase = userRepository.findByUsername(user.getUsername());
+        if (userInDatabase == null) {
+            userRepository.save(user);
+            return user;
+        }
+
+        if (!Objects.equals(user.getEmail(),userInDatabase.getEmail())
+            || !Objects.equals(user.getFullname(),userInDatabase.getFullname())
+        ) {
+            userInDatabase.setFullname(user.getFullname());
+            userInDatabase.setEmail(user.getEmail());
+        }
+
+        user = userInDatabase;
+        userRepository.save(user);
+        return user;
+    }
+
+    public UserDAO agreeToNDA() {
+        // Fetch the active user
+        getActiveUser();
+
+        user.setAgreeNDA(true);
+        userRepository.save(user);
+
+        return user;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/services/ExperimentService.java b/src/main/java/eu/hbp/mip/services/ExperimentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..45345c8a5b33d5826c149cd384a5b17c0d3b7a78
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/services/ExperimentService.java
@@ -0,0 +1,1008 @@
+package eu.hbp.mip.services;
+
+import com.github.jmchilton.blend4j.galaxy.GalaxyInstance;
+import com.github.jmchilton.blend4j.galaxy.GalaxyInstanceFactory;
+import com.github.jmchilton.blend4j.galaxy.WorkflowsClient;
+import com.github.jmchilton.blend4j.galaxy.beans.Workflow;
+import com.github.jmchilton.blend4j.galaxy.beans.WorkflowDetails;
+import com.github.jmchilton.blend4j.galaxy.beans.WorkflowInputDefinition;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.internal.LinkedTreeMap;
+import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients;
+import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance;
+import eu.hbp.mip.models.DAOs.ExperimentDAO;
+import eu.hbp.mip.models.DAOs.UserDAO;
+import eu.hbp.mip.models.DTOs.AlgorithmDTO;
+import eu.hbp.mip.models.DTOs.ExperimentDTO;
+import eu.hbp.mip.models.galaxy.GalaxyWorkflowResult;
+import eu.hbp.mip.models.galaxy.PostWorkflowToGalaxyDtoResponse;
+import eu.hbp.mip.repositories.ExperimentRepository;
+import eu.hbp.mip.services.Specifications.ExperimentSpecifications;
+import eu.hbp.mip.utils.ClaimUtils;
+import eu.hbp.mip.utils.Exceptions.*;
+import eu.hbp.mip.utils.HTTPUtil;
+import eu.hbp.mip.utils.JsonConverters;
+import eu.hbp.mip.utils.Logger;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Service;
+import retrofit2.Call;
+import retrofit2.Response;
+
+import java.io.IOException;
+import java.util.*;
+
+import static java.lang.Thread.sleep;
+
+@Service
+public class ExperimentService {
+
+
+    @Value("#{'${services.exareme.queryExaremeUrl}'}")
+    private String queryExaremeUrl;
+
+    @Value("#{'${services.galaxy.galaxyUrl}'}")
+    private String galaxyUrl;
+
+    @Value("#{'${services.galaxy.galaxyApiKey}'}")
+    private String galaxyApiKey;
+
+    @Value("#{'${authentication.enabled}'}")
+    private boolean authenticationIsEnabled;
+
+    private static final Gson gson = new Gson();
+
+    private final ActiveUserService activeUserService;
+    private final ExperimentRepository experimentRepository;
+
+    public ExperimentService(ActiveUserService activeUserService, ExperimentRepository experimentRepository) {
+        this.activeUserService = activeUserService;
+        this.experimentRepository = experimentRepository;
+    }
+
+    /**
+     * The getExperiments will retrieve the experiments from database according to the filters.
+     *
+     * @param name       is optional, in case it is required to filter the experiments by name
+     * @param algorithm  is optional, in case it is required to filter the experiments by algorithm name
+     * @param shared     is optional, in case it is required to filter the experiments by shared
+     * @param viewed     is optional, in case it is required to filter the experiments by viewed
+     * @param includeShared     is optional, in case it is required to retrieve the experiment that is shared
+     * @param page       is the page that is required to be retrieve
+     * @param size       is the size of each page
+     * @param orderBy    is the column that is required to ordered by
+     * @param descending is a boolean to determine if the experiments will be order by descending or ascending
+     * @param logger    contains username and the endpoint.
+     * @return a list of mapped experiments
+     */
+
+    public Map getExperiments(Authentication authentication, String name, String algorithm, Boolean shared, Boolean viewed, boolean includeShared, int page, int size, String orderBy, Boolean descending, Logger logger) {
+
+        UserDAO user = activeUserService.getActiveUser();
+        logger.LogUserAction("Listing my experiments.");
+        if (size > 50)
+            throw new BadRequestException("Invalid size input, max size is 50.");
+        Specification<ExperimentDAO> spec;
+        if(!authenticationIsEnabled  || ClaimUtils.validateAccessRightsOnExperiments(authentication, logger))
+        {
+            spec = Specification
+                    .where(new ExperimentSpecifications.ExperimentWithName(name))
+                    .and(new ExperimentSpecifications.ExperimentWithAlgorithm(algorithm))
+                    .and(new ExperimentSpecifications.ExperimentWithShared(shared))
+                    .and(new ExperimentSpecifications.ExperimentWithViewed(viewed))
+                    .and(new ExperimentSpecifications.ExperimentOrderBy(orderBy, descending));
+        }
+        else {
+            spec = Specification
+                    .where(new ExperimentSpecifications.MyExperiment(user.getUsername()))
+                    .or(new ExperimentSpecifications.SharedExperiment(includeShared))
+                    .and(new ExperimentSpecifications.ExperimentWithAlgorithm(algorithm))
+                    .and(new ExperimentSpecifications.ExperimentWithShared(shared))
+                    .and(new ExperimentSpecifications.ExperimentWithViewed(viewed))
+                    .and(new ExperimentSpecifications.ExperimentWithName(name))
+                    .and(new ExperimentSpecifications.ExperimentOrderBy(orderBy, descending));
+        }
+        Pageable paging = PageRequest.of(page, size);
+        Page<ExperimentDAO> pageExperiments = experimentRepository.findAll(spec, paging);
+        List<ExperimentDAO> experimentDAOs = pageExperiments.getContent();
+
+        if (experimentDAOs.isEmpty())
+            throw new NoContent("No experiment found with the filters provided.");
+
+        List<ExperimentDTO> experimentDTOs = new ArrayList<>();
+        experimentDAOs.forEach(experimentDAO -> experimentDTOs.add(experimentDAO.convertToDTO(false)));
+
+        Map<String, Object> response = new HashMap<>();
+        response.put("experiments", experimentDTOs);
+        response.put("currentPage", pageExperiments.getNumber());
+        response.put("totalExperiments", pageExperiments.getTotalElements());
+        response.put("totalPages", pageExperiments.getTotalPages());
+
+        return response;
+    }
+
+    /**
+     * The getExperiment will retrieve the experiment from database according to the input uuid
+     *
+     * @param uuid     is the id of the experiment to be retrieved
+     * @param logger    contains username and the endpoint.
+     * @return the experiment information that was retrieved from the database
+     */
+    public ExperimentDTO getExperiment(Authentication authentication, String uuid, Logger logger) {
+
+        ExperimentDAO experimentDAO;
+        UserDAO user = activeUserService.getActiveUser();
+
+        logger.LogUserAction("Loading Experiment with uuid : " + uuid);
+
+        experimentDAO = loadExperiment(uuid, logger);
+        if (
+                !experimentDAO.isShared()
+                && !experimentDAO.getCreatedBy().getUsername().equals(user.getUsername())
+                && authenticationIsEnabled
+                && ClaimUtils.validateAccessRightsOnExperiments(authentication, logger)
+        ) {
+            logger.LogUserAction("Accessing Experiment is unauthorized.");
+            throw new UnauthorizedException("You don't have access to the experiment.");
+        }
+        ExperimentDTO experimentDTO = experimentDAO.convertToDTO(true);
+        logger.LogUserAction("Experiment was Loaded with uuid : " + uuid + ".");
+
+        return experimentDTO;
+    }
+
+    /**
+     * The createExperiment will create and save an experiment in the database.
+     *
+     * @param authentication is the role of the user
+     * @param experimentDTO  is the experiment information
+     * @param logger    contains username and the endpoint.
+     * @return the experiment information which was created
+     */
+    public ExperimentDTO createExperiment(Authentication authentication, ExperimentDTO experimentDTO, Logger logger) {
+
+        //Checking if check (POST) /experiments has proper input.
+        checkPostExperimentProperInput(experimentDTO, logger);
+
+        // Get the type and name of algorithm
+        String algorithmType = experimentDTO.getAlgorithm().getType();
+
+        if(algorithmType == null){
+            logger.LogUserAction("Please provide algorithm type.");
+            throw new BadRequestException("Please provide algorithm type.");
+        }
+
+        algorithmParametersLogging(experimentDTO, logger);
+
+        if (authenticationIsEnabled) {
+            String experimentDatasets = getDatasetFromExperimentParameters(experimentDTO, logger);
+            ClaimUtils.validateAccessRightsOnDatasets(authentication, experimentDatasets, logger);
+        }
+
+        // Run with the appropriate engine
+        if (algorithmType.equals("workflow")) {
+            logger.LogUserAction("Algorithm runs on Galaxy.");
+            return runGalaxyWorkflow(experimentDTO, logger);
+        } else {
+            logger.LogUserAction("Algorithm runs on Exareme.");
+            return createExaremeExperiment(experimentDTO, logger);
+        }
+    }
+
+    /**
+     * The createTransientExperiment will run synchronous a transient experiment into exareme and provide results
+     *
+     * @param authentication is the role of the user
+     * @param experimentDTO  is the experiment information
+     * @param logger    contains username and the endpoint.
+     * @return the experiment information which was created
+     */
+    public ExperimentDTO createTransientExperiment(Authentication authentication, ExperimentDTO experimentDTO, Logger logger) {
+
+        //Checking if check (POST) /experiments has proper input.
+        checkPostExperimentProperInput(experimentDTO, logger);
+
+        // Get the type and name of algorithm
+        String algorithmType = experimentDTO.getAlgorithm().getType();
+
+        if(algorithmType.equals("workflow")){
+            logger.LogUserAction("You can not run workflow algorithms transiently.");
+            throw new BadRequestException("You can not run workflow algorithms transiently.");
+        }
+
+        // Get the parameters
+        List<AlgorithmDTO.AlgorithmParamDTO> algorithmParameters
+                = experimentDTO.getAlgorithm().getParameters();
+
+        // Get the type and name of algorithm
+        String algorithmName = experimentDTO.getAlgorithm().getName();
+
+        algorithmParametersLogging(experimentDTO, logger);
+
+        if (authenticationIsEnabled) {
+            String experimentDatasets = getDatasetFromExperimentParameters(experimentDTO, logger);
+            ClaimUtils.validateAccessRightsOnDatasets(authentication, experimentDatasets, logger);
+        }
+
+        String body = gson.toJson(algorithmParameters);
+        String url = queryExaremeUrl + "/" + algorithmName;
+        logger.LogUserAction("url: " + url + ", body: " + body);
+
+        logger.LogUserAction("Completed, returning: " + experimentDTO.toString());
+
+        // Results are stored in the experiment object
+        ExaremeResult exaremeResult = runExaremeExperiment(url, body, experimentDTO);
+
+        logger.LogUserAction("Experiment with uuid: " + experimentDTO.getUuid() + "gave response code: " + exaremeResult.getCode() + " and result: " + exaremeResult.getResults());
+
+        experimentDTO.setResult((exaremeResult.getCode() >= 400) ? null : exaremeResult.getResults());
+        experimentDTO.setStatus((exaremeResult.getCode() >= 400) ? ExperimentDAO.Status.error : ExperimentDAO.Status.success);
+
+        return experimentDTO;
+    }
+
+    /**
+     * The updateExperiment will update the experiment's properties
+     *
+     * @param uuid          is the id of the experiment to be updated
+     * @param experimentDTO is the experiment information to be updated
+     * @param logger    contains username and the endpoint.
+     */
+    public ExperimentDTO updateExperiment(String uuid, ExperimentDTO experimentDTO, Logger logger) {
+        ExperimentDAO experimentDAO;
+        UserDAO user = activeUserService.getActiveUser();
+        logger.LogUserAction("Updating experiment with uuid : " + uuid + ".");
+
+        experimentDAO = loadExperiment(uuid, logger);
+
+        //Verify (PATCH) /experiments non editable fields.
+        verifyPatchExperimentNonEditableFields(experimentDTO, logger);
+
+        if (!experimentDAO.getCreatedBy().getUsername().equals(user.getUsername()))
+            throw new UnauthorizedException("You don't have access to the experiment.");
+
+        if (experimentDTO.getName() != null && experimentDTO.getName().length() != 0)
+            experimentDAO.setName(experimentDTO.getName());
+
+        if (experimentDTO.getShared() != null)
+            experimentDAO.setShared(experimentDTO.getShared());
+
+        if (experimentDTO.getViewed() != null)
+            experimentDAO.setViewed(experimentDTO.getViewed());
+
+        experimentDAO.setUpdated(new Date());
+
+        try {
+            experimentRepository.save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+
+        logger.LogUserAction("Updated experiment with uuid : " + uuid + ".");
+
+        experimentDTO = experimentDAO.convertToDTO(true);
+        return experimentDTO;
+    }
+
+    /**
+     * The deleteExperiment will delete an experiment from the database
+     *
+     * @param uuid     is the id of the experiment to be deleted
+     * @param logger    contains username and the endpoint.
+     */
+    public void deleteExperiment(String uuid, Logger logger) {
+        ExperimentDAO experimentDAO;
+        UserDAO user = activeUserService.getActiveUser();
+        logger.LogUserAction("Deleting experiment with uuid : " + uuid + ".");
+
+        experimentDAO = loadExperiment(uuid, logger);
+
+        if (!experimentDAO.getCreatedBy().getUsername().equals(user.getUsername()))
+            throw new UnauthorizedException("You don't have access to the experiment.");
+
+        try {
+            experimentRepository.delete(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction("Attempted to delete an experiment to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+
+        logger.LogUserAction("Deleted experiment with uuid : " + uuid + ".");
+    }
+
+    //    /* -------------------------------  PRIVATE METHODS  ----------------------------------------------------*/
+
+    private void checkPostExperimentProperInput(ExperimentDTO experimentDTO, Logger logger) {
+
+        boolean properInput =
+                experimentDTO.getShared() == null
+                        && experimentDTO.getViewed() == null
+                        && experimentDTO.getCreated() == null
+                        && experimentDTO.getCreatedBy() == null
+                        && experimentDTO.getResult() == null
+                        && experimentDTO.getStatus() == null
+                        && experimentDTO.getUuid() == null;
+
+        if (!properInput) {
+            logger.LogUserAction( "Invalid input.");
+            throw new BadRequestException("Please provide proper input.");
+        }
+    }
+
+    private void verifyPatchExperimentNonEditableFields(ExperimentDTO experimentDTO, Logger logger) {
+        if (experimentDTO.getUuid() != null ) {
+            logger.LogUserAction( "Uuid is not editable.");
+            throw new BadRequestException("Uuid is not editable.");
+        }
+
+        if (experimentDTO.getAlgorithm() != null ) {
+            logger.LogUserAction( "Algorithm is not editable.");
+            throw new BadRequestException("Algorithm is not editable.");
+        }
+
+        if (experimentDTO.getCreated() != null) {
+            logger.LogUserAction( "Created is not editable.");
+            throw new BadRequestException("Created is not editable.");
+        }
+
+        if (experimentDTO.getCreatedBy() != null) {
+            logger.LogUserAction( "CreatedBy is not editable.");
+            throw new BadRequestException("CreatedBy is not editable.");
+        }
+
+        if (experimentDTO.getUpdated() != null) {
+            logger.LogUserAction( "Updated is not editable.");
+            throw new BadRequestException("Updated is not editable.");
+        }
+
+        if (experimentDTO.getFinished() != null) {
+            logger.LogUserAction( "Finished is not editable.");
+            throw new BadRequestException("Finished is not editable.");
+        }
+
+        if (experimentDTO.getResult() != null) {
+            logger.LogUserAction( "Result is not editable.");
+            throw new BadRequestException("Result is not editable.");
+        }
+
+        if (experimentDTO.getStatus() != null) {
+            logger.LogUserAction( "Status is not editable.");
+            throw new BadRequestException("Status is not editable.");
+        }
+    }
+
+    private void algorithmParametersLogging(ExperimentDTO experimentDTO, Logger logger) {
+        String algorithmName = experimentDTO.getAlgorithm().getName();
+        StringBuilder parametersLogMessage = new StringBuilder(", Parameters:\n");
+        experimentDTO.getAlgorithm().getParameters().forEach(
+                params -> parametersLogMessage
+                        .append("  ")
+                        .append(params.getLabel())
+                        .append(" -> ")
+                        .append(params.getValue())
+                        .append("\n"));
+        logger.LogUserAction("Executing " + algorithmName + parametersLogMessage);
+    }
+    
+    /**
+     * The getDatasetFromExperimentParameters will retrieve the dataset from the experiment parameters
+     *
+     * @param experimentDTO is the experiment information
+     * @param logger    contains username and the endpoint.
+     * @return the dataset from the experiment
+     */
+    private String getDatasetFromExperimentParameters(ExperimentDTO experimentDTO, Logger logger) {
+
+        String experimentDatasets = null;
+        for (AlgorithmDTO.AlgorithmParamDTO parameter : experimentDTO.getAlgorithm().getParameters()) {
+            if (parameter.getLabel().equals("dataset")) {
+                experimentDatasets = parameter.getValue();
+                break;
+            }
+        }
+
+        if (experimentDatasets == null || experimentDatasets.equals("")) {
+            logger.LogUserAction("A dataset should be specified to run an algorithm.");
+            throw new BadRequestException("Please provide at least one dataset to run the algorithm.");
+        }
+        return experimentDatasets;
+    }
+
+    /**
+     * The loadExperiment access the database and load the information of a specific experiment
+     *
+     * @param uuid is the id of the experiment to be retrieved
+     * @return the experiment information that was retrieved from database
+     */
+    private ExperimentDAO loadExperiment(String uuid, Logger logger) {
+        UUID experimentUuid;
+        ExperimentDAO experimentDAO;
+
+        try {
+            experimentUuid = UUID.fromString(uuid);
+        } catch (Exception e) {
+            logger.LogUserAction( e.getMessage());
+            throw new BadRequestException(e.getMessage());
+        }
+
+        experimentDAO = experimentRepository.findByUuid(experimentUuid);
+        if (experimentDAO == null) {
+            logger.LogUserAction( "Experiment with uuid : " + uuid + "was not found.");
+            throw new ExperimentNotFoundException("Experiment with uuid : " + uuid + " was not found.");
+        }
+
+        return experimentDAO;
+    }
+
+    /**
+     * The createExperimentInTheDatabase will insert a new experiment in the database according to the given experiment information
+     *
+     * @param experimentDTO is the experiment information to inserted in the database
+     * @return the experiment information that was inserted into the database
+     * @Note In the database there will be stored Algorithm Details that is the whole information about the algorithm
+     * and an Algorithm column that is required for the filtering with algorithm name  in the GET /experiments.
+     */
+    private ExperimentDAO createExperimentInTheDatabase(ExperimentDTO experimentDTO, Logger logger) {
+        UserDAO user = activeUserService.getActiveUser();
+
+        ExperimentDAO experimentDAO = new ExperimentDAO();
+        experimentDAO.setUuid(UUID.randomUUID());
+        experimentDAO.setCreatedBy(user);
+        experimentDAO.setAlgorithm(JsonConverters.convertObjectToJsonString(experimentDTO.getAlgorithm()));
+        experimentDAO.setAlgorithmId(experimentDTO.getAlgorithm().getName());
+        experimentDAO.setName(experimentDTO.getName());
+        experimentDAO.setStatus(ExperimentDAO.Status.pending);
+
+        try {
+            experimentRepository.save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+
+        logger.LogUserAction(" id : " + experimentDAO.getUuid());
+        logger.LogUserAction(" algorithm : " + experimentDAO.getAlgorithm());
+        logger.LogUserAction(" name : " + experimentDAO.getName());
+        return experimentDAO;
+    }
+
+    private void saveExperiment(ExperimentDAO experimentDAO, Logger logger) {
+
+        logger.LogUserAction(" id : " + experimentDAO.getUuid());
+        logger.LogUserAction(" algorithm : " + experimentDAO.getAlgorithm());
+        logger.LogUserAction(" name : " + experimentDAO.getName());
+        logger.LogUserAction(" historyId : " + experimentDAO.getWorkflowHistoryId());
+        logger.LogUserAction(" status : " + experimentDAO.getStatus());
+
+        try {
+            experimentRepository.save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+
+        logger.LogUserAction("Saved experiment");
+    }
+
+    private void finishExperiment(ExperimentDAO experimentDAO, Logger logger) {
+        experimentDAO.setFinished(new Date());
+
+        try {
+            experimentRepository.save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction( "Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+    }
+
+    private String formattingGalaxyResult(String result) {
+        List<LinkedTreeMap<String,Object>> jsonObject = JsonConverters.convertJsonStringToObject(result, new ArrayList<ArrayList<Object>>().getClass());
+        LinkedTreeMap<String,Object> firstResult = jsonObject.get(0);
+        jsonObject = (List<LinkedTreeMap<String, Object>>) firstResult.get("result");
+        List<LinkedTreeMap<String,Object>> finalJsonObject = new ArrayList<>();
+        finalJsonObject.add(jsonObject.get(0));
+        return JsonConverters.convertObjectToJsonString(finalJsonObject);
+    }
+
+    /**
+     * The runExaremeExperiment will run to exareme the experiment
+     *
+     * @param url           is the url that contain the results of the experiment
+     * @param body          is the parameters of the algorithm
+     * @param experimentDTO is the experiment information to be executed in the exareme
+     * @return the result of exareme as well as the http status that was retrieved
+     */
+    public ExaremeResult runExaremeExperiment(String url, String body, ExperimentDTO experimentDTO) {
+
+        StringBuilder results = new StringBuilder();
+        int code;
+        try {
+            code = HTTPUtil.sendPost(url, body, results);
+        } catch (Exception e) {
+            throw new InternalServerError("Error occurred : " + e.getMessage());
+        }
+
+        // Results are stored in the experiment object
+        ExperimentDTO experimentDTOWithOnlyResult = JsonConverters.convertJsonStringToObject(String.valueOf(results), ExperimentDTO.class);
+        List<Object> resultDTOS = experimentDTOWithOnlyResult.getResult();
+
+        return new ExaremeResult(code, resultDTOS);
+    }
+
+    /* --------------------------------------  EXAREME CALLS ---------------------------------------------------------*/
+
+    /**
+     * The createExaremeExperiment will POST the algorithm to the exareme client
+     *
+     * @param experimentDTO is the request with the experiment information
+     * @param logger    contains username and the endpoint.
+     * @return the experiment information that was retrieved from exareme
+     */
+    public ExperimentDTO createExaremeExperiment(ExperimentDTO experimentDTO, Logger logger) {
+
+        logger.LogUserAction("Running the algorithm...");
+
+        ExperimentDAO experimentDAO = createExperimentInTheDatabase(experimentDTO, logger);
+        logger.LogUserAction("Created experiment with uuid :" + experimentDAO.getUuid());
+
+        // Run the 1st algorithm from the list
+        String algorithmName = experimentDTO.getAlgorithm().getName();
+
+        // Get the parameters
+        List<AlgorithmDTO.AlgorithmParamDTO> algorithmParameters
+                = experimentDTO.getAlgorithm().getParameters();
+
+        String body = gson.toJson(algorithmParameters);
+        String url = queryExaremeUrl + "/" + algorithmName;
+        logger.LogUserAction("url: " + url + ", body: " + body);
+
+        logger.LogUserAction("Completed, returning: " + experimentDTO.toString());
+
+        logger.LogUserAction("Starting exareme execution thread");
+        ExperimentDTO finalExperimentDTO = experimentDTO;
+        new Thread(() -> {
+
+            // ATTENTION: Inside the Thread only LogExperimentAction should be used, not LogUserAction!
+            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Thread named :" + Thread.currentThread().getName() + " with id :" + Thread.currentThread().getId() + " started!");
+
+            try {
+                // Results are stored in the experiment object
+                ExaremeResult exaremeResult = runExaremeExperiment(url, body, finalExperimentDTO);
+
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Experiment with uuid: " + experimentDAO.getUuid() + "gave response code: " + exaremeResult.getCode() + " and result: " + exaremeResult.getResults());
+
+                experimentDAO.setResult((exaremeResult.getCode() >= 400) ? null : JsonConverters.convertObjectToJsonString(exaremeResult.getResults()));
+                experimentDAO.setStatus((exaremeResult.getCode() >= 400) ? ExperimentDAO.Status.error : ExperimentDAO.Status.success);
+            } catch (Exception e) {
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "There was an exception: " + e.getMessage());
+
+                experimentDAO.setStatus(ExperimentDAO.Status.error);
+            }
+
+            finishExperiment(experimentDAO, logger);
+            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Finished the experiment: " + experimentDAO.toString());
+        }).start();
+        experimentDTO = experimentDAO.convertToDTO(true);
+        return experimentDTO;
+    }
+
+    /* ---------------------------------------  GALAXY CALLS ---------------------------------------------------------*/
+
+
+    /**
+     * The runWorkflow will POST the algorithm to the galaxy client
+     *
+     * @param experimentDTO is the request with the experiment information
+     * @return the response to be returned
+     */
+    public ExperimentDTO runGalaxyWorkflow(ExperimentDTO experimentDTO, Logger logger) {
+        logger.LogUserAction("Running a workflow...");
+
+        ExperimentDAO experimentDAO = createExperimentInTheDatabase(experimentDTO, logger);
+        logger.LogUserAction("Created experiment with uuid :" + experimentDAO.getUuid());
+
+
+        // Run the 1st algorithm from the list
+        String workflowId = experimentDTO.getAlgorithm().getName();
+
+        // Get the parameters
+        List<AlgorithmDTO.AlgorithmParamDTO> algorithmParameters
+                = experimentDTO.getAlgorithm().getParameters();
+
+        // Convert the parameters to workflow parameters
+        HashMap<String, String> algorithmParamsIncludingEmpty = new HashMap<>();
+        if (algorithmParameters != null) {
+            for (AlgorithmDTO.AlgorithmParamDTO param : algorithmParameters) {
+                algorithmParamsIncludingEmpty.put(param.getName(), param.getValue());
+            }
+        }
+
+        // Get all the algorithm parameters because the frontend provides only the non-null
+        final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey);
+        final WorkflowsClient workflowsClient = instance.getWorkflowsClient();
+        Workflow workflow = null;
+        for (Workflow curWorkflow : workflowsClient.getWorkflows()) {
+            if (curWorkflow.getId().equals(workflowId)) {
+                workflow = curWorkflow;
+                break;
+            }
+        }
+        if (workflow == null) {
+            logger.LogUserAction("Could not find algorithm code: " + workflowId);
+            throw new BadRequestException("Could not find galaxy algorithm.");
+        }
+        final WorkflowDetails workflowDetails = workflowsClient.showWorkflow(workflow.getId());
+        for (Map.Entry<String, WorkflowInputDefinition> workflowParameter : workflowDetails.getInputs().entrySet()) {
+            if (!(algorithmParamsIncludingEmpty.containsKey(workflowParameter.getValue().getUuid()))) {
+                algorithmParamsIncludingEmpty.put(workflowParameter.getValue().getUuid(), "");
+            }
+        }
+
+        // Create the body of the request
+        HashMap<String, HashMap<String, String>> requestBody = new HashMap<>();
+        requestBody.put("inputs", algorithmParamsIncludingEmpty);
+        JsonObject requestBodyJson = new JsonParser().parse(gson.toJson(requestBody)).getAsJsonObject();
+
+        // Create the request client
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        logger.LogUserAction("Running Galaxy workflow with id: " + workflow.getId());
+
+        // Call Galaxy to run the workflow
+        Call<PostWorkflowToGalaxyDtoResponse> call = service.postWorkflowToGalaxy(workflow.getId(), galaxyApiKey, requestBodyJson);
+        try {
+            Response<PostWorkflowToGalaxyDtoResponse> response = call.execute();
+
+            if (response.code() == 200) {       // Call succeeded
+                String responseBody = gson.toJson(response.body());
+                logger.LogUserAction("Response: " + responseBody);
+
+                String historyId = (String) new JSONObject(responseBody).get("history_id");
+                experimentDAO.setWorkflowHistoryId(historyId);
+                experimentDAO.setStatus(ExperimentDAO.Status.success);
+
+            } else {     // Something unexpected happened
+                String msgErr = gson.toJson(response.errorBody());
+                logger.LogUserAction("Error Response: " + msgErr);
+                experimentDTO.setStatus((response.code() >= 400) ? ExperimentDAO.Status.error : ExperimentDAO.Status.success);
+            }
+
+        } catch (Exception e) {
+            logger.LogUserAction("An exception occurred: " + e.getMessage());
+            experimentDAO.setStatus(ExperimentDAO.Status.error);
+        }
+        saveExperiment(experimentDAO, logger);
+
+        // Start the process of fetching the status
+        updateWorkflowExperiment(experimentDAO, logger);
+
+        logger.LogUserAction("Run workflow completed!");
+
+        experimentDTO = experimentDAO.convertToDTO(true);
+        return experimentDTO;
+    }
+
+
+    /**
+     * This method creates a thread that will fetch the workflow result when it is ready
+     *
+     * @param experimentDAO will be used to fetch it's workflow status, it should have the workflowHistoryId initialized
+     *                      and the result should not already be fetched
+     */
+    public void updateWorkflowExperiment(ExperimentDAO experimentDAO, Logger logger) {
+
+        if (experimentDAO == null) {
+            logger.LogUserAction("The experiment does not exist.");
+            return;
+        }
+
+        logger.LogUserAction(" Experiment id : " + experimentDAO.getUuid());
+        if (experimentDAO.getWorkflowHistoryId() == null) {
+            logger.LogUserAction("History Id does not exist.");
+            return;
+        }
+
+        logger.LogUserAction("Starting Thread...");
+        new Thread(() -> {
+            while (true) {
+                // ATTENTION: Inside the Thread only LogExperimentAction should be used, not LogExperimentAction!
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Thread is running...");
+
+                try {
+                    sleep(2000);
+                } catch (InterruptedException e) {
+                    Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Sleep was disrupted: " + e.getMessage());
+                }
+
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Fetching status for experiment Id: " + experimentDAO.getUuid());
+
+                String state = getWorkflowStatus(experimentDAO);
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "State is: " + state);
+
+                switch (state) {
+                    case "pending":
+                        // Do nothing, when the experiment is created the status is set to running
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Workflow is still running.");
+                        break;
+
+                    case "success":
+                        // Get only the job result that is visible
+                        List<GalaxyWorkflowResult> workflowJobsResults = getWorkflowResults(experimentDAO);
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Results are: " + workflowJobsResults.toString());
+
+                        boolean resultFound = false;
+                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
+                            if (jobResult.getVisible()) {
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Visible result are: " + jobResult.getId());
+
+                                String result = getWorkflowResultBody(experimentDAO, jobResult.getId());
+
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "ResultDTO: " + result);
+                                if (result == null) {
+                                    experimentDAO.setStatus(ExperimentDAO.Status.error);
+                                } else {
+                                    experimentDAO.setResult(result);
+                                    experimentDAO.setStatus(ExperimentDAO.Status.success);
+                                    resultFound = true;
+                                }
+                            }
+                        }
+
+                        if (!resultFound) {      // If there is no visible result
+                            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "No visible result");
+                            experimentDAO.setStatus(ExperimentDAO.Status.error);
+                        }
+
+                        finishExperiment(experimentDAO, logger);
+                        break;
+
+                    case "error":
+                        // Get the job result that failed
+                        workflowJobsResults = getWorkflowResults(experimentDAO);
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Error results are: " + workflowJobsResults.toString());
+
+                        boolean failedJobFound = false;
+                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
+                            if (jobResult.getState().equals("error")) {
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Failed job is: " + jobResult.getId());
+
+                                String result = getWorkflowJobError(jobResult.getId(), experimentDAO);
+
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Job result: " + result);
+                                if (result == null) {
+                                    experimentDAO.setStatus(ExperimentDAO.Status.error);
+                                }
+                                experimentDAO.setStatus(ExperimentDAO.Status.error);
+                                failedJobFound = true;
+                            }
+                        }
+
+                        if (!failedJobFound) {      // If there is no visible failed job
+                            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "No failed result");
+                            experimentDAO.setStatus(ExperimentDAO.Status.error);
+                        }
+                        finishExperiment(experimentDAO, logger);
+                        break;
+
+                    default:        // InternalError or unexpected result
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "An unexpected error occurred.");
+                        experimentDAO.setStatus(ExperimentDAO.Status.error);
+                        finishExperiment(experimentDAO, logger);
+                        break;
+                }
+
+                // If result exists return
+                if (experimentDAO.getResult() != null) {
+                    Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "ResultDTO exists: " + experimentDAO.getResult());
+                    return;
+                }
+            }
+        }).start();
+    }
+
+
+    /**
+     * @param experimentDAO The experiment of the workflow
+     * @return "pending"           ->      When the workflow is still running
+     * "internalError"     ->      When an exception or a bad request occurred
+     * "error"             ->      When the workflow produced an error
+     * "success"         ->      When the workflow completed successfully
+     */
+    public String getWorkflowStatus(ExperimentDAO experimentDAO) {
+        String historyId = experimentDAO.getWorkflowHistoryId();
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+
+        // ATTENTION: This function is used from a Thread. Only LogExperimentAction should be used, not LogUserAction!
+        Logger.LogExperimentAction(experimentName, experimentId, " History Id : " + historyId);
+
+        // Create the request client
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<Object> call = service.getWorkflowStatusFromGalaxy(historyId, galaxyApiKey);
+
+        String result;
+        try {
+            Response<Object> response = call.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return "internalError";
+            }
+            result = new Gson().toJson(response.body());
+            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + result);
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
+            return "internalError";
+        }
+
+        String state;
+        try {
+            JSONObject resultJson = new JSONObject(result);
+            state = resultJson.getString("state");
+        } catch (JSONException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
+            return "internalError";
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
+        switch (state) {
+            case "ok":
+                return "success";
+            case "error":
+                return "error";
+            case "pending":
+            case "new":
+            case "waiting":
+            case "queued":
+                return "pending";
+            default:
+                return "internalError";
+        }
+    }
+
+    /**
+     * @param experimentDAO The experiment of the workflow
+     * @return a List<GalaxyWorkflowResult>   or null when an error occurred
+     */
+    public List<GalaxyWorkflowResult> getWorkflowResults(ExperimentDAO experimentDAO) {
+
+        String historyId = experimentDAO.getWorkflowHistoryId();
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+        Logger.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
+
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<List<GalaxyWorkflowResult>> call = service.getWorkflowResultsFromGalaxy(historyId, galaxyApiKey);
+
+        List<GalaxyWorkflowResult> getGalaxyWorkflowResultList;
+        try {
+            Response<List<GalaxyWorkflowResult>> response = call.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+            getGalaxyWorkflowResultList = response.body();
+            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + response.body());
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
+            return null;
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
+        return getGalaxyWorkflowResultList;
+
+    }
+
+    /**
+     * @param experimentDAO The experiment of the workflow
+     * @param contentId     the id of the job result that we want
+     * @return the result of the specific workflow job, null if there was an error
+     */
+    public String getWorkflowResultBody(ExperimentDAO experimentDAO, String contentId) {
+
+        String historyId = experimentDAO.getWorkflowHistoryId();
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+
+        Logger.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
+
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<Object> call =
+                service.getWorkflowResultsBodyFromGalaxy(historyId, contentId, galaxyApiKey);
+
+        String resultJson;
+        try {
+            Response<Object> response = call.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+            resultJson = new Gson().toJson(response.body());
+            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + resultJson);
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId,
+                    " An exception happened: " + e.getMessage());
+            return null;
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
+        return formattingGalaxyResult(resultJson);
+    }
+
+
+    /**
+     * @param jobId the id of the workflow job that failed
+     * @return the error that was produced or null if an error occurred
+     */
+    public String getWorkflowJobError(String jobId, ExperimentDAO experimentDAO) {
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+
+        Logger.LogExperimentAction(experimentName, experimentId, " jobId : " + jobId);
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<Object> callError = service.getErrorMessageOfWorkflowFromGalaxy(jobId, galaxyApiKey);
+
+        String fullError;
+        String returnError;
+        try {
+            Response<Object> response = callError.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, "Response code: "
+                        + response.code() + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+
+            // Parsing the stderr of the job that failed
+            String jsonString = new Gson().toJson(response.body());
+            JsonElement jsonElement = new JsonParser().parse(jsonString);
+            JsonObject rootObject = jsonElement.getAsJsonObject();
+            fullError = rootObject.get("stderr").getAsString();
+            Logger.LogExperimentAction(experimentName, experimentId, "Error: " + fullError);
+
+            String[] arrOfStr = fullError.split("ValueError", 0);
+            String specError = arrOfStr[arrOfStr.length - 1];
+            returnError = specError.substring(1);
+            Logger.LogExperimentAction(experimentName, experimentId, "Parsed Error: " + returnError);
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, "Exception: " + e.getMessage());
+            return null;
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, "Completed successfully!");
+
+        return returnError;
+    }
+
+    static class ExaremeResult {
+        private final int code;
+        private final List<Object> results;
+
+        public ExaremeResult(int code, List<Object> results) {
+            this.code = code;
+            this.results = results;
+        }
+
+        public int getCode() {
+            return code;
+        }
+
+        public List<Object> getResults() {
+            return results;
+        }
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/services/Specifications/ExperimentSpecifications.java b/src/main/java/eu/hbp/mip/services/Specifications/ExperimentSpecifications.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1e6a13acae08d9ac2c516884773b5bf9b4c71b2
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/services/Specifications/ExperimentSpecifications.java
@@ -0,0 +1,158 @@
+package eu.hbp.mip.services.Specifications;
+
+import eu.hbp.mip.models.DAOs.ExperimentDAO;
+import eu.hbp.mip.models.DAOs.UserDAO;
+import eu.hbp.mip.utils.Exceptions.BadRequestException;
+import org.springframework.data.jpa.domain.Specification;
+
+import javax.persistence.criteria.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExperimentSpecifications {
+    public static class ExperimentWithName implements Specification<ExperimentDAO> {
+
+        private String name;
+        private String regExp;
+
+        public ExperimentWithName(String name) {
+            this.name = name;
+            this.regExp = name;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
+            if (name == null) {
+                return cb.isTrue(cb.literal(true));
+            } else {
+                regExp = (name.contains("%") ? name : name + "%");
+            }
+
+            return cb.like(cb.lower(root.get("name")), this.regExp.toLowerCase());
+        }
+    }
+
+    public static class ExperimentWithAlgorithm implements Specification<ExperimentDAO> {
+
+        private String algorithm;
+
+        public ExperimentWithAlgorithm(String algorithm) {
+            this.algorithm = algorithm;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
+            if (algorithm == null) {
+                return cb.isTrue(cb.literal(true));
+            }
+
+            return cb.equal(cb.lower(root.get("algorithm")), this.algorithm.toLowerCase());
+        }
+    }
+
+    public static class ExperimentWithViewed implements Specification<ExperimentDAO> {
+
+        private Boolean viewed;
+
+        public ExperimentWithViewed(Boolean viewed) {
+            this.viewed = viewed;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
+            if (viewed == null) {
+                return cb.isTrue(cb.literal(true)); // always true = no filtering
+            }
+            return cb.equal(root.get("viewed"), this.viewed);
+        }
+    }
+
+    public static class ExperimentWithShared implements Specification<ExperimentDAO> {
+
+        private Boolean shared;
+
+        public ExperimentWithShared(Boolean shared) {
+            this.shared = shared;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
+            if (shared == null) {
+                return cb.isTrue(cb.literal(true));
+            }
+            return cb.equal(root.get("shared"), this.shared);
+        }
+    }
+
+    public static class MyExperiment implements Specification<ExperimentDAO> {
+
+        private String username;
+
+        public MyExperiment(String username) {
+            this.username = username;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
+            if (username == null) {
+                return cb.isTrue(cb.literal(true));
+            }
+            Join<ExperimentDAO, UserDAO> experimentDAOUserDAOJoin = root.join("createdBy");
+            return cb.equal(experimentDAOUserDAOJoin.get("username"), username);
+        }
+    }
+
+    public static class SharedExperiment implements Specification<ExperimentDAO> {
+
+        private boolean shared;
+
+        public SharedExperiment(boolean shared) {
+            this.shared = shared;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
+            if (shared == false) {
+                return cb.isTrue(cb.literal(false));
+            }
+            return cb.equal(root.get("shared"), shared);
+        }
+    }
+
+    public static class ExperimentOrderBy implements Specification<ExperimentDAO> {
+
+        private String orderBy;
+        private Boolean descending;
+
+        public ExperimentOrderBy(String orderBy, Boolean descending) {
+            if (properColumnToBeOrderedBy(orderBy))
+                this.orderBy = orderBy;
+            else
+                throw new BadRequestException("Please provide proper column to order by.");
+            if (descending == null)
+                this.descending = true;
+            else
+                this.descending = descending;
+        }
+
+        public Predicate toPredicate(Root<ExperimentDAO> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
+            if (descending) {
+                criteriaQuery.orderBy(cb.desc(root.get(orderBy)));
+            } else {
+                criteriaQuery.orderBy(cb.asc(root.get(orderBy)));
+            }
+            return cb.isTrue(cb.literal(true));
+        }
+
+    }
+
+    public static boolean properColumnToBeOrderedBy(String column) {
+        {
+            List<String> properColumns = new ArrayList<>();
+            properColumns.add("uuid");
+            properColumns.add("name");
+            properColumns.add("created_by_username");
+            properColumns.add("algorithm");
+            properColumns.add("created");
+            properColumns.add("status");
+            properColumns.add("shared");
+            properColumns.add("viewed");
+            return properColumns.contains(column);
+        }
+    }
+}
+
diff --git a/src/main/java/eu/hbp/mip/utils/CORSFilter.java b/src/main/java/eu/hbp/mip/utils/CORSFilter.java
index 7ed1ecf38d84fedddb5acb4750db327fbb9e5079..7d77b9022ef0855f0f5d6decf84601d0a00f75b0 100644
--- a/src/main/java/eu/hbp/mip/utils/CORSFilter.java
+++ b/src/main/java/eu/hbp/mip/utils/CORSFilter.java
@@ -1,32 +1,25 @@
 package eu.hbp.mip.utils;
 
+
 import javax.servlet.*;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
+
 /**
- * Created by mirco on 12.02.16.
+ * CORS Filter used only for development.
+ *
+ * Allows requests from all possible origins.
  */
 public class CORSFilter implements Filter {
-
     @Override
     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
         HttpServletResponse response = (HttpServletResponse) res;
         response.setHeader("Access-Control-Allow-Origin", "*");
-        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
+        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE");
         response.setHeader("Access-Control-Max-Age", "3600");
         response.setHeader("Access-Control-Allow-Headers", "*");
         response.setHeader("Access-Control-Request-Headers", "*");
         chain.doFilter(req, res);
     }
-
-    @Override
-    public void init(FilterConfig filterConfig) {
-        /* Nothing to do */
-    }
-
-    @Override
-    public void destroy() {
-        /* Nothing to do */
-    }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/ClaimUtils.java b/src/main/java/eu/hbp/mip/utils/ClaimUtils.java
index e71d3f19083d03ae0067176b2fccfe4f06175915..f5676b52c130f0b4be1c79d939567f74b752c0db 100644
--- a/src/main/java/eu/hbp/mip/utils/ClaimUtils.java
+++ b/src/main/java/eu/hbp/mip/utils/ClaimUtils.java
@@ -1,13 +1,14 @@
 package eu.hbp.mip.utils;
 
 import com.google.gson.Gson;
-import eu.hbp.mip.model.PathologyDTO;
-import org.springframework.security.core.GrantedAuthority;
+import eu.hbp.mip.models.DTOs.PathologyDTO;
+import eu.hbp.mip.utils.Exceptions.InternalServerError;
+import eu.hbp.mip.utils.Exceptions.UnauthorizedException;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
+import org.springframework.security.core.Authentication;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
 
 
 public class ClaimUtils {
@@ -15,68 +16,68 @@ public class ClaimUtils {
     private static final Gson gson = new Gson();
 
     public static String allDatasetsAllowedClaim() {
-        return "dataset_all";
+        return "research_dataset_all";
+    }
+
+    public static String allExperimentsAllowedClaim() {
+        return "research_experiment_all";
     }
 
     public static String getDatasetClaim(String datasetCode) {
-        return "dataset_" + datasetCode.toLowerCase();
+        return "research_dataset_" + datasetCode.toLowerCase();
     }
 
-    public static boolean userHasDatasetsAuthorization(String username, Collection<? extends GrantedAuthority> authorities,
-                                                       String experimentDatasets) {
+    public static void validateAccessRightsOnDatasets(Authentication authentication,
+                                                      String experimentDatasets, Logger logger) {
 
-        List<String> userClaims = Arrays.asList(authorities.toString().toLowerCase()
-                .replaceAll("[\\s+\\]\\[]", "").split(","));
-        Logging.LogUserAction(username, "(POST) /experiments/runAlgorithm", userClaims.toString());
+        ArrayList<String> authorities = getKeycloakAuthorities(authentication, logger);
 
         // Don't check for dataset claims if "super" claim exists allowing everything
-        if (!userClaims.contains(ClaimUtils.allDatasetsAllowedClaim())) {
+        if (!hasRoleAccess(authorities, ClaimUtils.allDatasetsAllowedClaim(), logger)) {
 
             for (String dataset : experimentDatasets.split(",")) {
                 String datasetRole = ClaimUtils.getDatasetClaim(dataset);
-                if (!userClaims.contains(datasetRole.toLowerCase())) {
-                    Logging.LogUserAction(username, "(POST) /experiments/runAlgorithm",
-                            "You are not allowed to use dataset: " + dataset);
-                    return false;
+                if (!hasRoleAccess(authorities, datasetRole, logger)) {
+                    logger.LogUserAction("You are not allowed to use dataset: " + dataset);
+                    throw new UnauthorizedException("You are not authorized to use these datasets.");
                 }
             }
-            Logging.LogUserAction(username, "(POST) /experiments/runAlgorithm",
-                    "User is authorized to use the datasets: " + experimentDatasets);
+            logger.LogUserAction("User is authorized to use the datasets: " + experimentDatasets);
         }
-        return true;
     }
 
-    public static String getAuthorizedPathologies(String username, Collection<? extends GrantedAuthority> authorities,
+    public static boolean validateAccessRightsOnExperiments(Authentication authentication, Logger logger) {
+
+        ArrayList<String> authorities = getKeycloakAuthorities(authentication, logger);
+
+        // Check for experiment_all claims
+        return  hasRoleAccess(authorities, ClaimUtils.allExperimentsAllowedClaim(), logger);
+    }
+
+    public static String getAuthorizedPathologies(Logger logger, Authentication authentication,
                                                   List<PathologyDTO> allPathologies) {
         // --- Providing only the allowed pathologies/datasets to the user  ---
-        Logging.LogUserAction(username,
-                "(GET) /pathologies", "Filter out the unauthorised datasets.");
+        logger.LogUserAction("Filter out the unauthorised datasets.");
 
-        List<String> userClaims = Arrays.asList(authorities.toString().toLowerCase()
-                .replaceAll("[\\s+\\]\\[]", "").split(","));
-
-        Logging.LogUserAction(username,
-                "(GET) /pathologies", "User Claims: " + userClaims);
+        ArrayList<String> authorities = getKeycloakAuthorities(authentication, logger);
 
         // If the "dataset_all" claim exists then return everything
-        if (userClaims.contains(ClaimUtils.allDatasetsAllowedClaim())) {
+        if (hasRoleAccess(authorities, ClaimUtils.allDatasetsAllowedClaim(), logger)) {
             return gson.toJson(allPathologies);
         }
 
         List<PathologyDTO> userPathologies = new ArrayList<>();
         for (PathologyDTO curPathology : allPathologies) {
-            List<PathologyDTO.PathologyDatasetDTO> userPathologyDatasets = new ArrayList<PathologyDTO.PathologyDatasetDTO>();
+            List<PathologyDTO.PathologyDatasetDTO> userPathologyDatasets = new ArrayList<>();
             for (PathologyDTO.PathologyDatasetDTO dataset : curPathology.getDatasets()) {
-                if (userClaims.contains(ClaimUtils.getDatasetClaim(dataset.getCode()))) {
-                    Logging.LogUserAction(username, "(GET) /pathologies",
-                            "Added dataset: " + dataset.getCode());
+                if (hasRoleAccess(authorities, ClaimUtils.getDatasetClaim(dataset.getCode()), logger)) {
+                    logger.LogUserAction("Added dataset: " + dataset.getCode());
                     userPathologyDatasets.add(dataset);
                 }
             }
 
             if (userPathologyDatasets.size() > 0) {
-                Logging.LogUserAction(username, "(GET) /pathologies",
-                        "Added pathology '" + curPathology.getLabel()
+                logger.LogUserAction("Added pathology '" + curPathology.getLabel()
                                 + "' with datasets: '" + userPathologyDatasets + "'");
 
                 PathologyDTO userPathology = new PathologyDTO();
@@ -91,4 +92,24 @@ public class ClaimUtils {
         return gson.toJson(userPathologies);
     }
 
+    private static boolean  hasRoleAccess(ArrayList<String> authorities, String role, Logger logger)
+    {
+        List<String> userClaims = Arrays.asList(authorities.toString().toLowerCase()
+                .replaceAll("[\\s+\\]\\[]", "").split(","));
+
+        logger.LogUserAction("User Claims: " + userClaims);
+        return userClaims.contains(role.toLowerCase());
+    }
+
+    private static ArrayList<String> getKeycloakAuthorities(Authentication authentication, Logger logger){
+        KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication;
+        KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) token.getPrincipal();
+        if(keycloakPrincipal.getKeycloakSecurityContext().getIdToken().getOtherClaims().get("authorities") == null)
+        {
+            logger.LogUserAction("Your user has no roles.");
+            throw new InternalServerError("Your user has no roles.");
+        }
+
+         return (ArrayList<String>)keycloakPrincipal.getKeycloakSecurityContext().getIdToken().getOtherClaims().get("authorities");
+    }
 }
diff --git a/src/main/java/eu/hbp/mip/utils/ControllerExceptionHandler.java b/src/main/java/eu/hbp/mip/utils/ControllerExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f644fb7fec4eec89a653236da29be79e3a2f80c
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/ControllerExceptionHandler.java
@@ -0,0 +1,89 @@
+package eu.hbp.mip.utils;
+
+import eu.hbp.mip.utils.Exceptions.*;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+import java.util.Date;
+
+@ControllerAdvice
+public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
+
+    @ExceptionHandler(ExperimentNotFoundException.class)
+    public ResponseEntity<Object> handleExperimentNotFoundException(ExperimentNotFoundException ex, WebRequest request) {
+
+        ErrorMessage message = new ErrorMessage(
+                HttpStatus.NOT_FOUND.value(),
+                new Date(),
+                ex.getMessage(),
+                request.getDescription(false));
+
+        return new ResponseEntity<>(message, HttpStatus.NOT_FOUND);
+    }
+    
+    @ExceptionHandler(BadRequestException.class)
+    public ResponseEntity<Object> handleBadRequestException(BadRequestException ex, WebRequest request) {
+
+        ErrorMessage message = new ErrorMessage(
+                HttpStatus.BAD_REQUEST.value(),
+                new Date(),
+                ex.getMessage(),
+                request.getDescription(false));
+
+        return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
+    }
+
+    @ExceptionHandler(UnauthorizedException.class)
+    public ResponseEntity<Object> handleUnauthorizedException(UnauthorizedException ex, WebRequest request) {
+
+        ErrorMessage message = new ErrorMessage(
+                HttpStatus.UNAUTHORIZED.value(),
+                new Date(),
+                ex.getMessage(),
+                request.getDescription(false));
+
+        return new ResponseEntity<>(message, HttpStatus.UNAUTHORIZED);
+    }
+
+    @ExceptionHandler(IllegalArgumentException.class)
+    public Object handleIllegalArgumentException(IllegalArgumentException ex, WebRequest request) {
+        return null;
+    }
+
+    @ExceptionHandler(InternalServerError.class)
+    public ResponseEntity<ErrorMessage> handleInternalServerError(InternalServerError er, WebRequest request) {
+        ErrorMessage message = new ErrorMessage(
+                HttpStatus.INTERNAL_SERVER_ERROR.value(),
+                new Date(),
+                er.getMessage(),
+                request.getDescription(false));
+
+        return new ResponseEntity<>(message, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+
+    @ExceptionHandler(NoContent.class)
+    public ResponseEntity<ErrorMessage> handleNoContent(NoContent nc, WebRequest request) {
+        ErrorMessage message = new ErrorMessage(
+                HttpStatus.NO_CONTENT.value(),
+                new Date(),
+                nc.getMessage(),
+                request.getDescription(false));
+
+        return new ResponseEntity<>(message, HttpStatus.NO_CONTENT);
+    }
+
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<ErrorMessage> globalExceptionHandler(Exception ex, WebRequest request) {
+        ErrorMessage message = new ErrorMessage(
+                HttpStatus.INTERNAL_SERVER_ERROR.value(),
+                new Date(),
+                ex.getMessage(),
+                request.getDescription(false));
+
+        return new ResponseEntity<>(message, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/utils/CustomAccessDeniedHandler.java b/src/main/java/eu/hbp/mip/utils/CustomAccessDeniedHandler.java
deleted file mode 100644
index 783e4a3ff68ab3384a798d9fc70f68f29c114bd6..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/utils/CustomAccessDeniedHandler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package eu.hbp.mip.utils;
-
-import org.codehaus.jettison.json.JSONException;
-import org.codehaus.jettison.json.JSONObject;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.web.access.AccessDeniedHandler;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.sql.Timestamp;
-
-public class CustomAccessDeniedHandler implements AccessDeniedHandler {
-    @Override
-    public void handle(HttpServletRequest request, HttpServletResponse response,
-                       AccessDeniedException accessDeniedException) throws IOException, ServletException {
-        response.setContentType("application/json;charset=UTF-8");
-        response.setStatus(403);
-        try {
-            response.getWriter().write(new JSONObject()
-                    .put("timestamp", new Timestamp(System.currentTimeMillis()))
-                    .put("status", 403)
-                    .put("error", "Forbidden")
-                    .put("message", "Access Denied. Please contact the system administrator to request access.")
-                    .put("path", request.getServletPath())
-                    .toString());
-        } catch (JSONException e) {
-            response.getWriter().write("");
-            e.printStackTrace();
-        }
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/utils/CustomLoginUrlAuthenticationEntryPoint.java b/src/main/java/eu/hbp/mip/utils/CustomLoginUrlAuthenticationEntryPoint.java
deleted file mode 100644
index 45870c7778280ff60c8ccca2908105ee677a6f7a..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/utils/CustomLoginUrlAuthenticationEntryPoint.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package eu.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/eu/hbp/mip/utils/ErrorMessage.java b/src/main/java/eu/hbp/mip/utils/ErrorMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef15c71ae041b277e51c487afb03d17d11556aa8
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/ErrorMessage.java
@@ -0,0 +1,34 @@
+package eu.hbp.mip.utils;
+
+
+import java.util.Date;
+
+public class ErrorMessage {
+    private int statusCode;
+    private Date timestamp;
+    private String message;
+    private String description;
+
+    public ErrorMessage(int statusCode, Date timestamp, String message, String description) {
+        this.statusCode = statusCode;
+        this.timestamp = timestamp;
+        this.message = message;
+        this.description = description;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public Date getTimestamp() {
+        return timestamp;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/utils/ErrorMessages.java b/src/main/java/eu/hbp/mip/utils/ErrorMessages.java
deleted file mode 100644
index 9f672f81b8bb57c559015a52bc65e44a0da7bd72..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/utils/ErrorMessages.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.hbp.mip.utils;
-
-public class ErrorMessages {
-
-    public static String pathologiesCouldNotBeLoaded = "The pathologies could not be loaded.";
-    public static String disabledAlgorithmsCouldNotBeLoaded = "The disabled algorithms could not be loaded.";
-}
diff --git a/src/main/java/eu/hbp/mip/utils/Exceptions/BadRequestException.java b/src/main/java/eu/hbp/mip/utils/Exceptions/BadRequestException.java
new file mode 100644
index 0000000000000000000000000000000000000000..6684cae281a0487aa5d39e78693b6c9f5bd04098
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/Exceptions/BadRequestException.java
@@ -0,0 +1,8 @@
+package eu.hbp.mip.utils.Exceptions;
+
+public class BadRequestException extends RuntimeException {
+
+    public BadRequestException(String msg) {
+        super(msg);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java b/src/main/java/eu/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8e05d7e667769537de9d540f436902dca6edc4e
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java
@@ -0,0 +1,8 @@
+package eu.hbp.mip.utils.Exceptions;
+
+public class ExperimentNotFoundException extends RuntimeException {
+
+    public ExperimentNotFoundException(String msg) {
+        super(msg);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/Exceptions/InternalServerError.java b/src/main/java/eu/hbp/mip/utils/Exceptions/InternalServerError.java
new file mode 100644
index 0000000000000000000000000000000000000000..19bc88eed27b6e0e4ab36a05136f043be65725ec
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/Exceptions/InternalServerError.java
@@ -0,0 +1,8 @@
+package eu.hbp.mip.utils.Exceptions;
+
+public class InternalServerError extends RuntimeException {
+
+    public InternalServerError(String msg) {
+        super(msg);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/Exceptions/NoContent.java b/src/main/java/eu/hbp/mip/utils/Exceptions/NoContent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bb67d8114e71545b8a00a8eb0bcdb0f7285b714
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/Exceptions/NoContent.java
@@ -0,0 +1,8 @@
+package eu.hbp.mip.utils.Exceptions;
+
+public class NoContent extends RuntimeException {
+
+    public NoContent(String msg) {
+        super(msg);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/Exceptions/UnauthorizedException.java b/src/main/java/eu/hbp/mip/utils/Exceptions/UnauthorizedException.java
new file mode 100644
index 0000000000000000000000000000000000000000..379911daeabe7227497f3d5bb622e54f6ccffb87
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/Exceptions/UnauthorizedException.java
@@ -0,0 +1,8 @@
+package eu.hbp.mip.utils.Exceptions;
+
+public class UnauthorizedException extends RuntimeException {
+
+    public UnauthorizedException(String msg) {
+        super(msg);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/JsonConverters.java b/src/main/java/eu/hbp/mip/utils/JsonConverters.java
new file mode 100644
index 0000000000000000000000000000000000000000..74d01b851f44877fffe0e146d8f678ee3fb95dfb
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/JsonConverters.java
@@ -0,0 +1,27 @@
+package eu.hbp.mip.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+
+import java.lang.reflect.Type;
+
+public class JsonConverters {
+    private static final Gson gson = new Gson();
+
+    public static String convertObjectToJsonString(Object object)  {
+        ObjectMapper mapper = new ObjectMapper();
+        //Converting the Object to JSONString
+        try {
+            return mapper.writeValueAsString(object);
+        } catch (JsonProcessingException e) {
+            return e.getMessage();
+        }
+    }
+
+    public static  <T> T convertJsonStringToObject(String jsonString, Type typeOfT)  {
+        if(jsonString == null || jsonString.isEmpty())
+            return null;
+        return gson.fromJson(jsonString, typeOfT);
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/utils/Logging.java b/src/main/java/eu/hbp/mip/utils/Logger.java
similarity index 53%
rename from src/main/java/eu/hbp/mip/utils/Logging.java
rename to src/main/java/eu/hbp/mip/utils/Logger.java
index 9b75de636fc7c1721fca6dba59e2ce38cced1a7d..1e25d2c921f0338235bed01c2f2fcd55ab4cf94a 100644
--- a/src/main/java/eu/hbp/mip/utils/Logging.java
+++ b/src/main/java/eu/hbp/mip/utils/Logger.java
@@ -1,16 +1,23 @@
 package eu.hbp.mip.utils;
 
-import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.UUID;
 
-public class Logging {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(Logging.class);
+public class Logger {
 
-    public static void LogUserAction(String userName, String endpoint, String actionInfo) {
-        LOGGER.info(" User -> " + userName + " ,"
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Logger.class);
+    private  String username;
+    private  String endpoint;
+
+    public Logger(String username, String endpoint){
+        this.username = username;
+        this.endpoint = endpoint;
+    }
+
+    public void LogUserAction(String actionInfo) {
+        LOGGER.info(" User -> " + username + " ,"
                 + "Endpoint -> " + endpoint + " ,"
                 + "Info ->  " + actionInfo);
     }
diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf
deleted file mode 100644
index e2abfd5ae7f2a4e0e3ceb4abc888cdb065dbc79f..0000000000000000000000000000000000000000
--- a/src/main/resources/application.conf
+++ /dev/null
@@ -1,20 +0,0 @@
-app {
-  # Name of the application
-  name = "Portal backend"
-  # Type of the application
-  type = "Spring"
-  clusterSystemName = ${clustering.cluster.name}
-}
-
-clustering {
-  ip = "127.0.0.1"
-  ip = ${?CLUSTER_IP}
-  port = 4489
-  port = ${?CLUSTER_PORT}
-}
-
-akka {
-  cluster {
-    roles = ["portal"]
-  }
-}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..345fc4bfa1955560e8cc33b2fb7cf62bb3698f12
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,81 @@
+# Configuration for development purposes
+
+### LOG LEVELS ###
+logging:
+  level:
+    root: "ERROR"
+    org: "ERROR"
+    eu:
+      hbp: "DEBUG"
+
+
+### AUTHENTICATION ###
+authentication:
+  enabled: false
+
+
+### DATABASE CONFIGURATION ###
+spring:
+  portal-datasource:
+    url: "jdbc:postgresql://127.0.0.1:5433/portal"
+    schema: "public"
+    username: "portal"
+    password: "portalpwd"
+    driver-class-name: org.postgresql.Driver
+  data:
+    jpa:
+      repositories:
+        bootstrap-mode: default
+  jpa:
+    hibernate:
+      dialect: org.hibernate.dialect.PostgreSQL9Dialect
+      ddl-auto: validate
+
+
+### EXTERNAL SERVICES ###
+services:
+  exareme:
+    queryExaremeUrl: "http://127.0.0.1:9090/mining/query"
+    algorithmsUrl: "http://127.0.0.1:9090/mining/algorithms.json"
+  galaxy:
+    galaxyUrl: "http://127.0.0.1:8090"
+    galaxyContext:  "nativeGalaxy/workflows/list"
+    galaxyApiKey:   "d14a4cc5eebf805eb2ff261374ed08a2"
+    galaxyUsername:  "admin"
+    galaxyPassword:  "password"
+
+
+### KEYCLOAK ###
+keycloak:
+  enabled: true
+  auth-server-url: "https://iam.humanbrainproject.eu/auth"
+  realm: "MIP"
+  resource: "mipfedqa"
+  enable-basic-auth: true
+  credentials:
+    secret: "dae83a6b-c769-4186-8383-f0984c6edf05"
+  principal-attribute: "preferred_username"
+
+
+### EXTERNAL FILES ###
+# Files are loaded from the resources
+files:
+  pathologies_json: "classPath:/pathologies.json"
+  disabledAlgorithms_json: "classPath:/disabledAlgorithms.json"
+
+
+### EMBEDDED SERVER CONFIGURATION ###
+server:
+  servlet:
+    contextPath: "/services"
+  port: 8080
+  forward-headers-strategy: native
+
+
+### ENDPOINTS ###
+endpoints:
+  enabled: true
+  health:
+    enabled: true
+    endpoint: "/health"
+    sensitive: false
\ No newline at end of file
diff --git a/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql b/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c1732c9e94860337218e6af917b1b523980a3d63
--- /dev/null
+++ b/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql
@@ -0,0 +1,84 @@
+UPDATE experiment
+SET algorithms =
+    (
+        SELECT SUBSTR(algorithms, 2, LENGTH(algorithms) - 2)
+    );
+
+UPDATE experiment
+SET workflowstatus = 'error'
+WHERE workflowstatus IS NULL AND haserror;
+
+UPDATE experiment
+SET workflowstatus = 'success'
+WHERE workflowstatus IS NULL AND NOT haserror;
+
+UPDATE experiment
+SET workflowstatus = 'success'
+WHERE workflowstatus = 'completed';
+
+UPDATE experiment
+SET workflowstatus = 'pending'
+WHERE workflowstatus = 'running';
+
+ALTER TABLE experiment
+DROP COLUMN haserror,
+DROP COLUMN hasservererror,
+DROP COLUMN validations,
+DROP COLUMN model_slug;
+
+ALTER TABLE experiment
+RENAME algorithms TO algorithm;
+ALTER TABLE experiment
+ALTER COLUMN algorithm TYPE json USING algorithm::json;
+ALTER TABLE experiment
+RENAME createdby_username TO created_by_username;
+ALTER TABLE experiment
+RENAME workflowhistoryid TO workflow_history_id;
+ALTER TABLE experiment
+RENAME resultsviewed TO viewed;
+ALTER TABLE experiment
+RENAME workflowstatus TO status;
+
+ALTER TABLE experiment
+ADD COLUMN algorithmId text;
+
+UPDATE experiment
+SET algorithmId = (algorithm ->> 'name');
+
+ALTER TABLE experiment
+ALTER COLUMN algorithm TYPE text;
+ALTER TABLE experiment
+ADD COLUMN updated timestamp without time zone;
+
+ALTER TABLE "user"
+DROP COLUMN birthday,
+DROP COLUMN city,
+DROP COLUMN country,
+DROP COLUMN firstname,
+DROP COLUMN gender,
+DROP COLUMN isactive,
+DROP COLUMN lastname,
+DROP COLUMN password,
+DROP COLUMN phone,
+DROP COLUMN picture,
+DROP COLUMN team,
+DROP COLUMN web,
+DROP COLUMN apikey;
+
+ALTER TABLE "user"
+ADD COLUMN subjectID text;
+
+DROP TABLE "config_title", "config_yaxisvariables";
+DROP TABLE "dataset_variable", "dataset_grouping", "dataset_data", "dataset_header";
+DROP TABLE "query_variable", "query_grouping", "query_filter", "query_covariable";
+DROP TABLE "article_tag", "tag","article";
+DROP TABLE "variable_value";
+DROP TABLE "query_training_datasets", "query_validation_datasets", "query_testing_datasets";
+DROP TABLE "variable", "value";
+DROP TABLE "group_group", "group";
+DROP TABLE "model";
+DROP TABLE "query";
+DROP TABLE "dataset";
+DROP TABLE "config";
+DROP TABLE "vote", "app";
+DROP TABLE "user_roles", "user_languages";
diff --git a/src/main/resources/kamon.conf b/src/main/resources/kamon.conf
deleted file mode 100644
index face394cba2325ea855db49c88219256c610a333..0000000000000000000000000000000000000000
--- a/src/main/resources/kamon.conf
+++ /dev/null
@@ -1,75 +0,0 @@
-kamon {
-  enabled = no
-  enabled = ${?KAMON_ENABLED}
-
-  environment {
-    service = "portal-backend"
-    service = ${?KAMON_SERVICE_NAME}
-  }
-
-  zipkin = {
-    enabled = no
-    enabled = ${?ZIPKIN_ENABLED}
-    host = "zipkin"
-    host = ${?ZIPKIN_IP}
-    port = 9411
-    port = ${?ZIPKIN_PORT}
-  }
-
-  prometheus = {
-    enabled = no
-    enabled = ${?PROMETHEUS_ENABLED}
-    host = "prometheus"
-    host = ${?PROMETHEUS_IP}
-    port = 9090
-    port = ${?PROMETHEUS_PORT}
-  }
-
-  util.filters {
-    "akka.tracked-actor" {
-      includes = ["**"]
-    }
-
-    "akka.tracked-dispatcher" {
-      includes = ["**"]
-    }
-
-    "akka.traced-actor" {
-      includes = ["**"]
-      excludes = [
-        ${clustering.cluster.name}"/system/IO**",
-        ${clustering.cluster.name}"/user/Stream**",
-        ${clustering.cluster.name}"/system/transports**",
-        ${clustering.cluster.name}"/system/cluster**",
-        ${clustering.cluster.name}"/system/remote**",
-        ${clustering.cluster.name}"/system/endpointmanager/**",
-        ${clustering.cluster.name}"/system/sharding/UserActor/**"]
-    }
-
-  }
-
-  akka-http {
-    add-http-status-code-as-metric-tag = true
-  }
-
-  akka {
-    ask-pattern-timeout-warning = lightweight
-  }
-
-  trace {
-    join-remote-parents-with-same-span-id = yes
-    sampler = "always"
-  }
-
-  system-metrics {
-    host {
-      enabled = no
-      enabled = ${?SIGAR_SYSTEM_METRICS}
-    }
-    jvm {
-      enabled = no
-      enabled = ${?JVM_SYSTEM_METRICS}
-    }
-  }
-
-}