diff --git a/.gitignore b/.gitignore
index bb28673b34bc3a64e034c30c37668ad3ba342825..27d6ff1faa1f0120c4d5adca9b748f381149feb2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ project/
 /.project
 /.settings/
 dependency-reduced-pom.xml
+logs/
diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl
index e34a00c0c2d4b693fc1a4ff26d3f709b43223299..6174fb409d967a2c67b5013ecc435a72fd763929 100644
--- a/docker/config/application.tmpl
+++ b/docker/config/application.tmpl
@@ -78,15 +78,15 @@ endpoints:
 
 services:
   exareme:
-    miningExaremeUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/query
+    queryExaremeUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/query
     algorithmsUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/algorithms.json
-  workflows:
-    workflowUrl: {{ default .Env.WORKFLOW_URL "http://localhost:9090" }}
-    jwtSecret: {{ default .Env.JWT_SECRET "secret" }}
-    workflowAuthorization: {{ default .Env.WORKFLOW_AUTHORIZATION "undefined" }}
+
   galaxy:
+    galaxyUrl:      {{ default .Env.GALAXY_URL "http://localhost:8090/" }}
+    galaxyContext:  {{ default .Env.GALAXY_CONTEXT "nativeGalaxy/workflows/list" }}
+    galaxyApiKey:   {{ .Env.GALAXY_API_KEY }}
     galaxyUsername:  {{ default .Env.GALAXY_USERNAME "admin" }}
     galaxyPassword:  {{ default .Env.GALAXY_PASSWORD "password" }}
-    galaxyContext:  {{ default .Env.GALAXY_CONTEXT "nativeGalaxy" }}
+
   keycloak:
     keycloakUrl: {{ .Env.KEYCLOAK_URL }}
diff --git a/pom.xml b/pom.xml
index 674ec19543bfb73623cdf88324f209ae513aa0c3..fb47d331018bbd301afd6350b5136c2f5f2020e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,7 +42,7 @@
         <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>
-        <flyway-core.version>4.0.3</flyway-core.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>
@@ -218,6 +218,34 @@
             <artifactId>java-jwt</artifactId>
             <version>3.8.3</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>
+        </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>
+        </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>
diff --git a/src/main/java/eu/hbp/mip/MIPApplication.java b/src/main/java/eu/hbp/mip/MIPApplication.java
index befb16ec91ee35a0bbd2c9a7631f30be9cde4b21..e6ccd8e1e2d1e71107a9d262b21e02bb070eefae 100644
--- a/src/main/java/eu/hbp/mip/MIPApplication.java
+++ b/src/main/java/eu/hbp/mip/MIPApplication.java
@@ -9,7 +9,6 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
 
 @SpringBootApplication
 public class MIPApplication {
diff --git a/src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java b/src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java
index 5c03ec4ebf5a95f424e4214de582c7967ce14d93..6b973dc6575c2027a344b0a872591f1b465e9a87 100644
--- a/src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java
+++ b/src/main/java/eu/hbp/mip/configuration/PersistenceConfiguration.java
@@ -46,5 +46,4 @@ public class PersistenceConfiguration {
         flyway.setDataSource(portalDataSource());
         return flyway;
     }
-
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java b/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..efe69c07207cd1b247b20cc9a953a37cb8bea7b5
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
@@ -0,0 +1,157 @@
+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.google.gson.Gson;
+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.galaxy.WorkflowDTO;
+import eu.hbp.mip.utils.HTTPUtil;
+import eu.hbp.mip.utils.UserActionLogging;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Value;
+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 retrofit2.Call;
+import retrofit2.Response;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+@RestController
+@RequestMapping(value = "/algorithms", produces = {APPLICATION_JSON_VALUE})
+@Api(value = "/algorithms")
+public class AlgorithmsApi {
+
+    private static final Gson gson = new Gson();
+
+    @Value("#{'${services.exareme.algorithmsUrl}'}")
+    private String exaremeAlgorithmsUrl;
+
+    @Value("#{'${services.galaxy.galaxyUrl}'}")
+    private String galaxyUrl;
+
+    @Value("#{'${services.galaxy.galaxyApiKey}'}")
+    private String galaxyApiKey;
+
+    @ApiOperation(value = "List all algorithms", response = String.class)
+    @RequestMapping(method = RequestMethod.GET)
+    public ResponseEntity<List<AlgorithmDTO>> getAlgorithms() {
+        UserActionLogging.LogAction("List all algorithms", "");
+
+        List<AlgorithmDTO> exaremeAlgorithms = getExaremeAlgorithms();
+        List<AlgorithmDTO> galaxyAlgorithms = getGalaxyWorkflows();
+
+        List<AlgorithmDTO> algorithms = new LinkedList<>();
+        if (exaremeAlgorithms != null) {
+            algorithms.addAll(exaremeAlgorithms);
+        } else {
+            UserActionLogging.LogAction("List all algorithms",
+                    "Getting exareme algorithms failed and returned null");
+        }
+        if (galaxyAlgorithms != null) {
+            algorithms.addAll(galaxyAlgorithms);
+        } else {
+            UserActionLogging.LogAction("List all algorithms",
+                    "Getting galaxy workflows failed and returned null");
+        }
+
+        return ResponseEntity.ok(algorithms);
+    }
+
+    /**
+     * This method gets all the available exareme algorithms and
+     *
+     * @return a list of AlgorithmDTOs or null if something fails
+     */
+    public List<AlgorithmDTO> getExaremeAlgorithms() {
+        UserActionLogging.LogAction("List exareme algorithms", "");
+
+        List<AlgorithmDTO> algorithms = new LinkedList<>();
+        // Get exareme algorithms
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendGet(exaremeAlgorithmsUrl, response);
+
+            algorithms = gson.fromJson(response.toString(), algorithms.getClass());
+        } catch (IOException e) {
+            UserActionLogging.LogAction("List exareme algorithms", "An exception occurred: " + e.getMessage());
+            return null;
+        }
+
+        UserActionLogging.LogAction("List exareme algorithms",
+                "Completed, returned " + algorithms.size() + " algorithms.");
+        return algorithms;
+    }
+
+    /**
+     * This method gets all the available galaxy workflows, converts them into algorithms and
+     *
+     * @return a list of AlgorithmDTOs or null if something fails
+     */
+    public List<AlgorithmDTO> getGalaxyWorkflows() {
+        UserActionLogging.LogAction("List Galaxy workflows", "");
+
+        List<Workflow> workflowList = null;
+        try {
+            // Get all the workflows with the galaxy client
+            final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey);
+            final WorkflowsClient workflowsClient = instance.getWorkflowsClient();
+
+            workflowList = new ArrayList<>(workflowsClient.getWorkflows());
+        } catch (Exception e) {
+            UserActionLogging.LogAction("List Galaxy workflows", "Error when calling list galaxy workflows: " + e.getMessage());
+
+            return null;
+        }
+
+        // Get the workflow details with the custom client to receive them as a WorkflowDTO
+        List<WorkflowDTO> workflows = new LinkedList<>();
+        // Create the request client
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        for (Workflow workflow : workflowList) {
+            // Call Galaxy to run the workflow
+            Call<WorkflowDTO> call = service.getWorkflowFromGalaxy(workflow.getId(), galaxyApiKey);
+            try {
+                Response<WorkflowDTO> response = call.execute();
+
+                if (response.code() == 200) {       // Call succeeded
+                    workflows.add(response.body());
+
+                } else {     // Something unexpected happened
+                    String msgErr = gson.toJson(response.errorBody());
+                    UserActionLogging.LogAction("List Galaxy workflows", "Error Response: " + msgErr);
+                    return null;
+                }
+            } catch (Exception e) {
+                UserActionLogging.LogAction("List Galaxy workflows", "An exception occurred: " + e.getMessage());
+                return null;
+            }
+        }
+        UserActionLogging.LogAction("List Galaxy workflows", "Workflows fetched: " + workflows.size());
+
+        // Convert the workflows to algorithms
+        List<AlgorithmDTO> algorithms = new LinkedList<>();
+        for (WorkflowDTO workflow : workflows) {
+            UserActionLogging.LogAction("List Galaxy workflows", "Converting workflow: " + workflow);
+
+            algorithms.add(workflow.convertToAlgorithmDTO());
+
+            UserActionLogging.LogAction("List Galaxy workflows",
+                    "Converted algorithm: " + algorithms.get(algorithms.size() - 1));
+        }
+
+        UserActionLogging.LogAction("List Galaxy workflows", "Completed!");
+        return algorithms;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java b/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java
deleted file mode 100644
index 897828faff819f71c108bbde751598b6b494776f..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Created by mirco on 04.12.15.
- */
-
-package eu.hbp.mip.controllers;
-
-import io.swagger.annotations.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-
-@RestController
-@RequestMapping(value = "/datasets", produces = {APPLICATION_JSON_VALUE})
-@Api(value = "/datasets", description = "the datasets API")
-public class DatasetsApi {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(DatasetsApi.class);
-
-
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
index deef20f755c0fd961e09a238eb662a671a9532e2..f876e315ed224bfc667b6ff6fb9337a2bafb361f 100644
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
@@ -1,48 +1,60 @@
 package eu.hbp.mip.controllers;
 
-import com.google.gson.*;
+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.Gson;
-import com.google.gson.GsonBuilder;
-
+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.HTTPUtil;
+import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+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.web.bind.annotation.*;
-import eu.hbp.mip.utils.JWTUtil;
-import eu.hbp.mip.utils.UserActionLogging;
+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;
 
-/**
- * Created by habfast on 21/04/16.
+/*
+    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", description = "the experiments API")
+@RequestMapping(value = "/experiments", produces = {APPLICATION_JSON_VALUE})
+@Api(value = "/experiments")
 public class ExperimentApi {
 
-    //private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentApi.class);
-
     private static final Gson gson = new Gson();
 
     private static final Gson gsonOnlyExposed = new GsonBuilder().serializeNulls()
             .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").excludeFieldsWithoutExposeAnnotation().create();
 
-    @Value("#{'${services.exareme.miningExaremeUrl:http://localhost:9090/mining/query}'}")
-    public String miningExaremeQueryUrl;
+    @Value("#{'${services.exareme.queryExaremeUrl}'}")
+    private String queryExaremeUrl;
 
     @Value("#{'${services.workflows.workflowUrl}'}")
     private String workflowUrl;
@@ -50,6 +62,12 @@ public class ExperimentApi {
     @Value("#{'${services.workflows.jwtSecret}'}")
     private String jwtSecret;
 
+    @Value("#{'${services.galaxy.galaxyUrl}'}")
+    private String galaxyUrl;
+
+    @Value("#{'${services.galaxy.galaxyApiKey}'}")
+    private String galaxyApiKey;
+
     @Autowired
     private UserInfo userInfo;
 
@@ -59,94 +77,6 @@ public class ExperimentApi {
     @Autowired
     private ExperimentRepository experimentRepository;
 
-    @ApiOperation(value = "Create an experiment on Exareme", response = Experiment.class)
-    @RequestMapping(value = "/exareme", method = RequestMethod.POST)
-    public ResponseEntity<String> runExaremeExperiment(@RequestBody ExperimentQuery expQuery) {
-        //LOGGER.info("send ExaremeExperiment");
-
-        Experiment experiment = saveExperiment(expQuery);
-
-        String algoCode = expQuery.getAlgorithms().get(0).getCode();
-        List<AlgorithmParam> params = expQuery.getAlgorithms().get(0).getParameters();
-        new Thread(() -> {
-            List<HashMap<String, String>> queryList = new ArrayList<HashMap<String, String>>();
-
-            if (params != null) {
-                for (AlgorithmParam p : params) {
-                    queryList.add(makeObject(p.getName(), p.getValue()));
-                }
-            }
-
-            String query = gson.toJson(queryList);
-            String url = miningExaremeQueryUrl + "/" + algoCode;
-
-            // Results are stored in the experiment object
-            try {
-                StringBuilder results = new StringBuilder();
-                int code = HTTPUtil.sendPost(url, query, results);
-                experiment.setResult("[" + results.toString() + "]");
-                experiment.setHasError(code >= 400);
-                experiment.setHasServerError(code >= 500);
-            } catch (IOException e) {
-                //LOGGER.trace("Invalid UUID", e);
-                //LOGGER.warn("Exareme experiment failed to run properly !");
-                experiment.setHasError(true);
-                experiment.setHasServerError(true);
-                experiment.setResult(e.getMessage());
-            }
-            finishExperiment(experiment);
-        }).start();
-		
-		UserActionLogging.LogAction("create ExaremeExperiment", "no info");
-		
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "Create a workflow", response = Experiment.class)
-    @RequestMapping(value = "/workflow", method = RequestMethod.POST)
-    public ResponseEntity<String> runWorkflow(@RequestBody ExperimentQuery expQuery) {
-        
-        Experiment experiment = saveExperiment(expQuery);
-
-        String algoCode = expQuery.getAlgorithms().get(0).getCode();
-        List<AlgorithmParam> params = expQuery.getAlgorithms().get(0).getParameters();
-
-        User user = userInfo.getUser();
-        String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-
-        HashMap<String, String> queryMap = new HashMap<String, String>();
-
-        if (params != null) {
-            for (AlgorithmParam p : params) {
-                queryMap.put(p.getName(), p.getValue());
-            }
-        }
-
-        String query = gson.toJson(queryMap);
-        String url = workflowUrl + "/runWorkflow/" + algoCode;
-        // Results are stored in the experiment object
-
-        new Thread(() -> {
-            try {
-                StringBuilder results = new StringBuilder();
-                int code = HTTPUtil.sendAuthorizedHTTP(url, query, results, "POST", "Bearer " + token);
-                experiment.setResult("[" + results.toString() + "]");
-                experiment.setHasError(code >= 400);
-                experiment.setHasServerError(code >= 500);
-            } catch (IOException e) {
-                //LOGGER.trace("Invalid UUID", e);
-                experiment.setHasError(true);
-                experiment.setHasServerError(true);
-                experiment.setResult(e.getMessage());
-            }
-            finishExperiment(experiment);
-        }).start();
-
-		UserActionLogging.LogAction("create workflow", "no info");
-		
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
     @ApiOperation(value = "get an experiment", response = Experiment.class)
     @RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
     public ResponseEntity<String> getExperiment(
@@ -157,8 +87,7 @@ public class ExperimentApi {
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
-            //LOGGER.trace("Invalid UUID", iae);
-            //LOGGER.warn("An invalid Experiment UUID was received ! " + uuid);
+            UserActionLogging.LogAction("Get Experiment", "Invalid Experiment UUID.");
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
@@ -167,95 +96,24 @@ public class ExperimentApi {
         if (experiment == null) {
             return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
         }
-		
-		UserActionLogging.LogAction("Get an experiment ", " uuid : "+ uuid);
-		
-        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "get workflow status", response = String.class)
-    @RequestMapping(value = "/workflow/status/{historyId}", method = RequestMethod.GET)
-    public ResponseEntity<String> getWorkflowStatus(
-            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
-       
-		UserActionLogging.LogAction("Get a workflow status", " historyId : "+ historyId);
-		
-        String url = workflowUrl + "/getWorkflowStatus/" + historyId;
-        try {
-            User user = userInfo.getUser();
-            String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-            StringBuilder response = new StringBuilder();
-            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", "Bearer " + token);
-            JsonElement element = new JsonParser().parse(response.toString());
-
-            return ResponseEntity.ok(gson.toJson(element));
-        } catch (IOException e) {
-            return ResponseEntity.status(500).body(e.getMessage());
-        }
-		
-    }
-
-    // TODO: factorize workflow results
-    @ApiOperation(value = "get workflow results", response = String.class)
-    @RequestMapping(value = "/workflow/results/{historyId}", method = RequestMethod.GET)
-    public ResponseEntity<String> getWorkflowResults(
-            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
-        UserActionLogging.LogAction("Get workflow results", " historyId : "+ historyId);
-		
-        String url = workflowUrl + "/getWorkflowResults/" + historyId;
-        try {
-            StringBuilder response = new StringBuilder();
-            User user = userInfo.getUser();
-            String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", "Bearer " + token);
-            JsonElement element = new JsonParser().parse(response.toString());
-
-            return ResponseEntity.ok(gson.toJson(element));
-        } catch (IOException e) {
-            return ResponseEntity.status(500).body(e.getMessage());
-        }
-    }
 
-    @ApiOperation(value = "get workflow result body", response = String.class)
-    @RequestMapping(value = "/workflow/resultsbody/{historyId}/content/{resultId}", method = RequestMethod.GET)
-    public ResponseEntity<String> getWorkflowResultBody(
-            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
-            @ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
-
-		UserActionLogging.LogAction("Get workflow result content", " historyId : "+ historyId + " resultId : "+ resultId);
-		
-        String url = workflowUrl + "/getWorkflowResultsBody/" + historyId + "/contents/" + resultId;
-        try {
-            StringBuilder response = new StringBuilder();
-            User user = userInfo.getUser();
-            String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", "Bearer " + token);
-            JsonElement element = new JsonParser().parse(response.toString());
+        UserActionLogging.LogAction("Get an experiment ", " uuid : " + uuid);
 
-            return ResponseEntity.ok(gson.toJson(element));
-        } catch (IOException e) {
-            return ResponseEntity.status(500).body(e.getMessage());
-        }
+        return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
-    @ApiOperation(value = "get workflow result details", response = String.class)
-    @RequestMapping(value = "/workflow/resultsdetails/{historyId}/content/{resultId}", method = RequestMethod.GET)
-    public ResponseEntity<String> getWorkflowResultsDetails(
-            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
-            @ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
-		UserActionLogging.LogAction("Get workflow result details", " historyId : "+ historyId + " resultId : "+ resultId);
+    @ApiOperation(value = "Create an experiment", response = Experiment.class)
+    @RequestMapping(value = "/runAlgorithm", method = RequestMethod.POST)
+    public ResponseEntity<String> runExperiment(@RequestBody ExperimentExecutionDTO experimentExecutionDTO) {
+        UserActionLogging.LogAction("Run algorithm", "Running the algorithm...");
 
-        String url = workflowUrl + "/getWorkflowResultsDetails/" + historyId + "/contents/" + resultId;
-        try {
-            StringBuilder response = new StringBuilder();
-            User user = userInfo.getUser();
-            String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", "Bearer " + token);
-            JsonElement element = new JsonParser().parse(response.toString());
+        // Get the type of algorithm
+        String algorithmType = experimentExecutionDTO.getAlgorithms().get(0).getType();
 
-            return ResponseEntity.ok(gson.toJson(element));
-        } catch (IOException e) {
-            return ResponseEntity.status(500).body(e.getMessage());
+        if (algorithmType.equals("workflow")) {
+            return runGalaxyWorkflow(experimentExecutionDTO);
+        } else {
+            return runExaremeAlgorithm(experimentExecutionDTO);
         }
     }
 
@@ -264,7 +122,7 @@ public class ExperimentApi {
     public ResponseEntity<String> markExperimentAsViewed(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
 
-		UserActionLogging.LogAction("Mark an experiment as viewed", " uuid : "+ uuid);
+        UserActionLogging.LogAction("Mark an experiment as viewed", " uuid : " + uuid);
 
         Experiment experiment;
         UUID experimentUuid;
@@ -283,7 +141,7 @@ public class ExperimentApi {
         experiment.setResultsViewed(true);
         experimentRepository.save(experiment);
 
-		UserActionLogging.LogAction("Experiment updated (marked as viewed)", " ");
+        UserActionLogging.LogAction("Experiment updated (marked as viewed)", " ");
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
@@ -293,8 +151,8 @@ public class ExperimentApi {
     public ResponseEntity<String> markExperimentAsShared(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
 
-		UserActionLogging.LogAction("Mark an experiment as shared", " uuid : "+ uuid);
-		
+        UserActionLogging.LogAction("Mark an experiment as shared", " uuid : " + uuid);
+
         return doMarkExperimentAsShared(uuid, true);
     }
 
@@ -302,27 +160,27 @@ public class ExperimentApi {
     @RequestMapping(value = "/{uuid}/markAsUnshared", method = RequestMethod.GET)
     public ResponseEntity<String> markExperimentAsUnshared(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-		UserActionLogging.LogAction("Mark an experiment as unshared", " uuid : "+ uuid);
-		
+        UserActionLogging.LogAction("Mark an experiment as unshared", " uuid : " + uuid);
+
         return doMarkExperimentAsShared(uuid, false);
     }
 
     @ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET, params = { "maxResultCount" })
+    @RequestMapping(method = RequestMethod.GET, params = {"maxResultCount"})
     public ResponseEntity<String> listExperiments(
             @ApiParam(value = "maxResultCount") @RequestParam int maxResultCount) {
 
-		UserActionLogging.LogAction("List experiments", " maxResultCount : "+ maxResultCount);
-		
+        UserActionLogging.LogAction("List experiments", " maxResultCount : " + maxResultCount);
+
         return doListExperiments(false, null);
     }
 
     @ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET, params = { "slug", "maxResultCount" })
+    @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) {
+                                                  @ApiParam(value = "maxResultCount") @RequestParam("maxResultCount") int maxResultCount) {
 
-		UserActionLogging.LogAction("List experiments", " modelSlug : "+ modelSlug);
+        UserActionLogging.LogAction("List experiments", " modelSlug : " + modelSlug);
 
         if (maxResultCount <= 0 && (modelSlug == null || "".equals(modelSlug))) {
             return new ResponseEntity<>("You must provide at least a slug or a limit of result",
@@ -333,9 +191,9 @@ public class ExperimentApi {
     }
 
     @ApiOperation(value = "list my experiments", response = Experiment.class, responseContainer = "List")
-    @RequestMapping(method = RequestMethod.GET, params = { "mine" })
+    @RequestMapping(method = RequestMethod.GET, params = {"mine"})
     public ResponseEntity<String> listMyExperiments(@ApiParam(value = "mine") @RequestParam("mine") boolean mine) {
-        UserActionLogging.LogAction("List my experiments", " mine : "+ mine);
+        UserActionLogging.LogAction("List my experiments", " mine : " + mine);
 
         return doListExperiments(true, null);
     }
@@ -352,7 +210,7 @@ public class ExperimentApi {
         }
 
         if (modelSlug != null && !"".equals(modelSlug)) {
-            for (Iterator<Experiment> it = expList.iterator(); it.hasNext();) {
+            for (Iterator<Experiment> it = expList.iterator(); it.hasNext(); ) {
                 Experiment e = it.next();
                 e.setResult(null);
                 e.setAlgorithms(null);
@@ -385,43 +243,527 @@ public class ExperimentApi {
 
         experiment.setShared(shared);
         experimentRepository.save(experiment);
-		
-		UserActionLogging.LogAction("Experiment updated (marked as shared)", "");
+
+        UserActionLogging.LogAction("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);
+
+        UserActionLogging.LogAction("Created an experiment", " id : " + experiment.getUuid());
+        UserActionLogging.LogAction("Created an experiment", " algorithms : " + experiment.getAlgorithms());
+        UserActionLogging.LogAction("Created an experiment", " model : " + experiment.getModel().getSlug());
+        UserActionLogging.LogAction("Created an experiment", " name : " + experiment.getName());
+        return experiment;
+    }
+
+    private void saveExperiment(Experiment experiment) {
+        UserActionLogging.LogAction("Saved an experiment", " id : " + experiment.getUuid());
+        UserActionLogging.LogAction("Saved an experiment", " algorithms : " + experiment.getAlgorithms());
+        UserActionLogging.LogAction("Saved an experiment", " model : " + experiment.getModel().getSlug());
+        UserActionLogging.LogAction("Saved an experiment", " name : " + experiment.getName());
+        UserActionLogging.LogAction("Saved an experiment", " historyId : " + experiment.getWorkflowHistoryId());
+        UserActionLogging.LogAction("Saved an experiment", " status : " + experiment.getWorkflowStatus());
+
+        experimentRepository.save(experiment);
+
+        UserActionLogging.LogAction("Experiment saved", "");
+    }
+
     private void finishExperiment(Experiment experiment) {
         experiment.setFinished(new Date());
         experimentRepository.save(experiment);
 
-        UserActionLogging.LogAction("Experiment updated (finished)","");
+        UserActionLogging.LogThreadAction("Experiment finished!", "");
     }
 
-    private HashMap<String, String> makeObject(String name, String value) {
-        HashMap<String, String> o = new HashMap<String, String>();
-        o.put("name", name);
-        o.put("value", value);
+    /* --------------------------------------  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) {
+        UserActionLogging.LogAction("Run exareme algorithm", "Running the algorithm...");
+
+        Experiment experiment = createExperiment(experimentExecutionDTO);
+
+        // 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;
+        UserActionLogging.LogAction("Run exareme algorithm", "url: " + url + ", body: " + body);
+
+        ResponseEntity<String> response = new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
+        UserActionLogging.LogAction("Run exareme algorithm",
+                "Completed, returning: " + experiment.toString());
 
-        return o;
+        UserActionLogging.LogAction("Run exareme algorithm",
+                "Starting exareme execution thread");
+        new Thread(() -> {
+            // ATTENTION: Inside the Thread only LogThreadAction should be used, not LogAction!
+            UserActionLogging.LogThreadAction("Run exareme algorithm",
+                    "Thread started!");
+
+            try {
+                UserActionLogging.LogThreadAction("Run exareme algorithm",
+                        "Thread started!");
+                StringBuilder results = new StringBuilder();
+                int code = HTTPUtil.sendPost(url, body, results);
+
+                UserActionLogging.LogThreadAction("Run exareme algorithm",
+                        "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) {
+                UserActionLogging.LogThreadAction("Run exareme algorithm",
+                        "There was an exception: " + e.getMessage());
+
+                experiment.setHasError(true);
+                experiment.setHasServerError(true);
+                experiment.setResult(e.getMessage());
+            }
+            UserActionLogging.LogThreadAction("Run exareme algorithm",
+                    "Finished the experiment: " + experiment.toString());
+            finishExperiment(experiment);
+
+            UserActionLogging.LogThreadAction("Run exareme algorithm",
+                    "Finished!");
+        }).start();
+
+        return response;
     }
 
-    private Experiment saveExperiment(ExperimentQuery expQuery) {
+    /* ---------------------------------------  GALAXY CALLS ---------------------------------------------------------*/
 
-        Experiment experiment = new Experiment();
-        experiment.setUuid(UUID.randomUUID());
-        User user = userInfo.getUser();
 
-        experiment.setAlgorithms(gson.toJson(expQuery.getAlgorithms()));
-        experiment.setValidations(gson.toJson(expQuery.getValidations()));
-        experiment.setName(expQuery.getName());
-        experiment.setCreatedBy(user);
-        experiment.setModel(modelRepository.findOne(expQuery.getModel()));
-        experimentRepository.save(experiment);
+    /**
+     * 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) {
+        UserActionLogging.LogAction("Run workflow", "Running a workflow...");
 
-        UserActionLogging.LogAction("Saved an experiment", " id : "+experiment.getUuid());
+        Experiment experiment = createExperiment(experimentExecutionDTO);
 
-        return experiment;
+        // 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) {
+            UserActionLogging.LogAction("Run workflow",
+                    "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);
+        UserActionLogging.LogAction("Run workflow", "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());
+                UserActionLogging.LogAction("Run workflow", "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());
+                UserActionLogging.LogAction("Run workflow", "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) {
+            UserActionLogging.LogAction("Run workflow", "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);
+
+        UserActionLogging.LogAction("Run workflow", "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) {
+
+        if (experiment == null) {
+            UserActionLogging.LogAction("Update workflow experiment", "The experiment does not exist.");
+            return;
+        }
+
+        UserActionLogging.LogAction("Update workflow experiment",
+                " Experiment id : " + experiment.getUuid());
+
+        if (experiment.getWorkflowHistoryId() == null) {
+            UserActionLogging.LogAction("Update workflow experiment", "History Id does not exist.");
+            return;
+        }
+
+        UserActionLogging.LogAction("Update workflow experiment", "Starting Thread..." );
+        new Thread(() -> {
+            while(true) {
+                // ATTENTION: Inside the Thread only LogThreadAction should be used, not LogAction!
+                UserActionLogging.LogThreadAction("Update workflow experiment", "Thread is running...");
+
+                try {
+                    sleep(2000);
+                } catch (InterruptedException e) {
+                    UserActionLogging.LogThreadAction("Update workflow experiment",
+                            "Sleep was disrupted: " + e.getMessage());
+                }
+
+                UserActionLogging.LogThreadAction("Update workflow experiment",
+                        "Fetching status for experiment Id: " + experiment.getUuid());
+
+                String state = getWorkflowStatus(experiment.getWorkflowHistoryId());
+                UserActionLogging.LogThreadAction("Update workflow experiment", "State is: " + state);
+
+                switch (state) {
+                    case "running":
+                        // Do nothing, when the experiment is created the status is set to running
+                        UserActionLogging.LogThreadAction("Update workflow experiment",
+                                "Workflow is still running.");
+                        break;
+
+                    case "completed":
+                        // Get only the job result that is visible
+                        List<GalaxyWorkflowResult> workflowJobsResults = getWorkflowResults(experiment.getWorkflowHistoryId());
+                        UserActionLogging.LogThreadAction("Update workflow experiment",
+                                "Results are: " + workflowJobsResults.toString());
+
+                        boolean resultFound = false;
+                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
+                            if (jobResult.getVisible()) {
+                                UserActionLogging.LogThreadAction("Update workflow experiment",
+                                        "Visible result are: " + jobResult.getId());
+
+                                String result = getWorkflowResultBody(experiment.getWorkflowHistoryId(), jobResult.getId());
+
+                                UserActionLogging.LogThreadAction("Update workflow experiment", "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
+                            UserActionLogging.LogThreadAction("Update workflow experiment", "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.getWorkflowHistoryId());
+                        UserActionLogging.LogThreadAction("Update workflow experiment",
+                                "Error results are: " + workflowJobsResults.toString());
+
+                        boolean failedJobFound = false;
+                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
+                            if (jobResult.getState().equals("error")) {
+                                UserActionLogging.LogThreadAction("Update workflow experiment",
+                                        "Failed job is: " + jobResult.getId());
+
+                                String result = getWorkflowJobError(jobResult.getId());
+
+                                UserActionLogging.LogThreadAction("Update workflow experiment", "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
+                            UserActionLogging.LogThreadAction("Update workflow experiment", "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) {
+                    UserActionLogging.LogThreadAction("Update workflow experiment",
+                            "Result exists: " + experiment.getResult());
+                    return;
+                }
+            }
+        }).start();
+    }
+
+
+    /**
+     * @param historyId The historyId 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(String historyId) {
+        // ATTENTION: This function is used from a Thread. Only LogThreadAction should be used, not LogAction!
+        UserActionLogging.LogThreadAction("Get workflow status", " 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) {
+                UserActionLogging.LogThreadAction("Get workflow status", " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return "internalError";
+            }
+            result = new Gson().toJson(response.body());
+            UserActionLogging.LogThreadAction("Get workflow status", " Result: " + result);
+
+        } catch (IOException e) {
+            UserActionLogging.LogThreadAction("Get workflow status"
+                    , " An exception happened: " + e.getMessage());
+            return "internalError";
+        }
+
+        String state = null;
+        try {
+            JSONObject resultJson = new JSONObject(result);
+            state = resultJson.getString("state");
+        } catch (JSONException e) {
+            UserActionLogging.LogThreadAction("Get workflow status"
+                    , " An exception happened: " + e.getMessage());
+            return "internalError";
+        }
+
+        UserActionLogging.LogThreadAction("Get workflow status", " 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 historyId The historyId of the workflow
+     * @return a List<GalaxyWorkflowResult>   or null when an error occurred
+     */
+    public List<GalaxyWorkflowResult> getWorkflowResults(String historyId) {
+        UserActionLogging.LogThreadAction("Get workflow results", " 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) {
+                UserActionLogging.LogThreadAction("Get workflow results", " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+            getGalaxyWorkflowResultList = response.body();
+            UserActionLogging.LogThreadAction("Get workflow results", " Result: " + response.body());
+
+        } catch (IOException e) {
+            UserActionLogging.LogThreadAction("Get workflow results"
+                    , " An exception happened: " + e.getMessage());
+            return null;
+        }
+
+        UserActionLogging.LogThreadAction("Get workflow results", " Completed!");
+        return getGalaxyWorkflowResultList;
+
+    }
+
+    /**
+     * @param historyId the historyId 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(String historyId, String contentId) {
+        UserActionLogging.LogThreadAction("Get workflow results Body", " 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) {
+                UserActionLogging.LogThreadAction("Get workflow results Body", " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+            resultJson = new Gson().toJson(response.body());
+            UserActionLogging.LogThreadAction("Get workflow results Body", " Result: " + resultJson);
+
+        } catch (IOException e) {
+            UserActionLogging.LogThreadAction("Get workflow results Body",
+                    " An exception happened: " + e.getMessage());
+            return null;
+        }
+
+        UserActionLogging.LogThreadAction("Get workflow results Body", " 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) {
+        UserActionLogging.LogThreadAction("Get workflow job error", " 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) {
+                UserActionLogging.LogThreadAction("Get workflow job error", "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();
+            UserActionLogging.LogThreadAction("Get workflow job error", "Error: " + fullError);
+
+            String[] arrOfStr = fullError.split("ValueError", 0);
+            String specError = arrOfStr[arrOfStr.length - 1];
+            returnError = specError.substring(1);
+            UserActionLogging.LogThreadAction("Get workflow job error", "Parsed Error: " + returnError);
+
+        } catch (IOException e) {
+            UserActionLogging.LogThreadAction("Get workflow job error", "Exception: " + e.getMessage());
+            return null;
+        }
+
+        UserActionLogging.LogThreadAction("Get workflow job error", "Completed successfully!");
+
+        return returnError;
+    }
+
+
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/JWTApi.java b/src/main/java/eu/hbp/mip/controllers/JWTApi.java
deleted file mode 100644
index a1cb6afd55431bb859170b52c9daa7007ca69c42..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/JWTApi.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package eu.hbp.mip.controllers;
-
-import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.HttpStatus;
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.bind.annotation.*;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import eu.hbp.mip.utils.JWTUtil;
-import eu.hbp.mip.utils.UserActionLogging;
-
-@RestController
-@RequestMapping(value = "/jwt", produces = { TEXT_PLAIN_VALUE })
-@Api(value = "/jwt", description = "the jwt API")
-public class JWTApi {
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @Value("#{'${services.workflows.jwtSecret}'}")
-    private String jwtSecret;
-
-    @ApiOperation(value = "Create a JSON Web Token", response = String.class)
-    @RequestMapping(method = RequestMethod.POST)
-    public ResponseEntity<String> createJWT() {
-
-        UserActionLogging.LogAction("Create a JSON Web Token", "");
-
-        User user = userInfo.getUser();
-        String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-
-        return ResponseEntity.status(HttpStatus.CREATED).body(token);
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
deleted file mode 100644
index f88f6795156f566b4b4e6e70288a5e4d535a67da..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package eu.hbp.mip.controllers;
-
-import com.google.gson.*;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-import eu.hbp.mip.model.User;
-import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.utils.HTTPUtil;
-import org.springframework.beans.factory.annotation.Value;
-import java.io.IOException;
-import eu.hbp.mip.utils.JWTUtil;
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-import org.springframework.beans.factory.annotation.Autowired;
-import eu.hbp.mip.utils.UserActionLogging;
-
-@RestController
-@RequestMapping(value = "/methods", produces = { APPLICATION_JSON_VALUE })
-@Api(value = "/methods", description = "the methods API")
-public class MethodsApi {
-
-    
-    private static final Gson gson = new Gson();
-
-    @Value("#{'${services.exareme.algorithmsUrl:http://localhost:9090/mining/algorithms.json}'}")
-    private String exaremeAlgorithmsUrl;
-
-    @Value("#{'${services.workflows.workflowUrl}'}")
-    private String workflowUrl;
-
-    @Value("#{'${services.workflows.jwtSecret}'}")
-    private String jwtSecret;
-
-    @Autowired
-    private UserInfo userInfo;
-
-    @ApiOperation(value = "List Exareme algorithms and validations", response = String.class)
-    @RequestMapping(value = "/exareme", method = RequestMethod.GET)
-    public ResponseEntity<Object> getExaremeAlgorithms() {
-        UserActionLogging.LogAction("List Exareme algorithms and validations", "");
-
-        try {
-            StringBuilder response = new StringBuilder();
-            HTTPUtil.sendGet(exaremeAlgorithmsUrl, response);
-            JsonElement element = new JsonParser().parse(response.toString());
-
-            return ResponseEntity.ok(gson.toJson(element));
-        } catch (IOException e) {
-            return ResponseEntity.status(500).body(e.getMessage());
-        }
-
-    }
-
-    @ApiOperation(value = "List Galaxy workflows", response = String.class)
-    @RequestMapping(value = "/workflows", method = RequestMethod.GET)
-    public ResponseEntity<Object> getWorkflows() {
-        UserActionLogging.LogAction("List Galaxy workflows", "");
-
-        try {
-            User user = userInfo.getUser();
-            String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
-
-            StringBuilder response = new StringBuilder();
-            HTTPUtil.sendAuthorizedHTTP(workflowUrl + "/getAllWorkflowWithDetails", "", response, "GET", "Bearer " + token);
-            JsonElement element = new JsonParser().parse(response.toString());
-
-            return ResponseEntity.ok(gson.toJson(element));
-        } catch (IOException e) {
-            return ResponseEntity.status(500).body(e.getMessage());
-        }
-
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/controllers/MiningApi.java b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
index 13272fc7355ed509e5b030429409a98b83ac55e1..3adcc6269e8120147c6c81367c91b928c1d5d486 100644
--- a/src/main/java/eu/hbp/mip/controllers/MiningApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
@@ -45,16 +45,16 @@ public class MiningApi {
     @Autowired
     private UserInfo userInfo;
 
-    @Value("#{'${services.exareme.miningExaremeUrl:http://localhost:9090/mining/query}'}")
-    public String miningExaremeQueryUrl;
+    @Value("#{'${services.exareme.queryExaremeUrl:http://localhost:9090/mining/query}'}")
+    public String queryExaremeUrl;
 
-    @ApiOperation(value = "Create an histogram on Exareme", response = String.class)
-    @RequestMapping(value = "/exareme", method = RequestMethod.POST)
-    public ResponseEntity runExaremeMining(@RequestBody List<HashMap<String, String>> queryList) {
+    @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) {
         UserActionLogging.LogAction("Run an histogram", "");
 
         String query = gson.toJson(queryList);
-        String url = miningExaremeQueryUrl + "/" + "HISTOGRAMS";
+        String url = queryExaremeUrl + "/" + "MULTIPLE_HISTOGRAMS";
 
         try {
             StringBuilder results = new StringBuilder();
@@ -66,13 +66,13 @@ public class MiningApi {
         }
     }
 
-    @ApiOperation(value = "Create an descriptive statistic on Exareme", response = String.class)
-    @RequestMapping(value = "/exareme-stats", method = RequestMethod.POST)
+    @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) {
         UserActionLogging.LogAction("Run descriptive stats", "");
 
         String query = gson.toJson(queryList);
-        String url = miningExaremeQueryUrl + "/" + "DESCRIPTIVE_STATS";
+        String url = queryExaremeUrl + "/" + "DESCRIPTIVE_STATS";
 
         try {
             StringBuilder results = new StringBuilder();
@@ -84,24 +84,11 @@ public class MiningApi {
         }
     }
 
-    @ApiOperation(value = "Perform an non persisted algorithm on Exareme", response = String.class)
-    @RequestMapping(value = "/exareme/{algorithmName}", method = RequestMethod.POST)
-    public ResponseEntity runExaremeAlgorithm(
-        @RequestBody List<HashMap<String, String>> queryList,
-        @ApiParam(value = "algorithmName", required = true) @PathVariable("algorithmName") String algorithmName
-        ) {
-        UserActionLogging.LogAction("Run algo", "");
+    @ApiOperation(value = "Check if a formula is valid", response = String.class)
+    @RequestMapping(value = "/checkFormula", method = RequestMethod.POST)
+    public ResponseEntity checkFormulaValidity(String formula) {
+        UserActionLogging.LogAction("Check Formula Validity", "");
 
-        String query = gson.toJson(queryList);
-        String url = miningExaremeQueryUrl + "/" + algorithmName;
-
-        try {
-            StringBuilder results = new StringBuilder();
-            int code = HTTPUtil.sendPost(url, query, results);
-
-            return ResponseEntity.ok(gson.toJson(results.toString()));
-        } catch (IOException e) {
-            return new ResponseEntity<>("Not found", HttpStatus.BAD_REQUEST);
-        }
+        return ResponseEntity.ok("");
     }
 }
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
new file mode 100644
index 0000000000000000000000000000000000000000..612dce6ca5b557f23deafdf873978c0f442eb1d9
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetroFitGalaxyClients.java
@@ -0,0 +1,31 @@
+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 retrofit2.Call;
+import retrofit2.http.*;
+
+import java.util.List;
+
+public interface RetroFitGalaxyClients {
+
+    @GET("workflows/{workflowId}")
+    Call<WorkflowDTO> getWorkflowFromGalaxy(@Path("workflowId") String workflowId, @Query("key") String key);
+
+    @POST("workflows/{workflowId}/invocations")
+    Call<PostWorkflowToGalaxyDtoResponse> postWorkflowToGalaxy(@Path("workflowId") String workflowId, @Query("key") String key, @Body JsonObject body);
+
+    @GET("histories/{historyId}")
+    Call<Object> getWorkflowStatusFromGalaxy(@Path("historyId") String historyId, @Query("key") String key);
+
+    @GET("histories/{historyId}/contents")
+    Call<List<GalaxyWorkflowResult>> getWorkflowResultsFromGalaxy(@Path("historyId") String historyId, @Query("key") String key);
+
+    @GET("histories/{historyId}/contents/{contentId}/display")
+    Call<Object> getWorkflowResultsBodyFromGalaxy(@Path("historyId") String historyId, @Path("contentId") String contentId, @Query("key") String key);
+
+    @GET("jobs/{jobId}?full=true")
+    Call<Object> getErrorMessageOfWorkflowFromGalaxy(@Path("jobId") String jobId, @Query("key") String key);
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetrofitClientInstance.java b/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetrofitClientInstance.java
new file mode 100644
index 0000000000000000000000000000000000000000..6aa218902ebd724518d56d8cca8b0c5e77aa2893
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/controllers/galaxy/retrofit/RetrofitClientInstance.java
@@ -0,0 +1,42 @@
+package eu.hbp.mip.controllers.galaxy.retrofit;
+
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+import javax.annotation.PostConstruct;
+
+@Component
+public class RetrofitClientInstance {
+
+    private static Retrofit retrofit;
+
+    @Value("#{'${services.galaxy.galaxyUrl}'}")
+    private String galaxyUrl;
+
+    private static String BASE_URL;
+
+    @PostConstruct
+    public void init() {
+        BASE_URL = galaxyUrl + "/api/";
+    }
+
+    public static Retrofit getRetrofitInstance() {
+        if (retrofit == null) {
+
+            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
+            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
+            OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
+
+            retrofit = new retrofit2.Retrofit.Builder()
+                    .baseUrl(BASE_URL)
+                    .client(client)
+                    .addConverterFactory(GsonConverterFactory.create())
+                    .build();
+        }
+        return retrofit;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/model/Algorithm.java b/src/main/java/eu/hbp/mip/model/Algorithm.java
deleted file mode 100644
index bd08093a82e0cc7823fdc6c33c193a3feff774ba..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/Algorithm.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package eu.hbp.mip.model;
-
-import java.util.LinkedList;
-
-/**
- * Created by mirco on 09.11.16.
- */
-
-public class Algorithm extends ExperimentValidator {
-
-    private boolean validation;
-
-    public Algorithm() {
-
-    }
-
-    public Algorithm(String code, String name, boolean validation) {
-        this.validation = validation;
-        setCode(code);
-        setName(name);
-        setParameters(new LinkedList<>());
-    }
-
-    public boolean isValidation() {
-        return validation;
-    }
-
-    public void setValidation(boolean validation) {
-        this.validation = validation;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/AlgorithmDTO.java b/src/main/java/eu/hbp/mip/model/AlgorithmDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed0ef2a15606ef09f139bad65c90c3cf436c2474
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/AlgorithmDTO.java
@@ -0,0 +1,220 @@
+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/AlgorithmParam.java b/src/main/java/eu/hbp/mip/model/AlgorithmParam.java
deleted file mode 100644
index 62c48ba13b4cffcf647d4da97a0509735f18cac4..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/AlgorithmParam.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package eu.hbp.mip.model;
-
-/**
- * Created by mirco on 09.11.16.
- */
-
-public class AlgorithmParam {
-
-    private String code;
-    private String value;
-
-    public String getCode() {
-        return code;
-
-    }
-
-    public void setName(String name) {
-        this.code = name;
-    }
-
-    public String getName() {
-        return this.code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/Experiment.java b/src/main/java/eu/hbp/mip/model/Experiment.java
index a15b575c9b76895d922d7c65b3c0ea3811501a7e..902cf37da1ef0abad1f2c8836fe0a7e2654f077f 100644
--- a/src/main/java/eu/hbp/mip/model/Experiment.java
+++ b/src/main/java/eu/hbp/mip/model/Experiment.java
@@ -16,8 +16,6 @@ import java.util.*;
 @Table(name = "`experiment`")
 public class Experiment {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(Experiment.class);
-
     private static final Gson gson = new Gson();
 
     @Id
@@ -45,9 +43,16 @@ public class Experiment {
     private String algorithms;
 
     @Column(columnDefinition="TEXT")
-    @Expose
     private String validations;
 
+    @Column(columnDefinition="TEXT")
+    @Expose
+    private String workflowHistoryId;
+
+    @Column(columnDefinition="TEXT")
+    @Expose
+    private String workflowStatus;
+
     @Column(columnDefinition="TEXT")
     @Expose
     private String result;
@@ -139,6 +144,22 @@ public class Experiment {
         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;
     }
diff --git a/src/main/java/eu/hbp/mip/model/ExperimentExecutionDTO.java b/src/main/java/eu/hbp/mip/model/ExperimentExecutionDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..a68cd9121d852503bc01eb6b2f0d23dd8af525dd
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/ExperimentExecutionDTO.java
@@ -0,0 +1,106 @@
+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/ExperimentQuery.java b/src/main/java/eu/hbp/mip/model/ExperimentQuery.java
deleted file mode 100644
index 333751c438099de62942918e17f019505a800de7..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/ExperimentQuery.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package eu.hbp.mip.model;
-
-import java.util.List;
-
-/**
- * Created by mirco on 09.11.16.
- */
-public class ExperimentQuery {
-
-    private String name;
-    private String model;
-    private List<ExperimentValidator> validations;
-    private List<Algorithm> algorithms;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getModel() {
-        return model;
-    }
-
-    public void setModel(String model) {
-        this.model = model;
-    }
-
-    public List<ExperimentValidator> getValidations() {
-        return validations;
-    }
-
-    public void setValidations(List<ExperimentValidator> validations) {
-        this.validations = validations;
-    }
-
-    public List<Algorithm> getAlgorithms() {
-        return algorithms;
-    }
-
-    public void setAlgorithms(List<Algorithm> algorithms) {
-        this.algorithms = algorithms;
-    }
-}
diff --git a/src/main/java/eu/hbp/mip/model/ExperimentValidator.java b/src/main/java/eu/hbp/mip/model/ExperimentValidator.java
deleted file mode 100644
index 208fc90fa7272779bf51e09ca7fa0b6f409c66d3..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/model/ExperimentValidator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package eu.hbp.mip.model;
-
-import java.util.List;
-
-/**
- * Created by mirco on 09.11.16.
- */
-
-public class ExperimentValidator {
-
-    private String code;
-    private String name;
-
-    private List<AlgorithmParam> parameters;
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public List<AlgorithmParam> getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(List<AlgorithmParam> parameters) {
-        this.parameters = parameters;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/model/MiningQuery.java b/src/main/java/eu/hbp/mip/model/MiningQuery.java
index 6ced265037ba4148d4f18e6ba06d9434e4610317..171c55032eee4b3c5f63d636c137d6ae41bfe051 100644
--- a/src/main/java/eu/hbp/mip/model/MiningQuery.java
+++ b/src/main/java/eu/hbp/mip/model/MiningQuery.java
@@ -1,6 +1,7 @@
 package eu.hbp.mip.model;
 
 import com.google.gson.Gson;
+
 import java.util.LinkedList;
 import java.util.List;
 
@@ -14,7 +15,7 @@ public class MiningQuery {
     private List<Variable> grouping;
     private List<Variable> datasets;
     private String filters;
-    private Algorithm algorithm;
+    private ExperimentExecutionDTO.AlgorithmExecutionDTO algorithm;
 
     public MiningQuery() {
         this.variables = new LinkedList<>();
@@ -32,7 +33,9 @@ public class MiningQuery {
         this.variables = variables;
     }
 
-    public  void addVariable(Variable variable) { this.variables.add(variable); }
+    public void addVariable(Variable variable) {
+        this.variables.add(variable);
+    }
 
     public List<Variable> getCovariables() {
         return covariables;
@@ -42,7 +45,9 @@ public class MiningQuery {
         this.covariables = covariables;
     }
 
-    public  void addCovariable(Variable variable) { this.covariables.add(variable); }
+    public void addCovariable(Variable variable) {
+        this.covariables.add(variable);
+    }
 
     public List<Variable> getGrouping() {
         return grouping;
@@ -52,15 +57,21 @@ public class MiningQuery {
         this.grouping = grouping;
     }
 
-    public List<Variable> getDatasets() { return datasets; }
+    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 addDataset(Variable variable) {
+        this.datasets.add(variable);
+    }
 
-    public  void addGrouping(Variable variable) { this.grouping.add(variable); }
+    public void addGrouping(Variable variable) {
+        this.grouping.add(variable);
+    }
 
     public String getFilters() {
         return filters;
@@ -70,11 +81,11 @@ public class MiningQuery {
         this.filters = filters;
     }
 
-    public Algorithm getAlgorithm() {
+    public ExperimentExecutionDTO.AlgorithmExecutionDTO getAlgorithm() {
         return algorithm;
     }
 
-    public void setAlgorithm(Algorithm algorithm) {
+    public void setAlgorithm(ExperimentExecutionDTO.AlgorithmExecutionDTO algorithm) {
         this.algorithm = algorithm;
     }
 
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/ErrorResponse.java b/src/main/java/eu/hbp/mip/model/galaxy/ErrorResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..77a171358b54561e3492dcb317acd835aeaa645f
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/galaxy/ErrorResponse.java
@@ -0,0 +1,50 @@
+/*
+ * Developed by Kechagias Konstantinos.
+ * Copyright (c) 2019. MIT License
+ */
+
+package eu.hbp.mip.model.galaxy;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ErrorResponse {
+
+    @SerializedName("result")
+    List<ErrorMessage> result;
+
+    public ErrorResponse() {
+    }
+
+    public ErrorResponse(String errMsg) {
+        this.result = new ArrayList<>();
+        this.result.add(new ErrorMessage(errMsg));
+    }
+
+    public static class ErrorMessage {
+
+        @SerializedName("data")
+        String errMsg;
+
+        @SerializedName("type")
+        String errType;
+
+        public ErrorMessage() {
+        }
+
+        public ErrorMessage(String errMsg) {
+            this.errMsg = errMsg;
+            this.errType = "text/plain+error";
+        }
+
+        public String getErrMsg() {
+            return errMsg;
+        }
+
+        public void setErrMsg(String errMsg) {
+            this.errMsg = errMsg;
+        }
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/GalaxyWorkflowResult.java b/src/main/java/eu/hbp/mip/model/galaxy/GalaxyWorkflowResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..089a6a626ed1e0d38306c911b515edd3fa8fa5f0
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/galaxy/GalaxyWorkflowResult.java
@@ -0,0 +1,208 @@
+/*
+ * Developed by Kechagias Konstantinos.
+ * Copyright (c) 2019. MIT License
+ */
+
+package eu.hbp.mip.model.galaxy;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+public class GalaxyWorkflowResult {
+
+    @SerializedName("history_content_type")
+    private String historyContentType;
+    @SerializedName("update_time")
+    private String updateTime;
+    @SerializedName("name")
+    private String name;
+    @SerializedName("extension")
+    private String extension;
+    @SerializedName("type_id")
+    private String typeId;
+    @SerializedName("deleted")
+    private Boolean deleted;
+    @SerializedName("history_id")
+    private String historyId;
+    @SerializedName("tags")
+    private List<Object> tags = null;
+    @SerializedName("id")
+    private String id;
+    @SerializedName("visible")
+    private Boolean visible;
+    @SerializedName("state")
+    private String state;
+    @SerializedName("create_time")
+    private String createTime;
+    @SerializedName("hid")
+    private Integer hid;
+    @SerializedName("url")
+    private String url;
+    @SerializedName("dataset_id")
+    private String datasetId;
+    @SerializedName("type")
+    private String type;
+    @SerializedName("purged")
+    private Boolean purged;
+
+    public GalaxyWorkflowResult() {
+    }
+
+    public GalaxyWorkflowResult(String historyContentType, String updateTime, String name, String extension, String typeId, Boolean deleted, String historyId, List<Object> tags, String id, Boolean visible, String state, String createTime, Integer hid, String url, String datasetId, String type, Boolean purged) {
+        this.historyContentType = historyContentType;
+        this.updateTime = updateTime;
+        this.name = name;
+        this.extension = extension;
+        this.typeId = typeId;
+        this.deleted = deleted;
+        this.historyId = historyId;
+        this.tags = tags;
+        this.id = id;
+        this.visible = visible;
+        this.state = state;
+        this.createTime = createTime;
+        this.hid = hid;
+        this.url = url;
+        this.datasetId = datasetId;
+        this.type = type;
+        this.purged = purged;
+    }
+
+    public String getHistoryContentType() {
+        return historyContentType;
+    }
+
+    public void setHistoryContentType(String historyContentType) {
+        this.historyContentType = historyContentType;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getExtension() {
+        return extension;
+    }
+
+    public void setExtension(String extension) {
+        this.extension = extension;
+    }
+
+    public String getTypeId() {
+        return typeId;
+    }
+
+    public void setTypeId(String typeId) {
+        this.typeId = typeId;
+    }
+
+    public Boolean getDeleted() {
+        return deleted;
+    }
+
+    public void setDeleted(Boolean deleted) {
+        this.deleted = deleted;
+    }
+
+    public String getHistoryId() {
+        return historyId;
+    }
+
+    public void setHistoryId(String historyId) {
+        this.historyId = historyId;
+    }
+
+    public List<Object> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<Object> tags) {
+        this.tags = tags;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Boolean getVisible() {
+        return visible;
+    }
+
+    public void setVisible(Boolean visible) {
+        this.visible = visible;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public Integer getHid() {
+        return hid;
+    }
+
+    public void setHid(Integer hid) {
+        this.hid = hid;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getDatasetId() {
+        return datasetId;
+    }
+
+    public void setDatasetId(String datasetId) {
+        this.datasetId = datasetId;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Boolean getPurged() {
+        return purged;
+    }
+
+    public void setPurged(Boolean purged) {
+        this.purged = purged;
+    }
+}
+
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/PostWorkflowToGalaxyDtoResponse.java b/src/main/java/eu/hbp/mip/model/galaxy/PostWorkflowToGalaxyDtoResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..edefd63266a8d1678bf82d057882e4eccab112cc
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/galaxy/PostWorkflowToGalaxyDtoResponse.java
@@ -0,0 +1,93 @@
+/*
+ * Developed by Kechagias Konstantinos.
+ * Copyright (c) 2019. MIT License
+ */
+
+package eu.hbp.mip.model.galaxy;
+
+import com.google.gson.annotations.SerializedName;
+
+public class PostWorkflowToGalaxyDtoResponse {
+
+
+    @SerializedName("update_time")
+    String updateTime;
+    String uuid;
+    @SerializedName("history_id")
+    String historyId;
+    String stake;
+    @SerializedName("workflow_id")
+    String workflowId;
+    @SerializedName("model_class")
+    String modelClass;
+    String id;
+
+    public PostWorkflowToGalaxyDtoResponse() {
+    }
+
+    public PostWorkflowToGalaxyDtoResponse(String updateTime, String uuid, String historyId, String stake, String workflowId, String modelClass, String id) {
+        this.updateTime = updateTime;
+        this.uuid = uuid;
+        this.historyId = historyId;
+        this.stake = stake;
+        this.workflowId = workflowId;
+        this.modelClass = modelClass;
+        this.id = id;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public String getHistoryId() {
+        return historyId;
+    }
+
+    public void setHistoryId(String historyId) {
+        this.historyId = historyId;
+    }
+
+    public String getStake() {
+        return stake;
+    }
+
+    public void setStake(String stake) {
+        this.stake = stake;
+    }
+
+    public String getWorkflowId() {
+        return workflowId;
+    }
+
+    public void setWorkflowId(String workflowId) {
+        this.workflowId = workflowId;
+    }
+
+    public String getModelClass() {
+        return modelClass;
+    }
+
+    public void setModelClass(String modelClass) {
+        this.modelClass = modelClass;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/model/galaxy/WorkflowDTO.java b/src/main/java/eu/hbp/mip/model/galaxy/WorkflowDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..de537a1dcc4649e0ea6b28ff967567b599c77251
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/galaxy/WorkflowDTO.java
@@ -0,0 +1,162 @@
+package eu.hbp.mip.model.galaxy;
+
+import com.google.gson.Gson;
+import com.google.gson.annotations.SerializedName;
+import eu.hbp.mip.model.AlgorithmDTO;
+
+import java.util.*;
+
+public class WorkflowDTO {
+
+    @SerializedName("id")
+    private String id;
+
+    @SerializedName("name")
+    private String name;
+
+    @SerializedName("inputs")
+    private HashMap<String, WorkflowInputDTO> inputs;
+
+    @SerializedName("steps")
+    private HashMap<String, WorkflowStepDTO> steps;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public HashMap<String, WorkflowInputDTO> getInputs() {
+        return inputs;
+    }
+
+    public void setInputs(HashMap<String, WorkflowInputDTO> inputs) {
+        this.inputs = inputs;
+    }
+
+    public HashMap<String, WorkflowStepDTO> getSteps() {
+        return steps;
+    }
+
+    public void setSteps(HashMap<String, WorkflowStepDTO> steps) {
+        this.steps = steps;
+    }
+
+    public class WorkflowInputDTO {
+        @SerializedName("uuid")
+        private String uuid;
+
+        @SerializedName("label")
+        private String label;
+
+        public String getLabel() {
+            return label;
+        }
+
+        public void setLabel(String label) {
+            this.label = label;
+        }
+
+        public String getUuid() {
+            return uuid;
+        }
+
+        public void setUuid(String uuid) {
+            this.uuid = uuid;
+        }
+    }
+
+    public class WorkflowStepDTO {
+        @SerializedName("id")
+        private int id;
+
+        @SerializedName("type")
+        private String type;
+
+        @SerializedName("annotation")
+        private String annotation;
+
+        public int getId() {
+            return id;
+        }
+
+        public void setId(int id) {
+            this.id = id;
+        }
+
+        public String getAnnotation() {
+            return annotation;
+        }
+
+        public void setAnnotation(String annotation) {
+            this.annotation = annotation;
+        }
+    }
+
+    public AlgorithmDTO convertToAlgorithmDTO(){
+
+        AlgorithmDTO algorithmDTO = new AlgorithmDTO();
+
+        // Transfer workflow information
+        algorithmDTO.setName(id);
+        algorithmDTO.setDesc("");
+        algorithmDTO.setLabel(name);
+        algorithmDTO.setType("workflow");
+
+        // Transfer workflow parameters information
+        List<AlgorithmDTO.AlgorithmParamDTO> algorithmParams = new LinkedList<>();
+        Gson gson = new Gson();
+        for (Map.Entry<String, WorkflowInputDTO> workflowInput : getInputs().entrySet()) {
+
+            // Convert the annotation to algorithm Parameter
+            AlgorithmDTO.AlgorithmParamDTO algorithmParam;
+            if(steps.get(workflowInput.getKey()).getAnnotation() != null) {
+                algorithmParam = gson.fromJson(steps.get(workflowInput.getKey()).getAnnotation(),
+                                AlgorithmDTO.AlgorithmParamDTO.class);
+            }else{
+                // If annotation is not provided, auto-fill some information
+                algorithmParam = new AlgorithmDTO.AlgorithmParamDTO();
+                // When the constraints are not known, set the most relaxed constraints
+                algorithmParam.setDesc("");
+                algorithmParam.setValue("");
+                algorithmParam.setValueType("string");
+                algorithmParam.setValueNotBlank("false");
+                algorithmParam.setDefaultValue("");
+                algorithmParam.setDefaultValue("true");
+                // If label is dataset/pathology/filter/formula the type should be the same
+                if(workflowInput.getValue().getLabel().equals("dataset") ||
+                        workflowInput.getValue().getLabel().equals("pathology")||
+                        workflowInput.getValue().getLabel().equals("filter")||
+                        workflowInput.getValue().getLabel().equals("formula")){
+                    algorithmParam.setType(workflowInput.getValue().getLabel());
+                }else if(workflowInput.getValue().getLabel().equals("x") ||
+                        workflowInput.getValue().getLabel().equals("y")){
+                    algorithmParam.setType("column");
+                    algorithmParam.setColumnValuesSQLType("text,real,integer");
+                    algorithmParam.setColumnValuesIsCategorical("");
+                }else{
+                    algorithmParam.setType("other");
+                }
+            }
+            // Set the name to the workflow id
+            algorithmParam.setName(workflowInput.getValue().getUuid());
+            algorithmParam.setLabel(workflowInput.getValue().getLabel());
+
+            algorithmParams.add(algorithmParam);
+        }
+        algorithmDTO.setParameters(algorithmParams);
+
+        return algorithmDTO;
+    }
+
+}
diff --git a/src/main/java/eu/hbp/mip/utils/JWTUtil.java b/src/main/java/eu/hbp/mip/utils/JWTUtil.java
deleted file mode 100644
index 1e74841842150aef10778726040b88a53d14d218..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/utils/JWTUtil.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package eu.hbp.mip.utils;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import com.auth0.jwt.algorithms.Algorithm;
-import com.auth0.jwt.JWT;
-
-public class JWTUtil {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(JWT.class);
-
-    public static String getJWT(String secret, String subject) {
-        LOGGER.info("getJWT");
-        Algorithm algorithm = Algorithm.HMAC512(secret);
-        String token = JWT.create().withIssuer("mip.humanbrainproject.eu").withSubject(subject).sign(algorithm);
-
-        return token;
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/utils/UserActionLogging.java b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
index 745fc24a6ca53951c1f43cd9db2f6fa5965a73d4..b4a96fc864a16063c39dede8ea0233fbfd41b981 100644
--- a/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
+++ b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
@@ -4,8 +4,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.context.SecurityContextHolder;
 
-import java.time.LocalTime;
-
 public class UserActionLogging {
 
 
@@ -13,11 +11,15 @@ public class UserActionLogging {
 
     public static void LogAction(String actionName, String actionIdInfo)
     {
-        LOGGER.info( LocalTime.now()+" User : "
+        LOGGER.info( " User : "
                 + SecurityContextHolder.getContext().getAuthentication().getName()
-                + " called enpoint " + actionName
-                + " info "
-                + actionIdInfo);
+                + " called endpoint: " + actionName
+                + " info: " + actionIdInfo);
     }
 
+    // Used from Threads because LogAction won't work.
+    public static void LogThreadAction(String actionName, String actionIdInfo)
+    {
+        LOGGER.info( "Thread -->" + actionName + " info: " + actionIdInfo);
+    }
 }
diff --git a/src/main/resources/db/migration/V6_0__AddWorkflowDetails.sql b/src/main/resources/db/migration/V6_0__AddWorkflowDetails.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0e508b0efda4aa4842ebc9ff52d3b688761aca5b
--- /dev/null
+++ b/src/main/resources/db/migration/V6_0__AddWorkflowDetails.sql
@@ -0,0 +1,2 @@
+ALTER TABLE experiment ADD COLUMN workflowhistoryid text;
+ALTER TABLE experiment ADD COLUMN workflowstatus text;
\ No newline at end of file