diff --git a/docker/README.md b/docker/README.md
index 36a3e1245c7b0ffce433854dc7b7678f8644bd3f..8693aad09f765b12de66b77c37f700563fa4eec7 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -24,7 +24,7 @@ To use this image, you need a running instance of PostgreSQL and to configure th
 
 
 ### EXTERNAL SERVICES ###
-* MIPENGINE_URL: URL to MIPENGINE server. Default is "http://192.168.124.129:5000" .
+* MIPENGINE_URL: URL to MIPENGINE server. Default is "http://localhost:5000" .
 
 * EXAREME_URL: URL to Exareme server. Default is "http://localhost:9090" .
 
diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl
index 6059a902be06193d8a57c3c72f5c820d66e1b7ff..a8bfdf9ff3d49b00668dc9b3e8b581dd054180a6 100644
--- a/docker/config/application.tmpl
+++ b/docker/config/application.tmpl
@@ -35,7 +35,7 @@ spring:
 ### EXTERNAL SERVICES ###
 services:
   mipengine:
-    algorithmsUrl: {{ default .Env.MIPENGINE_URL "http://192.168.124.129:5000" }}/algorithms
+    algorithmsUrl: {{ .Env.MIPENGINE_URL}}/algorithms
 
   exareme:
     queryExaremeUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/query
diff --git a/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java
index aea67b056981111fceede22ce964adab2ae7f57d..5ac49a402094cf3c435537ddf95f60d162dbbd46 100644
--- a/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java
+++ b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java
@@ -76,17 +76,17 @@ public class AlgorithmsAPI {
         logger.LogUserAction("Loaded " + galaxyAlgorithms.size() + " galaxy algorithms");
 
         ArrayList<ExaremeAlgorithmDTO> algorithms = new ArrayList<>();
-        if (!exaremeAlgorithms.isEmpty()) {
+        if (exaremeAlgorithms != null) {
             algorithms.addAll(exaremeAlgorithms);
         } else {
             logger.LogUserAction("Getting exareme algorithms failed and returned null");
         }
-        if (!mipengineAlgorithms.isEmpty()) {
+        if (mipengineAlgorithms != null) {
             algorithms.addAll(mipengineAlgorithms);
         } else {
             logger.LogUserAction("Getting mipengine algorithms failed and returned null");
         }
-        if (!galaxyAlgorithms.isEmpty()) {
+        if (galaxyAlgorithms != null) {
             algorithms.addAll(galaxyAlgorithms);
         } else {
             logger.LogUserAction("Getting galaxy workflows failed and returned null");
@@ -159,7 +159,7 @@ public class AlgorithmsAPI {
         }
 
         ArrayList<ExaremeAlgorithmDTO> algorithms = new ArrayList<>();
-        mipEngineAlgorithms.forEach(mipEngineAlgorithm -> algorithms.add(mipEngineAlgorithm.convertToAlgorithmDTO()));
+        mipEngineAlgorithms.forEach(mipEngineAlgorithm -> algorithms.add(new ExaremeAlgorithmDTO(mipEngineAlgorithm)));
 
         logger.LogUserAction("Completed, returned " + algorithms.size() + " algorithms.");
         return algorithms;
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java b/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java
index e5d0b04c54b0fd8652f5d284cb8690eaf14d3acf..449765fc999b0a9187d58446ca5dfc9695bf321d 100644
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentAPI.java
@@ -78,6 +78,7 @@ public class ExperimentAPI {
     @ApiOperation(value = "Create an experiment", response = ExperimentDTO.class)
     @RequestMapping(method = RequestMethod.POST)
     public ResponseEntity<String> createExperiment(Authentication authentication, @RequestBody ExperimentDTO experimentDTO) {
+        new Logger(activeUserService.getActiveUser().getUsername(),"(POST) /experiments").LogUserAction("TEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEST");
         experimentDTO = experimentService.createExperiment(authentication, experimentDTO, new Logger(activeUserService.getActiveUser().getUsername(),"(POST) /experiments"));
         return new ResponseEntity<>(JsonConverters.convertObjectToJsonString(experimentDTO), HttpStatus.CREATED);
     }
@@ -103,6 +104,7 @@ public class ExperimentAPI {
     @ApiOperation(value = "Create a transient experiment", response = ExperimentDTO.class)
     @RequestMapping(value = "/transient", method = RequestMethod.POST)
     public ResponseEntity<String> createTransientExperiment(Authentication authentication, @RequestBody ExperimentDTO experimentDTO) {
+        new Logger(activeUserService.getActiveUser().getUsername(),"(POST) /experiments").LogUserAction("TEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEST");
         experimentDTO = experimentService.createTransientExperiment(authentication, experimentDTO, new Logger(activeUserService.getActiveUser().getUsername(), "(POST) /experiments/transient"));
         return new ResponseEntity<>(JsonConverters.convertObjectToJsonString(experimentDTO), HttpStatus.OK);
     }
diff --git a/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java b/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java
index 4e206fae0d3605e6b0ffcaab5fded486eef25d45..8eb343c9cc658b97e8f0c1a1b6a7be19f09c9c94 100644
--- a/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java
+++ b/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java
@@ -3,12 +3,9 @@ package eu.hbp.mip.models.DAOs;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
-import eu.hbp.mip.models.DTOs.ExaremeAlgorithmDTO;
-import eu.hbp.mip.models.DTOs.ExperimentDTO;
-import eu.hbp.mip.utils.JsonConverters;
 import io.swagger.annotations.ApiModel;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
 import javax.persistence.*;
 import java.util.*;
@@ -17,8 +14,8 @@ import java.util.*;
  * Created by habfast on 21/04/16.
  */
 @Entity
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 @Table(name = "`experiment`")
 @ApiModel
 @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -95,22 +92,4 @@ public class ExperimentDAO {
          */
     }
 
-    public ExperimentDTO convertToDTO(boolean includeResult)
-    {
-        ExperimentDTO experimentDTO = new ExperimentDTO();
-        experimentDTO.setAlgorithm(JsonConverters.convertJsonStringToObject(this.algorithm, ExaremeAlgorithmDTO.class));
-        experimentDTO.setCreated(this.created);
-        experimentDTO.setUpdated(this.updated);
-        experimentDTO.setFinished(this.finished);
-        experimentDTO.setCreatedBy(this.createdBy.getUsername());
-        experimentDTO.setName(this.name);
-        if(includeResult){
-            experimentDTO.setResult(JsonConverters.convertJsonStringToObject(String.valueOf(this.result),  new ArrayList<>().getClass()));
-        }
-        experimentDTO.setStatus(this.status);
-        experimentDTO.setShared(this.shared);
-        experimentDTO.setUuid(this.uuid);
-        experimentDTO.setViewed(this.viewed);
-        return experimentDTO;
-    }
 }
diff --git a/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java b/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java
index 9279b3793c44c449302c083b823da674d7e4d46f..3bb43f3eec865cc92cd1be4e97fdf660d90e3089 100644
--- a/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java
+++ b/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java
@@ -7,16 +7,16 @@ package eu.hbp.mip.models.DAOs;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.google.gson.annotations.Expose;
 import io.swagger.annotations.ApiModel;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Table;
 
 @Entity
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 @Table(name = "`user`")
 @ApiModel
 @JsonInclude(JsonInclude.Include.NON_NULL)
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmDTO.java
index 887733de88a395d9c5f7a31b5c55c32024b56312..584ffd424f4c691a168cd26b3b8b1fa2566658bf 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmDTO.java
@@ -1,15 +1,13 @@
 package eu.hbp.mip.models.DTOs;
 
 import com.google.gson.annotations.SerializedName;
-import eu.hbp.mip.utils.JsonConverters;
 import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.Data;
 
 import java.util.*;
 
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 public class ExaremeAlgorithmDTO {
 
     @SerializedName("name")
@@ -27,9 +25,30 @@ public class ExaremeAlgorithmDTO {
     @SerializedName("parameters")
     private List<ExaremeAlgorithmRequestParamDTO> parameters;
 
+    public ExaremeAlgorithmDTO()
+    {
+
+    }
 
-    @Getter
-    @Setter
+    public ExaremeAlgorithmDTO(MIPEngineAlgorithmDTO mipEngineAlgorithm )
+    {
+        this.name = mipEngineAlgorithm.getName().toUpperCase();
+        this.label = mipEngineAlgorithm.getLabel();
+        this.desc = mipEngineAlgorithm.getDesc();
+        this.type = "mipengine";
+        List<ExaremeAlgorithmRequestParamDTO> parameters = new ArrayList<>();
+        parameters.add(new ExaremeAlgorithmRequestParamDTO("x", mipEngineAlgorithm.getInputdata().getX()));
+        parameters.add(new ExaremeAlgorithmRequestParamDTO("y", mipEngineAlgorithm.getInputdata().getY()));
+        parameters.add(new ExaremeAlgorithmRequestParamDTO("pathology", mipEngineAlgorithm.getInputdata().getPathology()));
+        parameters.add(new ExaremeAlgorithmRequestParamDTO("dataset", mipEngineAlgorithm.getInputdata().getDatasets()));
+        parameters.add(new ExaremeAlgorithmRequestParamDTO("filter", mipEngineAlgorithm.getInputdata().getFilter()));
+        mipEngineAlgorithm.getParameters().forEach((name, parameterDTO) -> {
+            ExaremeAlgorithmRequestParamDTO parameter = new ExaremeAlgorithmRequestParamDTO(name, parameterDTO);
+            parameters.add(parameter);
+        });
+        this.setParameters(parameters);
+    }
+    @Data
     @AllArgsConstructor
     static class Rule
     {
@@ -45,47 +64,4 @@ public class ExaremeAlgorithmDTO {
         @SerializedName("value")
         private Object value;
     }
-    public MIPEngineAlgorithmRequestDTO convertToMIPEngineBody()
-    {
-        MIPEngineAlgorithmRequestDTO mipEngineAlgorithmRequestDTO = new MIPEngineAlgorithmRequestDTO();
-        MIPEngineAlgorithmRequestDTO.InputData inputData = new MIPEngineAlgorithmRequestDTO.InputData();
-        HashMap<String, Object> mipEngineParameters = new HashMap<>();
-
-        List<Object> rules = new ArrayList<>();
-        this.parameters.forEach(parameter -> {
-
-            switch (parameter.getName()) {
-                case "x":
-                    List<String> x = Arrays.asList(parameter.getValue().split(","));
-                    x.forEach(column -> rules.add(new Rule(column, parameter.getColumnValuesSQLType(), "is_not_null", null)));
-                    inputData.setX(x);
-                    break;
-                case "y":
-                    List<String> y = Arrays.asList(parameter.getValue().split(","));
-                    y.forEach(column -> rules.add(new Rule(column, parameter.getColumnValuesSQLType(), "is_not_null", null)));
-                    inputData.setY(y);
-                    break;
-                case "dataset":
-                    List<String> datasets = Arrays.asList(parameter.getValue().split(","));
-                    rules.add(new Rule("dataset", "string", "in", datasets));
-                    inputData.setDatasets(datasets);
-                    break;
-                case "pathology":
-                    inputData.setPathology(parameter.getValue());
-                    break;
-                case "filter":
-                    if (!parameter.getValue().equals(""))
-                        rules.add(JsonConverters.convertJsonStringToObject(parameter.getValue(), MIPEngineAlgorithmRequestDTO.Filter.class));
-                    break;
-                default:
-                    mipEngineParameters.put(parameter.getName(), Arrays.asList(parameter.getValue().split(",")));
-                    break;
-            }
-        });
-        MIPEngineAlgorithmRequestDTO.Filter filter = new MIPEngineAlgorithmRequestDTO.Filter("AND", rules, true);
-        inputData.setFilters(filter);
-        mipEngineAlgorithmRequestDTO.setInputdata(inputData);
-        mipEngineAlgorithmRequestDTO.setParameters(mipEngineParameters);
-        return mipEngineAlgorithmRequestDTO;
-    }
 }
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmRequestParamDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmRequestParamDTO.java
index 6f7d21655c0e5fb7cb8eea1f5bcded5183de55b8..4109c5e5916b65c0b1af9f0eaed04aa96249c640 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmRequestParamDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmRequestParamDTO.java
@@ -1,14 +1,16 @@
 package eu.hbp.mip.models.DTOs;
 
 import com.google.gson.annotations.SerializedName;
-import lombok.Getter;
-import lombok.Setter;
+import eu.hbp.mip.utils.Exceptions.InternalServerError;
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
+import java.util.Arrays;
 import java.util.List;
 
 //The request of an exareme algorithm is a list of ExaremeAlgorithmRequestParamDTOs.
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 public class ExaremeAlgorithmRequestParamDTO {
     @SerializedName("name")
     private String name;
@@ -51,4 +53,54 @@ public class ExaremeAlgorithmRequestParamDTO {
 
     @SerializedName("valueEnumerations")
     private List<String> valueEnumerations;
+    public ExaremeAlgorithmRequestParamDTO (){}
+
+    public ExaremeAlgorithmRequestParamDTO (String name, MIPEngineAlgorithmDTO.MIPEngineAlgorithmParameterDTO parameter){
+        this.name = name;
+        this.desc = parameter.getDesc();
+        this.valueType = parameter.getType();
+        this.type = "other";
+        this.defaultValue = parameter.getDefault_value();
+        this.valueNotBlank = parameter.getNotblank();
+        this.label = parameter.getLabel();
+        this.valueEnumerations = parameter.getEnums();
+        this.valueMultiple = parameter.getMultiple();
+        this.valueMax = parameter.getMin();
+        this.valueMin = parameter.getMax();
+    }
+
+    public ExaremeAlgorithmRequestParamDTO (String name, MIPEngineAlgorithmDTO.MIPEngineAlgorithmInputDataDetailDTO inputDataDetail){
+        this.name = name;
+        this.desc = inputDataDetail.getDesc();
+        this.value = "";
+        this.valueNotBlank = inputDataDetail.getNotblank();
+        this.valueMultiple = inputDataDetail.getMultiple();
+        String[] hidden = {"x","y","dataset", "filter","pathology","centers","formula"};
+        this.label = (Arrays.asList(hidden).contains(this.name) ? this.name : inputDataDetail.getLabel());
+        if(name.equals("dataset") || name.equals("filter") || name.equals("pathology")){
+            this.valueType = inputDataDetail.getTypes().get(0);
+            this.type = this.name;
+        }
+        else{
+            this.type = "column";
+            this.columnValuesSQLType = String.join(", ", inputDataDetail.getTypes());
+            this.columnValuesIsCategorical = getColumnValuesIsCategorical(inputDataDetail.getStattypes());
+        }
+    }
+
+    private String getColumnValuesIsCategorical(List<String> stattypes){
+
+        if (stattypes.contains("nominal") && stattypes.contains("numerical")){
+            return "";
+        }
+        else if (stattypes.contains("nominal")){
+            return "true";
+        }
+        else if (stattypes.contains("numerical")){
+            return "false";
+        }
+        else{
+            throw new InternalServerError("Invalid stattypes");
+        }
+    }
 }
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmResultDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmResultDTO.java
index ca556bb7341c838271c03cd1d75249d2fba59f37..d1f5947c889c6581b341e4561e0c65e336f980ff 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmResultDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/ExaremeAlgorithmResultDTO.java
@@ -1,13 +1,11 @@
 package eu.hbp.mip.models.DTOs;
 
 import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.Data;
 
 import java.util.List;
 
-@Getter
-@Setter
+@Data
 @AllArgsConstructor
 public class ExaremeAlgorithmResultDTO {
     private int code;
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java
index 765c20144a3a376124d717980acff6dd8991543a..0dd28c1d6c4fde45164d9077aa5c9be3c90f57fb 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/ExperimentDTO.java
@@ -2,15 +2,17 @@ package eu.hbp.mip.models.DTOs;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import eu.hbp.mip.models.DAOs.ExperimentDAO;
-import lombok.Getter;
-import lombok.Setter;
+import eu.hbp.mip.utils.JsonConverters;
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 @JsonInclude(JsonInclude.Include.NON_NULL)
 public class ExperimentDTO {
 
@@ -30,4 +32,23 @@ public class ExperimentDTO {
     private ExperimentDAO.Status status;
     private ExaremeAlgorithmDTO algorithm;
 
+    public ExperimentDTO(){
+
+    }
+    public ExperimentDTO(boolean includeResult, ExperimentDAO experimentDAO)
+    {
+        this.algorithm = JsonConverters.convertJsonStringToObject(experimentDAO.getAlgorithm(), ExaremeAlgorithmDTO.class);
+        this.created = experimentDAO.getCreated();
+        this.updated = experimentDAO.getUpdated();
+        this.finished = experimentDAO.getFinished();
+        this.createdBy = experimentDAO.getCreatedBy().getUsername();
+        this.name = experimentDAO.getName();
+        if(includeResult){
+            this.result = JsonConverters.convertJsonStringToObject(String.valueOf(experimentDAO.getResult()),  new ArrayList<>().getClass());
+        }
+        this.status = experimentDAO.getStatus();
+        this.uuid = experimentDAO.getUuid();
+        this.shared = experimentDAO.isShared();
+        this.viewed = experimentDAO.isViewed();
+    }
 }
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmDTO.java
index 98677991e486e2fca38b8c7688a0d77e6eec084c..5edfbfe77827179234caf339f3f627235f72e967 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmDTO.java
@@ -1,17 +1,14 @@
 package eu.hbp.mip.models.DTOs;
 
 import com.google.gson.annotations.SerializedName;
-import eu.hbp.mip.utils.Exceptions.InternalServerError;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Hashtable;
 import java.util.List;
 
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 public class MIPEngineAlgorithmDTO {
 
     @SerializedName("name")
@@ -27,17 +24,17 @@ public class MIPEngineAlgorithmDTO {
     private String type;
 
     @SerializedName("parameters")
-    private Hashtable<String, ParameterDTO> parameters;
+    private Hashtable<String, MIPEngineAlgorithmParameterDTO> parameters;
 
     @SerializedName("crossvalidation")
     private String crossvalidation;
 
     @SerializedName("inputdata")
-    private InputdataDTO inputdata;
+    private MIPEngineAlgorithmInputdataDTO inputdata;
 
-    @Getter
-    @Setter
-    public static class ParameterDTO {
+    @Data
+    @AllArgsConstructor
+    public static class MIPEngineAlgorithmParameterDTO {
 
         @SerializedName("label")
         private String label;
@@ -65,56 +62,30 @@ public class MIPEngineAlgorithmDTO {
 
         @SerializedName("enums")
         private List<String> enums;
-
-        public ExaremeAlgorithmRequestParamDTO convertToexaremeAlgorithmRequestDTO(String name){
-            ExaremeAlgorithmRequestParamDTO exaremeAlgorithmRequestParamDTO = new ExaremeAlgorithmRequestParamDTO();
-            exaremeAlgorithmRequestParamDTO.setName(name);
-            exaremeAlgorithmRequestParamDTO.setDesc(this.desc);
-            exaremeAlgorithmRequestParamDTO.setValueType(this.type);
-            exaremeAlgorithmRequestParamDTO.setType("other");
-            exaremeAlgorithmRequestParamDTO.setDefaultValue(this.default_value);
-            exaremeAlgorithmRequestParamDTO.setValueNotBlank(this.notblank);
-            exaremeAlgorithmRequestParamDTO.setLabel(this.label);
-            exaremeAlgorithmRequestParamDTO.setValueEnumerations(this.enums);
-            exaremeAlgorithmRequestParamDTO.setValueMultiple(this.multiple);
-            exaremeAlgorithmRequestParamDTO.setValueMin(this.min);
-            exaremeAlgorithmRequestParamDTO.setValueMax(this.max);
-            return exaremeAlgorithmRequestParamDTO;
-        }
     }
 
-    @Getter
-    @Setter
-    public static class InputdataDTO {
+    @Data
+    @AllArgsConstructor
+    public static class MIPEngineAlgorithmInputdataDTO {
         @SerializedName("x")
-        private InputDataDetailDTO x;
+        private MIPEngineAlgorithmInputDataDetailDTO x;
 
         @SerializedName("y")
-        private InputDataDetailDTO y;
+        private MIPEngineAlgorithmInputDataDetailDTO y;
 
         @SerializedName("pathology")
-        private InputDataDetailDTO pathology;
+        private MIPEngineAlgorithmInputDataDetailDTO pathology;
 
         @SerializedName("datasets")
-        private InputDataDetailDTO datasets;
+        private MIPEngineAlgorithmInputDataDetailDTO datasets;
 
         @SerializedName("filter")
-        private InputDataDetailDTO filter;
-
-        public List<ExaremeAlgorithmRequestParamDTO> convertToAlgorithmRequestParamDTOs(){
-            List<ExaremeAlgorithmRequestParamDTO> exaremeAlgorithmRequestParamDTOS = new ArrayList<>();
-            exaremeAlgorithmRequestParamDTOS.add(this.x.convertToExaremeAlgorithmRequestDTO("x"));
-            exaremeAlgorithmRequestParamDTOS.add(this.y.convertToExaremeAlgorithmRequestDTO("y"));
-            exaremeAlgorithmRequestParamDTOS.add(this.pathology.convertToExaremeAlgorithmRequestDTO("pathology"));
-            exaremeAlgorithmRequestParamDTOS.add(this.datasets.convertToExaremeAlgorithmRequestDTO("dataset"));
-            exaremeAlgorithmRequestParamDTOS.add(this.filter.convertToExaremeAlgorithmRequestDTO("filter"));
-            return exaremeAlgorithmRequestParamDTOS;
-        }
+        private MIPEngineAlgorithmInputDataDetailDTO filter;
     }
 
-    @Getter
-    @Setter
-    public static class InputDataDetailDTO {
+    @Data
+    @AllArgsConstructor
+    public static class MIPEngineAlgorithmInputDataDetailDTO {
 
         @SerializedName("stattypes")
         private List<String> stattypes;
@@ -136,58 +107,5 @@ public class MIPEngineAlgorithmDTO {
 
         @SerializedName("desc")
         private String desc;
-
-        public ExaremeAlgorithmRequestParamDTO convertToExaremeAlgorithmRequestDTO(String name){
-            ExaremeAlgorithmRequestParamDTO exaremeAlgorithmRequestParamDTO = new ExaremeAlgorithmRequestParamDTO();
-            exaremeAlgorithmRequestParamDTO.setName(name);
-            exaremeAlgorithmRequestParamDTO.setDesc(this.desc);
-            exaremeAlgorithmRequestParamDTO.setValue("");
-            exaremeAlgorithmRequestParamDTO.setValueNotBlank(this.notblank);
-            exaremeAlgorithmRequestParamDTO.setValueMultiple(this.multiple);
-            String[] hidden = {"x","y","dataset", "filter","pathology","centers","formula"};
-            exaremeAlgorithmRequestParamDTO.setLabel(Arrays.asList(hidden).contains(exaremeAlgorithmRequestParamDTO.getName()) ? exaremeAlgorithmRequestParamDTO.getName():this.label);
-            if(name.equals("dataset") || name.equals("filter") || name.equals("pathology")){
-                exaremeAlgorithmRequestParamDTO.setValueType(this.types.get(0));
-                exaremeAlgorithmRequestParamDTO.setType(exaremeAlgorithmRequestParamDTO.getName());
-            }
-            else{
-                exaremeAlgorithmRequestParamDTO.setType("column");
-                exaremeAlgorithmRequestParamDTO.setColumnValuesSQLType(String.join(", ", this.types));
-                exaremeAlgorithmRequestParamDTO.setColumnValuesIsCategorical(getColumnValuesIsCategorical(this.stattypes));
-            }
-            return exaremeAlgorithmRequestParamDTO;
-        }
-
-        private String getColumnValuesIsCategorical(List<String> stattypes){
-
-            if (stattypes.contains("nominal") && stattypes.contains("numerical")){
-                return "";
-            }
-            else if (stattypes.contains("nominal")){
-                return "true";
-            }
-            else if (stattypes.contains("numerical")){
-                return "false";
-            }
-            else{
-                throw new InternalServerError("Invalid stattypes");
-            }
-        }
-    }
-
-    public ExaremeAlgorithmDTO convertToAlgorithmDTO()
-    {
-        ExaremeAlgorithmDTO exaremeAlgorithmDTO = new ExaremeAlgorithmDTO();
-        exaremeAlgorithmDTO.setName(this.name.toUpperCase());
-        exaremeAlgorithmDTO.setLabel(this.label);
-        exaremeAlgorithmDTO.setDesc(this.desc);
-        exaremeAlgorithmDTO.setType("mipengine");
-        List<ExaremeAlgorithmRequestParamDTO> parameters = new ArrayList<>(this.inputdata.convertToAlgorithmRequestParamDTOs());
-        this.parameters.forEach((name, parameterDTO) -> {
-            ExaremeAlgorithmRequestParamDTO parameter = parameterDTO.convertToexaremeAlgorithmRequestDTO(name);
-            parameters.add(parameter);
-        });
-        exaremeAlgorithmDTO.setParameters(parameters);
-        return exaremeAlgorithmDTO;
     }
 }
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmRequestDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmRequestDTO.java
index ff8229e372ddd480d58aee2a5c3af36b9536a41f..a5604f2e7b9b619d023523535c636531c139f937 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmRequestDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmRequestDTO.java
@@ -1,23 +1,68 @@
 package eu.hbp.mip.models.DTOs;
 
 import com.google.gson.annotations.SerializedName;
+import eu.hbp.mip.utils.JsonConverters;
 import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.Data;
 
-import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 public class MIPEngineAlgorithmRequestDTO {
     @SerializedName("inputdata")
     private InputData inputdata;
     @SerializedName("parameters")
-    private Hashtable<String, Object> parameters;
+    private HashMap<String, Object> parameters;
 
-    @Getter
-    @Setter
+    public MIPEngineAlgorithmRequestDTO(List<ExaremeAlgorithmRequestParamDTO> exaremeAlgorithmRequestParamDTOs)
+    {
+        MIPEngineAlgorithmRequestDTO.InputData inputData = new MIPEngineAlgorithmRequestDTO.InputData();
+        HashMap<String, Object> mipEngineParameters = new HashMap<>();
+
+        List<Object> rules = new ArrayList<>();
+        exaremeAlgorithmRequestParamDTOs.forEach(parameter -> {
+
+            switch (parameter.getName()) {
+                case "x":
+                    List<String> x = Arrays.asList(parameter.getValue().split(","));
+                    x.forEach(column -> rules.add(new ExaremeAlgorithmDTO.Rule(column, parameter.getColumnValuesSQLType(), "is_not_null", null)));
+                    inputData.setX(x);
+                    break;
+                case "y":
+                    List<String> y = Arrays.asList(parameter.getValue().split(","));
+                    y.forEach(column -> rules.add(new ExaremeAlgorithmDTO.Rule(column, parameter.getColumnValuesSQLType(), "is_not_null", null)));
+                    inputData.setY(y);
+                    break;
+                case "dataset":
+                    List<String> datasets = Arrays.asList(parameter.getValue().split(","));
+                    rules.add(new ExaremeAlgorithmDTO.Rule("dataset", "string", "in", datasets));
+                    inputData.setDatasets(datasets);
+                    break;
+                case "pathology":
+                    inputData.setPathology(parameter.getValue());
+                    break;
+                case "filter":
+                    if (!parameter.getValue().equals(""))
+                        rules.add(JsonConverters.convertJsonStringToObject(parameter.getValue(), MIPEngineAlgorithmRequestDTO.Filter.class));
+                    break;
+                default:
+                    mipEngineParameters.put(parameter.getName(), Arrays.asList(parameter.getValue().split(",")));
+                    break;
+            }
+        });
+        MIPEngineAlgorithmRequestDTO.Filter filter = new MIPEngineAlgorithmRequestDTO.Filter("AND", rules);
+        inputData.setFilters(filter);
+        this.inputdata = inputData;
+        this.parameters = mipEngineParameters;
+    }
+
+
+    @Data
+    @AllArgsConstructor
     public static class InputData {
         @SerializedName("pathology")
         private String pathology;
@@ -29,10 +74,12 @@ public class MIPEngineAlgorithmRequestDTO {
         private List<String> x;
         @SerializedName("y")
         private List<String> y;
+        public InputData(){
+
+        }
     }
 
-    @Getter
-    @Setter
+    @Data
     @AllArgsConstructor
     public static class Filter
     {
@@ -41,8 +88,5 @@ public class MIPEngineAlgorithmRequestDTO {
 
         @SerializedName("rules")
         private List<Object> rules;
-
-        @SerializedName("valid")
-        private boolean valid;
     }
 }
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmResultDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmResultDTO.java
index 087adb1f84072ba0188d0b8e300ba0d5ee535e20..4491ddb443ddaba506e3165ab95c0e2ba3e20d87 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmResultDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineAlgorithmResultDTO.java
@@ -1,23 +1,14 @@
 package eu.hbp.mip.models.DTOs;
 
 import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.Data;
 
-import java.util.HashMap;
 import java.util.List;
 
-@Getter
-@Setter
+@Data
 @AllArgsConstructor
 public class MIPEngineAlgorithmResultDTO {
     private final String title;
-    private final List<MIPEngineTabularVisualizationDTO.Field> columns;
+    private final List<TabularVisualizationDTO.Field> columns;
     private final List<List<Object>> data;
-
-    public MIPEngineTabularVisualizationDTO convertToVisualization() {
-        HashMap<String, List<MIPEngineTabularVisualizationDTO.Field>> schema = new HashMap<>();
-        schema.put("fields", columns);
-        return new MIPEngineTabularVisualizationDTO(this.title, "tabular-data-resource", schema, this.data);
-    }
 }
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineTabularVisualizationDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineTabularVisualizationDTO.java
deleted file mode 100644
index 7be3fad336e3bf4642f09c6985909d38fb2c4abc..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/models/DTOs/MIPEngineTabularVisualizationDTO.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package eu.hbp.mip.models.DTOs;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.util.HashMap;
-import java.util.List;
-
-@Getter
-@Setter
-@AllArgsConstructor
-public class MIPEngineTabularVisualizationDTO {
-    private final String name;
-    private final String profile;
-    private final HashMap<String, List<Field>> schema;
-    private final List<List<Object>> data;
-
-    @Getter
-    @Setter
-    @AllArgsConstructor
-    public static class Field {
-        private final String name;
-        private final String type;
-    }
-}
-
diff --git a/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java b/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java
index aa78ef8b0e315a2f71261dc1fed480cb8617ccb2..ecc5b723bef81a572c61ac14dd46f48a5593eb50 100644
--- a/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java
+++ b/src/main/java/eu/hbp/mip/models/DTOs/PathologyDTO.java
@@ -1,13 +1,13 @@
 package eu.hbp.mip.models.DTOs;
 
 import com.google.gson.annotations.SerializedName;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
 import java.util.List;
 
-@Getter
-@Setter
+@Data
+@AllArgsConstructor
 public class PathologyDTO {
 
     @SerializedName("code")
@@ -22,8 +22,11 @@ public class PathologyDTO {
     @SerializedName("datasets")
     private List<PathologyDatasetDTO> datasets;
 
-    @Getter
-    @Setter
+    public PathologyDTO(){
+
+    }
+    @Data
+    @AllArgsConstructor
     public static class PathologyDatasetDTO {
         @SerializedName("code")
         private String code;
diff --git a/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java b/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java
index 9ac54cada906b78ad5ab5ac41d77d05562bedc4e..b776b6c46d147e0c146305b4567a0c518b3ea11c 100644
--- a/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java
+++ b/src/main/java/eu/hbp/mip/repositories/ExperimentRepository.java
@@ -1,9 +1,17 @@
 package eu.hbp.mip.repositories;
 
 import eu.hbp.mip.models.DAOs.ExperimentDAO;
+import eu.hbp.mip.models.DAOs.UserDAO;
+import eu.hbp.mip.models.DTOs.ExperimentDTO;
+import eu.hbp.mip.utils.Exceptions.BadRequestException;
+import eu.hbp.mip.utils.Exceptions.ExperimentNotFoundException;
+import eu.hbp.mip.utils.Exceptions.InternalServerError;
+import eu.hbp.mip.utils.JsonConverters;
+import eu.hbp.mip.utils.Logger;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.repository.CrudRepository;
 
+import java.util.Date;
 import java.util.Optional;
 import java.util.UUID;
 
@@ -14,4 +22,91 @@ import java.util.UUID;
 public interface ExperimentRepository extends CrudRepository<ExperimentDAO, UUID>, JpaSpecificationExecutor<ExperimentDAO>
 {
     ExperimentDAO findByUuid(UUID experimentUuid);
+
+    /**
+     * The loadExperiment access the database and load the information of a specific experiment
+     *
+     * @param uuid is the id of the experiment to be retrieved
+     * @return the experiment information that was retrieved from database
+     */
+    default ExperimentDAO loadExperiment(String uuid, Logger logger) {
+        UUID experimentUuid;
+        ExperimentDAO experimentDAO;
+
+        try {
+            experimentUuid = UUID.fromString(uuid);
+        } catch (Exception e) {
+            logger.LogUserAction( e.getMessage());
+            throw new BadRequestException(e.getMessage());
+        }
+
+        experimentDAO = findByUuid(experimentUuid);
+        if (experimentDAO == null) {
+            logger.LogUserAction( "Experiment with uuid : " + uuid + "was not found.");
+            throw new ExperimentNotFoundException("Experiment with uuid : " + uuid + " was not found.");
+        }
+
+        return experimentDAO;
+    }
+
+    /**
+     * The createExperimentInTheDatabase will insert a new experiment in the database according to the given experiment information
+     *
+     * @param experimentDTO is the experiment information to inserted in the database
+     * @return the experiment information that was inserted into the database
+     * @Note In the database there will be stored Algorithm Details that is the whole information about the algorithm
+     * and an Algorithm column that is required for the filtering with algorithm name  in the GET /experiments.
+     */
+    default ExperimentDAO createExperimentInTheDatabase(ExperimentDTO experimentDTO, UserDAO user, Logger logger) {
+
+        ExperimentDAO experimentDAO = new ExperimentDAO();
+        experimentDAO.setUuid(UUID.randomUUID());
+        experimentDAO.setCreatedBy(user);
+        experimentDAO.setAlgorithm(JsonConverters.convertObjectToJsonString(experimentDTO.getAlgorithm()));
+        experimentDAO.setAlgorithmId(experimentDTO.getAlgorithm().getName());
+        experimentDAO.setName(experimentDTO.getName());
+        experimentDAO.setStatus(ExperimentDAO.Status.pending);
+
+        try {
+            save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+
+        logger.LogUserAction(" id : " + experimentDAO.getUuid());
+        logger.LogUserAction(" algorithm : " + experimentDAO.getAlgorithm());
+        logger.LogUserAction(" name : " + experimentDAO.getName());
+        return experimentDAO;
+    }
+
+    default void saveExperiment(ExperimentDAO experimentDAO, Logger logger) {
+
+        logger.LogUserAction(" id : " + experimentDAO.getUuid());
+        logger.LogUserAction(" algorithm : " + experimentDAO.getAlgorithm());
+        logger.LogUserAction(" name : " + experimentDAO.getName());
+        logger.LogUserAction(" historyId : " + experimentDAO.getWorkflowHistoryId());
+        logger.LogUserAction(" status : " + experimentDAO.getStatus());
+
+        try {
+            save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+
+        logger.LogUserAction("Saved experiment");
+    }
+
+    default void finishExperiment(ExperimentDAO experimentDAO, Logger logger) {
+        experimentDAO.setFinished(new Date());
+
+        try {
+            save(experimentDAO);
+        } catch (Exception e) {
+            logger.LogUserAction( "Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
+            throw new InternalServerError(e.getMessage());
+        }
+    }
+
 }
diff --git a/src/main/java/eu/hbp/mip/services/ExperimentService.java b/src/main/java/eu/hbp/mip/services/ExperimentService.java
index 3c52503c23ac6976495e3e006e8b765fbb8c9794..c421fd4717e85b99e06d46f9c6be304f8b22c2da 100644
--- a/src/main/java/eu/hbp/mip/services/ExperimentService.java
+++ b/src/main/java/eu/hbp/mip/services/ExperimentService.java
@@ -1,23 +1,10 @@
 package eu.hbp.mip.services;
 
-import com.github.jmchilton.blend4j.galaxy.GalaxyInstance;
-import com.github.jmchilton.blend4j.galaxy.GalaxyInstanceFactory;
-import com.github.jmchilton.blend4j.galaxy.WorkflowsClient;
-import com.github.jmchilton.blend4j.galaxy.beans.Workflow;
-import com.github.jmchilton.blend4j.galaxy.beans.WorkflowDetails;
-import com.github.jmchilton.blend4j.galaxy.beans.WorkflowInputDefinition;
 import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
 import com.google.gson.internal.LinkedTreeMap;
-import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients;
-import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance;
 import eu.hbp.mip.models.DAOs.ExperimentDAO;
 import eu.hbp.mip.models.DAOs.UserDAO;
 import eu.hbp.mip.models.DTOs.*;
-import eu.hbp.mip.models.galaxy.GalaxyWorkflowResult;
-import eu.hbp.mip.models.galaxy.PostWorkflowToGalaxyDtoResponse;
 import eu.hbp.mip.repositories.ExperimentRepository;
 import eu.hbp.mip.services.Specifications.ExperimentSpecifications;
 import eu.hbp.mip.utils.ClaimUtils;
@@ -25,8 +12,6 @@ import eu.hbp.mip.utils.Exceptions.*;
 import eu.hbp.mip.utils.HTTPUtil;
 import eu.hbp.mip.utils.JsonConverters;
 import eu.hbp.mip.utils.Logger;
-import org.codehaus.jettison.json.JSONException;
-import org.codehaus.jettison.json.JSONObject;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -34,13 +19,8 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.security.core.Authentication;
 import org.springframework.stereotype.Service;
-import retrofit2.Call;
-import retrofit2.Response;
-
-import java.io.IOException;
 import java.util.*;
 
-import static java.lang.Thread.sleep;
 
 @Service
 public class ExperimentService {
@@ -52,22 +32,18 @@ public class ExperimentService {
     @Value("#{'${services.mipengine.algorithmsUrl}'}")
     private String mipengineAlgorithmsUrl;
 
-    @Value("#{'${services.galaxy.galaxyUrl}'}")
-    private String galaxyUrl;
-
-    @Value("#{'${services.galaxy.galaxyApiKey}'}")
-    private String galaxyApiKey;
-
     @Value("#{'${authentication.enabled}'}")
     private boolean authenticationIsEnabled;
 
     private static final Gson gson = new Gson();
 
     private final ActiveUserService activeUserService;
+    private final GalaxyService galaxyService;
     private final ExperimentRepository experimentRepository;
 
-    public ExperimentService(ActiveUserService activeUserService, ExperimentRepository experimentRepository) {
+    public ExperimentService(ActiveUserService activeUserService, GalaxyService galaxyService, ExperimentRepository experimentRepository) {
         this.activeUserService = activeUserService;
+        this.galaxyService = galaxyService;
         this.experimentRepository = experimentRepository;
     }
 
@@ -121,7 +97,7 @@ public class ExperimentService {
             throw new NoContent("No experiment found with the filters provided.");
 
         List<ExperimentDTO> experimentDTOs = new ArrayList<>();
-        experimentDAOs.forEach(experimentDAO -> experimentDTOs.add(experimentDAO.convertToDTO(false)));
+        experimentDAOs.forEach(experimentDAO -> experimentDTOs.add(new ExperimentDTO(false, experimentDAO)));
 
         Map<String, Object> response = new HashMap<>();
         response.put("experiments", experimentDTOs);
@@ -146,7 +122,7 @@ public class ExperimentService {
 
         logger.LogUserAction("Loading Experiment with uuid : " + uuid);
 
-        experimentDAO = loadExperiment(uuid, logger);
+        experimentDAO = experimentRepository.loadExperiment(uuid, logger);
         if (
                 !experimentDAO.isShared()
                 && !experimentDAO.getCreatedBy().getUsername().equals(user.getUsername())
@@ -156,7 +132,7 @@ public class ExperimentService {
             logger.LogUserAction("Accessing Experiment is unauthorized.");
             throw new UnauthorizedException("You don't have access to the experiment.");
         }
-        ExperimentDTO experimentDTO = experimentDAO.convertToDTO(true);
+        ExperimentDTO experimentDTO = new ExperimentDTO(true, experimentDAO);
         logger.LogUserAction("Experiment was Loaded with uuid : " + uuid + ".");
 
         return experimentDTO;
@@ -193,7 +169,7 @@ public class ExperimentService {
         // Run with the appropriate engine
         if (algorithmType.equals("workflow")) {
             logger.LogUserAction("Algorithm runs on Galaxy.");
-            return runGalaxyWorkflow(experimentDTO, logger);
+            return galaxyService.runGalaxyWorkflow(experimentDTO, logger);
         } else {
             logger.LogUserAction("Algorithm runs on Exareme.");
             return createExperiment(experimentDTO, logger);
@@ -253,7 +229,7 @@ public class ExperimentService {
         UserDAO user = activeUserService.getActiveUser();
         logger.LogUserAction("Updating experiment with uuid : " + uuid + ".");
 
-        experimentDAO = loadExperiment(uuid, logger);
+        experimentDAO = experimentRepository.loadExperiment(uuid, logger);
 
         //Verify (PATCH) /experiments non editable fields.
         verifyPatchExperimentNonEditableFields(experimentDTO, logger);
@@ -281,7 +257,7 @@ public class ExperimentService {
 
         logger.LogUserAction("Updated experiment with uuid : " + uuid + ".");
 
-        experimentDTO = experimentDAO.convertToDTO(true);
+        experimentDTO = new ExperimentDTO(true, experimentDAO);
         return experimentDTO;
     }
 
@@ -296,7 +272,7 @@ public class ExperimentService {
         UserDAO user = activeUserService.getActiveUser();
         logger.LogUserAction("Deleting experiment with uuid : " + uuid + ".");
 
-        experimentDAO = loadExperiment(uuid, logger);
+        experimentDAO = experimentRepository.loadExperiment(uuid, logger);
 
         if (!experimentDAO.getCreatedBy().getUsername().equals(user.getUsername()))
             throw new UnauthorizedException("You don't have access to the experiment.");
@@ -409,106 +385,10 @@ public class ExperimentService {
         return experimentDatasets;
     }
 
-    /**
-     * The loadExperiment access the database and load the information of a specific experiment
-     *
-     * @param uuid is the id of the experiment to be retrieved
-     * @return the experiment information that was retrieved from database
-     */
-    private ExperimentDAO loadExperiment(String uuid, Logger logger) {
-        UUID experimentUuid;
-        ExperimentDAO experimentDAO;
-
-        try {
-            experimentUuid = UUID.fromString(uuid);
-        } catch (Exception e) {
-            logger.LogUserAction( e.getMessage());
-            throw new BadRequestException(e.getMessage());
-        }
-
-        experimentDAO = experimentRepository.findByUuid(experimentUuid);
-        if (experimentDAO == null) {
-            logger.LogUserAction( "Experiment with uuid : " + uuid + "was not found.");
-            throw new ExperimentNotFoundException("Experiment with uuid : " + uuid + " was not found.");
-        }
-
-        return experimentDAO;
-    }
-
-    /**
-     * The createExperimentInTheDatabase will insert a new experiment in the database according to the given experiment information
-     *
-     * @param experimentDTO is the experiment information to inserted in the database
-     * @return the experiment information that was inserted into the database
-     * @Note In the database there will be stored Algorithm Details that is the whole information about the algorithm
-     * and an Algorithm column that is required for the filtering with algorithm name  in the GET /experiments.
-     */
-    private ExperimentDAO createExperimentInTheDatabase(ExperimentDTO experimentDTO, Logger logger) {
-        UserDAO user = activeUserService.getActiveUser();
-
-        ExperimentDAO experimentDAO = new ExperimentDAO();
-        experimentDAO.setUuid(UUID.randomUUID());
-        experimentDAO.setCreatedBy(user);
-        experimentDAO.setAlgorithm(JsonConverters.convertObjectToJsonString(experimentDTO.getAlgorithm()));
-        experimentDAO.setAlgorithmId(experimentDTO.getAlgorithm().getName());
-        experimentDAO.setName(experimentDTO.getName());
-        experimentDAO.setStatus(ExperimentDAO.Status.pending);
-
-        try {
-            experimentRepository.save(experimentDAO);
-        } catch (Exception e) {
-            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
-            throw new InternalServerError(e.getMessage());
-        }
-
-        logger.LogUserAction(" id : " + experimentDAO.getUuid());
-        logger.LogUserAction(" algorithm : " + experimentDAO.getAlgorithm());
-        logger.LogUserAction(" name : " + experimentDAO.getName());
-        return experimentDAO;
-    }
-
-    private void saveExperiment(ExperimentDAO experimentDAO, Logger logger) {
-
-        logger.LogUserAction(" id : " + experimentDAO.getUuid());
-        logger.LogUserAction(" algorithm : " + experimentDAO.getAlgorithm());
-        logger.LogUserAction(" name : " + experimentDAO.getName());
-        logger.LogUserAction(" historyId : " + experimentDAO.getWorkflowHistoryId());
-        logger.LogUserAction(" status : " + experimentDAO.getStatus());
-
-        try {
-            experimentRepository.save(experimentDAO);
-        } catch (Exception e) {
-            logger.LogUserAction("Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
-            throw new InternalServerError(e.getMessage());
-        }
-
-        logger.LogUserAction("Saved experiment");
-    }
-
-    private void finishExperiment(ExperimentDAO experimentDAO, Logger logger) {
-        experimentDAO.setFinished(new Date());
-
-        try {
-            experimentRepository.save(experimentDAO);
-        } catch (Exception e) {
-            logger.LogUserAction( "Attempted to save changes to database but an error ocurred  : " + e.getMessage() + ".");
-            throw new InternalServerError(e.getMessage());
-        }
-    }
-
-    private String formattingGalaxyResult(String result) {
-        List<LinkedTreeMap<String,Object>> jsonObject = JsonConverters.convertJsonStringToObject(result, new ArrayList<ArrayList<Object>>().getClass());
-        LinkedTreeMap<String,Object> firstResult = jsonObject.get(0);
-        jsonObject = (List<LinkedTreeMap<String, Object>>) firstResult.get("result");
-        List<LinkedTreeMap<String,Object>> finalJsonObject = new ArrayList<>();
-        finalJsonObject.add(jsonObject.get(0));
-        return JsonConverters.convertObjectToJsonString(finalJsonObject);
-    }
-
     private ExaremeAlgorithmResultDTO convertMIPEngineResultToExaremeAlgorithmResult(int code, String result) {
         MIPEngineAlgorithmResultDTO mipVisualization = JsonConverters.convertJsonStringToObject(result, MIPEngineAlgorithmResultDTO.class);
         LinkedTreeMap<String,Object> data = new LinkedTreeMap<>();
-        data.put("data", mipVisualization.convertToVisualization());
+        data.put("data", new TabularVisualizationDTO(mipVisualization));
         data.put("type", "application/vnd.dataresource+json");
         List<Object> finalObject = new ArrayList<>();
         finalObject.add(data);
@@ -531,7 +411,7 @@ public class ExperimentService {
 
         // Run with the appropriate engine
         if (algorithmType.equals("mipengine")) {
-            MIPEngineAlgorithmRequestDTO mipEngineAlgorithmRequestDTO = experimentDTO.getAlgorithm().convertToMIPEngineBody();
+            MIPEngineAlgorithmRequestDTO mipEngineAlgorithmRequestDTO = new MIPEngineAlgorithmRequestDTO(experimentDTO.getAlgorithm().getParameters());
             String body = JsonConverters.convertObjectToJsonString(mipEngineAlgorithmRequestDTO);
             String url =  mipengineAlgorithmsUrl + "/" + algorithmName.toLowerCase();
             logger.LogUserAction("url: " + url + ", body: " + body);
@@ -609,10 +489,9 @@ public class ExperimentService {
 
         logger.LogUserAction("Running the algorithm...");
 
-        ExperimentDAO experimentDAO = createExperimentInTheDatabase(experimentDTO, logger);
+        ExperimentDAO experimentDAO = experimentRepository.createExperimentInTheDatabase(experimentDTO, activeUserService.getActiveUser(), logger);
         logger.LogUserAction("Created experiment with uuid :" + experimentDAO.getUuid());
 
-
         logger.LogUserAction("Starting execution in thread");
         ExperimentDTO finalExperimentDTO = experimentDTO;
         new Thread(() -> {
@@ -635,402 +514,13 @@ public class ExperimentService {
                 experimentDAO.setStatus(ExperimentDAO.Status.error);
             }
 
-            finishExperiment(experimentDAO, logger);
+            experimentRepository.finishExperiment(experimentDAO, logger);
             Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Finished the experiment: " + experimentDAO);
         }).start();
-        experimentDTO = experimentDAO.convertToDTO(true);
+        experimentDTO = new ExperimentDTO(true, experimentDAO);
         return experimentDTO;
     }
 
     /* ---------------------------------------  GALAXY CALLS ---------------------------------------------------------*/
 
-
-    /**
-     * The runWorkflow will POST the algorithm to the galaxy client
-     *
-     * @param experimentDTO is the request with the experiment information
-     * @return the response to be returned
-     */
-    public ExperimentDTO runGalaxyWorkflow(ExperimentDTO experimentDTO, Logger logger) {
-        logger.LogUserAction("Running a workflow...");
-
-        ExperimentDAO experimentDAO = createExperimentInTheDatabase(experimentDTO, logger);
-        logger.LogUserAction("Created experiment with uuid :" + experimentDAO.getUuid());
-
-
-        // Run the 1st algorithm from the list
-        String workflowId = experimentDTO.getAlgorithm().getName();
-
-        // Get the parameters
-        List<ExaremeAlgorithmRequestParamDTO> algorithmParameters
-                = experimentDTO.getAlgorithm().getParameters();
-
-        // Convert the parameters to workflow parameters
-        HashMap<String, String> algorithmParamsIncludingEmpty = new HashMap<>();
-        if (algorithmParameters != null) {
-            for (ExaremeAlgorithmRequestParamDTO param : algorithmParameters) {
-                algorithmParamsIncludingEmpty.put(param.getName(), param.getValue());
-            }
-        }
-
-        // Get all the algorithm parameters because the frontend provides only the non-null
-        final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey);
-        final WorkflowsClient workflowsClient = instance.getWorkflowsClient();
-        Workflow workflow = null;
-        for (Workflow curWorkflow : workflowsClient.getWorkflows()) {
-            if (curWorkflow.getId().equals(workflowId)) {
-                workflow = curWorkflow;
-                break;
-            }
-        }
-        if (workflow == null) {
-            logger.LogUserAction("Could not find algorithm code: " + workflowId);
-            throw new BadRequestException("Could not find galaxy algorithm.");
-        }
-        final WorkflowDetails workflowDetails = workflowsClient.showWorkflow(workflow.getId());
-        for (Map.Entry<String, WorkflowInputDefinition> workflowParameter : workflowDetails.getInputs().entrySet()) {
-            if (!(algorithmParamsIncludingEmpty.containsKey(workflowParameter.getValue().getUuid()))) {
-                algorithmParamsIncludingEmpty.put(workflowParameter.getValue().getUuid(), "");
-            }
-        }
-
-        // Create the body of the request
-        HashMap<String, HashMap<String, String>> requestBody = new HashMap<>();
-        requestBody.put("inputs", algorithmParamsIncludingEmpty);
-        JsonObject requestBodyJson = new JsonParser().parse(gson.toJson(requestBody)).getAsJsonObject();
-
-        // Create the request client
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        logger.LogUserAction("Running Galaxy workflow with id: " + workflow.getId());
-
-        // Call Galaxy to run the workflow
-        Call<PostWorkflowToGalaxyDtoResponse> call = service.postWorkflowToGalaxy(workflow.getId(), galaxyApiKey, requestBodyJson);
-        try {
-            Response<PostWorkflowToGalaxyDtoResponse> response = call.execute();
-
-            if (response.code() == 200) {       // Call succeeded
-                String responseBody = gson.toJson(response.body());
-                logger.LogUserAction("Response: " + responseBody);
-
-                String historyId = (String) new JSONObject(responseBody).get("history_id");
-                experimentDAO.setWorkflowHistoryId(historyId);
-                experimentDAO.setStatus(ExperimentDAO.Status.success);
-
-            } else {     // Something unexpected happened
-                String msgErr = gson.toJson(response.errorBody());
-                logger.LogUserAction("Error Response: " + msgErr);
-                experimentDTO.setStatus((response.code() >= 400) ? ExperimentDAO.Status.error : ExperimentDAO.Status.success);
-            }
-
-        } catch (Exception e) {
-            logger.LogUserAction("An exception occurred: " + e.getMessage());
-            experimentDAO.setStatus(ExperimentDAO.Status.error);
-        }
-        saveExperiment(experimentDAO, logger);
-
-        // Start the process of fetching the status
-        updateWorkflowExperiment(experimentDAO, logger);
-
-        logger.LogUserAction("Run workflow completed!");
-
-        experimentDTO = experimentDAO.convertToDTO(true);
-        return experimentDTO;
-    }
-
-
-    /**
-     * This method creates a thread that will fetch the workflow result when it is ready
-     *
-     * @param experimentDAO will be used to fetch it's workflow status, it should have the workflowHistoryId initialized
-     *                      and the result should not already be fetched
-     */
-    public void updateWorkflowExperiment(ExperimentDAO experimentDAO, Logger logger) {
-
-        if (experimentDAO == null) {
-            logger.LogUserAction("The experiment does not exist.");
-            return;
-        }
-
-        logger.LogUserAction(" Experiment id : " + experimentDAO.getUuid());
-        if (experimentDAO.getWorkflowHistoryId() == null) {
-            logger.LogUserAction("History Id does not exist.");
-            return;
-        }
-
-        logger.LogUserAction("Starting Thread...");
-        new Thread(() -> {
-            while (true) {
-                // ATTENTION: Inside the Thread only LogExperimentAction should be used, not LogExperimentAction!
-                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Thread is running...");
-
-                try {
-                    sleep(2000);
-                } catch (InterruptedException e) {
-                    Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Sleep was disrupted: " + e.getMessage());
-                }
-
-                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Fetching status for experiment Id: " + experimentDAO.getUuid());
-
-                String state = getWorkflowStatus(experimentDAO);
-                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "State is: " + state);
-
-                switch (state) {
-                    case "pending":
-                        // Do nothing, when the experiment is created the status is set to running
-                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Workflow is still running.");
-                        break;
-
-                    case "success":
-                        // Get only the job result that is visible
-                        List<GalaxyWorkflowResult> workflowJobsResults = getWorkflowResults(experimentDAO);
-                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Results are: " + workflowJobsResults.toString());
-
-                        boolean resultFound = false;
-                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
-                            if (jobResult.getVisible()) {
-                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Visible result are: " + jobResult.getId());
-
-                                String result = getWorkflowResultBody(experimentDAO, jobResult.getId());
-
-                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "ResultDTO: " + result);
-                                if (result == null) {
-                                    experimentDAO.setStatus(ExperimentDAO.Status.error);
-                                } else {
-                                    experimentDAO.setResult(result);
-                                    experimentDAO.setStatus(ExperimentDAO.Status.success);
-                                    resultFound = true;
-                                }
-                            }
-                        }
-
-                        if (!resultFound) {      // If there is no visible result
-                            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "No visible result");
-                            experimentDAO.setStatus(ExperimentDAO.Status.error);
-                        }
-
-                        finishExperiment(experimentDAO, logger);
-                        break;
-
-                    case "error":
-                        // Get the job result that failed
-                        workflowJobsResults = getWorkflowResults(experimentDAO);
-                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Error results are: " + workflowJobsResults.toString());
-
-                        boolean failedJobFound = false;
-                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
-                            if (jobResult.getState().equals("error")) {
-                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Failed job is: " + jobResult.getId());
-
-                                String result = getWorkflowJobError(jobResult.getId(), experimentDAO);
-
-                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Job result: " + result);
-                                if (result == null) {
-                                    experimentDAO.setStatus(ExperimentDAO.Status.error);
-                                }
-                                experimentDAO.setStatus(ExperimentDAO.Status.error);
-                                failedJobFound = true;
-                            }
-                        }
-
-                        if (!failedJobFound) {      // If there is no visible failed job
-                            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "No failed result");
-                            experimentDAO.setStatus(ExperimentDAO.Status.error);
-                        }
-                        finishExperiment(experimentDAO, logger);
-                        break;
-
-                    default:        // InternalError or unexpected result
-                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "An unexpected error occurred.");
-                        experimentDAO.setStatus(ExperimentDAO.Status.error);
-                        finishExperiment(experimentDAO, logger);
-                        break;
-                }
-
-                // If result exists return
-                if (experimentDAO.getResult() != null) {
-                    Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "ResultDTO exists: " + experimentDAO.getResult());
-                    return;
-                }
-            }
-        }).start();
-    }
-
-
-    /**
-     * @param experimentDAO The experiment of the workflow
-     * @return "pending"           ->      When the workflow is still running
-     * "internalError"     ->      When an exception or a bad request occurred
-     * "error"             ->      When the workflow produced an error
-     * "success"         ->      When the workflow completed successfully
-     */
-    public String getWorkflowStatus(ExperimentDAO experimentDAO) {
-        String historyId = experimentDAO.getWorkflowHistoryId();
-        String experimentName = experimentDAO.getName();
-        UUID experimentId = experimentDAO.getUuid();
-
-        // ATTENTION: This function is used from a Thread. Only LogExperimentAction should be used, not LogUserAction!
-        Logger.LogExperimentAction(experimentName, experimentId, " History Id : " + historyId);
-
-        // Create the request client
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<Object> call = service.getWorkflowStatusFromGalaxy(historyId, galaxyApiKey);
-
-        String result;
-        try {
-            Response<Object> response = call.execute();
-            if (response.code() >= 400) {
-                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
-                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return "internalError";
-            }
-            result = new Gson().toJson(response.body());
-            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + result);
-
-        } catch (IOException e) {
-            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
-            return "internalError";
-        }
-
-        String state;
-        try {
-            JSONObject resultJson = new JSONObject(result);
-            state = resultJson.getString("state");
-        } catch (JSONException e) {
-            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
-            return "internalError";
-        }
-
-        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
-        switch (state) {
-            case "ok":
-                return "success";
-            case "error":
-                return "error";
-            case "pending":
-            case "new":
-            case "waiting":
-            case "queued":
-                return "pending";
-            default:
-                return "internalError";
-        }
-    }
-
-    /**
-     * @param experimentDAO The experiment of the workflow
-     * @return a List<GalaxyWorkflowResult>   or null when an error occurred
-     */
-    public List<GalaxyWorkflowResult> getWorkflowResults(ExperimentDAO experimentDAO) {
-
-        String historyId = experimentDAO.getWorkflowHistoryId();
-        String experimentName = experimentDAO.getName();
-        UUID experimentId = experimentDAO.getUuid();
-        Logger.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
-
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<List<GalaxyWorkflowResult>> call = service.getWorkflowResultsFromGalaxy(historyId, galaxyApiKey);
-
-        List<GalaxyWorkflowResult> getGalaxyWorkflowResultList;
-        try {
-            Response<List<GalaxyWorkflowResult>> response = call.execute();
-            if (response.code() >= 400) {
-                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
-                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return null;
-            }
-            getGalaxyWorkflowResultList = response.body();
-            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + response.body());
-
-        } catch (IOException e) {
-            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
-            return null;
-        }
-
-        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
-        return getGalaxyWorkflowResultList;
-
-    }
-
-    /**
-     * @param experimentDAO The experiment of the workflow
-     * @param contentId     the id of the job result that we want
-     * @return the result of the specific workflow job, null if there was an error
-     */
-    public String getWorkflowResultBody(ExperimentDAO experimentDAO, String contentId) {
-
-        String historyId = experimentDAO.getWorkflowHistoryId();
-        String experimentName = experimentDAO.getName();
-        UUID experimentId = experimentDAO.getUuid();
-
-        Logger.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
-
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<Object> call =
-                service.getWorkflowResultsBodyFromGalaxy(historyId, contentId, galaxyApiKey);
-
-        String resultJson;
-        try {
-            Response<Object> response = call.execute();
-            if (response.code() >= 400) {
-                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
-                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return null;
-            }
-            resultJson = new Gson().toJson(response.body());
-            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + resultJson);
-
-        } catch (IOException e) {
-            Logger.LogExperimentAction(experimentName, experimentId,
-                    " An exception happened: " + e.getMessage());
-            return null;
-        }
-
-        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
-        return formattingGalaxyResult(resultJson);
-    }
-
-
-    /**
-     * @param jobId the id of the workflow job that failed
-     * @return the error that was produced or null if an error occurred
-     */
-    public String getWorkflowJobError(String jobId, ExperimentDAO experimentDAO) {
-        String experimentName = experimentDAO.getName();
-        UUID experimentId = experimentDAO.getUuid();
-
-        Logger.LogExperimentAction(experimentName, experimentId, " jobId : " + jobId);
-        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        Call<Object> callError = service.getErrorMessageOfWorkflowFromGalaxy(jobId, galaxyApiKey);
-
-        String fullError;
-        String returnError;
-        try {
-            Response<Object> response = callError.execute();
-            if (response.code() >= 400) {
-                Logger.LogExperimentAction(experimentName, experimentId, "Response code: "
-                        + response.code() + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
-                return null;
-            }
-
-            // Parsing the stderr of the job that failed
-            String jsonString = new Gson().toJson(response.body());
-            JsonElement jsonElement = new JsonParser().parse(jsonString);
-            JsonObject rootObject = jsonElement.getAsJsonObject();
-            fullError = rootObject.get("stderr").getAsString();
-            Logger.LogExperimentAction(experimentName, experimentId, "Error: " + fullError);
-
-            String[] arrOfStr = fullError.split("ValueError", 0);
-            String specError = arrOfStr[arrOfStr.length - 1];
-            returnError = specError.substring(1);
-            Logger.LogExperimentAction(experimentName, experimentId, "Parsed Error: " + returnError);
-
-        } catch (IOException e) {
-            Logger.LogExperimentAction(experimentName, experimentId, "Exception: " + e.getMessage());
-            return null;
-        }
-
-        Logger.LogExperimentAction(experimentName, experimentId, "Completed successfully!");
-
-        return returnError;
-    }
 }
diff --git a/src/main/java/eu/hbp/mip/services/GalaxyService.java b/src/main/java/eu/hbp/mip/services/GalaxyService.java
new file mode 100644
index 0000000000000000000000000000000000000000..80590c7be75a5603996d9b792921b8bb73a42b99
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/services/GalaxyService.java
@@ -0,0 +1,454 @@
+package eu.hbp.mip.services;
+
+import com.github.jmchilton.blend4j.galaxy.GalaxyInstance;
+import com.github.jmchilton.blend4j.galaxy.GalaxyInstanceFactory;
+import com.github.jmchilton.blend4j.galaxy.WorkflowsClient;
+import com.github.jmchilton.blend4j.galaxy.beans.Workflow;
+import com.github.jmchilton.blend4j.galaxy.beans.WorkflowDetails;
+import com.github.jmchilton.blend4j.galaxy.beans.WorkflowInputDefinition;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.internal.LinkedTreeMap;
+import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients;
+import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance;
+import eu.hbp.mip.models.DAOs.ExperimentDAO;
+import eu.hbp.mip.models.DTOs.ExaremeAlgorithmRequestParamDTO;
+import eu.hbp.mip.models.DTOs.ExperimentDTO;
+import eu.hbp.mip.models.galaxy.GalaxyWorkflowResult;
+import eu.hbp.mip.models.galaxy.PostWorkflowToGalaxyDtoResponse;
+import eu.hbp.mip.repositories.ExperimentRepository;
+import eu.hbp.mip.utils.Exceptions.BadRequestException;
+import eu.hbp.mip.utils.JsonConverters;
+import eu.hbp.mip.utils.Logger;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import retrofit2.Call;
+import retrofit2.Response;
+
+import java.io.IOException;
+import java.util.*;
+
+import static java.lang.Thread.sleep;
+
+@Service
+public class GalaxyService {
+
+    private final ActiveUserService activeUserService;
+    private final ExperimentRepository experimentRepository;
+    public GalaxyService(
+            ActiveUserService activeUserService,
+            ExperimentRepository experimentRepository
+    ) {
+        this.activeUserService = activeUserService;
+        this.experimentRepository = experimentRepository;
+    }
+    @Value("#{'${services.galaxy.galaxyUrl}'}")
+    private String galaxyUrl;
+
+    @Value("#{'${services.galaxy.galaxyApiKey}'}")
+    private String galaxyApiKey;
+
+    private static final Gson gson = new Gson();
+
+    /**
+     * The runWorkflow will POST the algorithm to the galaxy client
+     *
+     * @param experimentDTO is the request with the experiment information
+     * @return the response to be returned
+     */
+    public ExperimentDTO runGalaxyWorkflow(ExperimentDTO experimentDTO, Logger logger) {
+        logger.LogUserAction("Running a workflow...");
+
+        ExperimentDAO experimentDAO = experimentRepository.createExperimentInTheDatabase(experimentDTO, activeUserService.getActiveUser(), logger);
+        logger.LogUserAction("Created experiment with uuid :" + experimentDAO.getUuid());
+
+
+        // Run the 1st algorithm from the list
+        String workflowId = experimentDTO.getAlgorithm().getName();
+
+        // Get the parameters
+        List<ExaremeAlgorithmRequestParamDTO> algorithmParameters
+                = experimentDTO.getAlgorithm().getParameters();
+
+        // Convert the parameters to workflow parameters
+        HashMap<String, String> algorithmParamsIncludingEmpty = new HashMap<>();
+        if (algorithmParameters != null) {
+            for (ExaremeAlgorithmRequestParamDTO param : algorithmParameters) {
+                algorithmParamsIncludingEmpty.put(param.getName(), param.getValue());
+            }
+        }
+
+        // Get all the algorithm parameters because the frontend provides only the non-null
+        final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey);
+        final WorkflowsClient workflowsClient = instance.getWorkflowsClient();
+        Workflow workflow = null;
+        for (Workflow curWorkflow : workflowsClient.getWorkflows()) {
+            if (curWorkflow.getId().equals(workflowId)) {
+                workflow = curWorkflow;
+                break;
+            }
+        }
+        if (workflow == null) {
+            logger.LogUserAction("Could not find algorithm code: " + workflowId);
+            throw new BadRequestException("Could not find galaxy algorithm.");
+        }
+        final WorkflowDetails workflowDetails = workflowsClient.showWorkflow(workflow.getId());
+        for (Map.Entry<String, WorkflowInputDefinition> workflowParameter : workflowDetails.getInputs().entrySet()) {
+            if (!(algorithmParamsIncludingEmpty.containsKey(workflowParameter.getValue().getUuid()))) {
+                algorithmParamsIncludingEmpty.put(workflowParameter.getValue().getUuid(), "");
+            }
+        }
+
+        // Create the body of the request
+        HashMap<String, HashMap<String, String>> requestBody = new HashMap<>();
+        requestBody.put("inputs", algorithmParamsIncludingEmpty);
+        JsonObject requestBodyJson = new JsonParser().parse(gson.toJson(requestBody)).getAsJsonObject();
+
+        // Create the request client
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        logger.LogUserAction("Running Galaxy workflow with id: " + workflow.getId());
+
+        // Call Galaxy to run the workflow
+        Call<PostWorkflowToGalaxyDtoResponse> call = service.postWorkflowToGalaxy(workflow.getId(), galaxyApiKey, requestBodyJson);
+        try {
+            Response<PostWorkflowToGalaxyDtoResponse> response = call.execute();
+
+            if (response.code() == 200) {       // Call succeeded
+                String responseBody = gson.toJson(response.body());
+                logger.LogUserAction("Response: " + responseBody);
+
+                String historyId = (String) new JSONObject(responseBody).get("history_id");
+                experimentDAO.setWorkflowHistoryId(historyId);
+                experimentDAO.setStatus(ExperimentDAO.Status.success);
+
+            } else {     // Something unexpected happened
+                String msgErr = gson.toJson(response.errorBody());
+                logger.LogUserAction("Error Response: " + msgErr);
+                experimentDTO.setStatus((response.code() >= 400) ? ExperimentDAO.Status.error : ExperimentDAO.Status.success);
+            }
+
+        } catch (Exception e) {
+            logger.LogUserAction("An exception occurred: " + e.getMessage());
+            experimentDAO.setStatus(ExperimentDAO.Status.error);
+        }
+        experimentRepository.saveExperiment(experimentDAO, logger);
+
+        // Start the process of fetching the status
+        updateWorkflowExperiment(experimentDAO, logger);
+
+        logger.LogUserAction("Run workflow completed!");
+
+        experimentDTO = new ExperimentDTO(true, experimentDAO);
+        return experimentDTO;
+    }
+
+
+
+    /**
+     * @param experimentDAO The experiment of the workflow
+     * @return "pending"           ->      When the workflow is still running
+     * "internalError"     ->      When an exception or a bad request occurred
+     * "error"             ->      When the workflow produced an error
+     * "success"         ->      When the workflow completed successfully
+     */
+    public String getWorkflowStatus(ExperimentDAO experimentDAO) {
+        String historyId = experimentDAO.getWorkflowHistoryId();
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+
+        // ATTENTION: This function is used from a Thread. Only LogExperimentAction should be used, not LogUserAction!
+        Logger.LogExperimentAction(experimentName, experimentId, " History Id : " + historyId);
+
+        // Create the request client
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<Object> call = service.getWorkflowStatusFromGalaxy(historyId, galaxyApiKey);
+
+        String result;
+        try {
+            Response<Object> response = call.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return "internalError";
+            }
+            result = new Gson().toJson(response.body());
+            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + result);
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
+            return "internalError";
+        }
+
+        String state;
+        try {
+            JSONObject resultJson = new JSONObject(result);
+            state = resultJson.getString("state");
+        } catch (JSONException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
+            return "internalError";
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
+        switch (state) {
+            case "ok":
+                return "success";
+            case "error":
+                return "error";
+            case "pending":
+            case "new":
+            case "waiting":
+            case "queued":
+                return "pending";
+            default:
+                return "internalError";
+        }
+    }
+
+    /**
+     * @param experimentDAO The experiment of the workflow
+     * @return a List<GalaxyWorkflowResult>   or null when an error occurred
+     */
+    public List<GalaxyWorkflowResult> getWorkflowResults(ExperimentDAO experimentDAO) {
+
+        String historyId = experimentDAO.getWorkflowHistoryId();
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+        Logger.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
+
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<List<GalaxyWorkflowResult>> call = service.getWorkflowResultsFromGalaxy(historyId, galaxyApiKey);
+
+        List<GalaxyWorkflowResult> getGalaxyWorkflowResultList;
+        try {
+            Response<List<GalaxyWorkflowResult>> response = call.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+            getGalaxyWorkflowResultList = response.body();
+            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + response.body());
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, " An exception happened: " + e.getMessage());
+            return null;
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
+        return getGalaxyWorkflowResultList;
+
+    }
+
+    /**
+     * @param experimentDAO The experiment of the workflow
+     * @param contentId     the id of the job result that we want
+     * @return the result of the specific workflow job, null if there was an error
+     */
+    public String getWorkflowResultBody(ExperimentDAO experimentDAO, String contentId) {
+
+        String historyId = experimentDAO.getWorkflowHistoryId();
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+
+        Logger.LogExperimentAction(experimentName, experimentId, " historyId : " + historyId);
+
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<Object> call =
+                service.getWorkflowResultsBodyFromGalaxy(historyId, contentId, galaxyApiKey);
+
+        String resultJson;
+        try {
+            Response<Object> response = call.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, " Response code: "
+                        + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+            resultJson = new Gson().toJson(response.body());
+            Logger.LogExperimentAction(experimentName, experimentId, " ResultDTO: " + resultJson);
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId,
+                    " An exception happened: " + e.getMessage());
+            return null;
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, " Completed!");
+        return formattingGalaxyResult(resultJson);
+    }
+
+    private String formattingGalaxyResult(String result) {
+        List<LinkedTreeMap<String,Object>> jsonObject = JsonConverters.convertJsonStringToObject(result, new ArrayList<ArrayList<Object>>().getClass());
+        LinkedTreeMap<String,Object> firstResult = jsonObject.get(0);
+        jsonObject = (List<LinkedTreeMap<String, Object>>) firstResult.get("result");
+        List<LinkedTreeMap<String,Object>> finalJsonObject = new ArrayList<>();
+        finalJsonObject.add(jsonObject.get(0));
+        return JsonConverters.convertObjectToJsonString(finalJsonObject);
+    }
+
+
+    /**
+     * @param jobId the id of the workflow job that failed
+     * @return the error that was produced or null if an error occurred
+     */
+    public String getWorkflowJobError(String jobId, ExperimentDAO experimentDAO) {
+        String experimentName = experimentDAO.getName();
+        UUID experimentId = experimentDAO.getUuid();
+
+        Logger.LogExperimentAction(experimentName, experimentId, " jobId : " + jobId);
+        RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
+        Call<Object> callError = service.getErrorMessageOfWorkflowFromGalaxy(jobId, galaxyApiKey);
+
+        String fullError;
+        String returnError;
+        try {
+            Response<Object> response = callError.execute();
+            if (response.code() >= 400) {
+                Logger.LogExperimentAction(experimentName, experimentId, "Response code: "
+                        + response.code() + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
+                return null;
+            }
+
+            // Parsing the stderr of the job that failed
+            String jsonString = new Gson().toJson(response.body());
+            JsonElement jsonElement = new JsonParser().parse(jsonString);
+            JsonObject rootObject = jsonElement.getAsJsonObject();
+            fullError = rootObject.get("stderr").getAsString();
+            Logger.LogExperimentAction(experimentName, experimentId, "Error: " + fullError);
+
+            String[] arrOfStr = fullError.split("ValueError", 0);
+            String specError = arrOfStr[arrOfStr.length - 1];
+            returnError = specError.substring(1);
+            Logger.LogExperimentAction(experimentName, experimentId, "Parsed Error: " + returnError);
+
+        } catch (IOException e) {
+            Logger.LogExperimentAction(experimentName, experimentId, "Exception: " + e.getMessage());
+            return null;
+        }
+
+        Logger.LogExperimentAction(experimentName, experimentId, "Completed successfully!");
+
+        return returnError;
+    }
+
+    /**
+     * This method creates a thread that will fetch the workflow result when it is ready
+     *
+     * @param experimentDAO will be used to fetch it's workflow status, it should have the workflowHistoryId initialized
+     *                      and the result should not already be fetched
+     */
+    public void updateWorkflowExperiment(ExperimentDAO experimentDAO, Logger logger) {
+
+        if (experimentDAO == null) {
+            logger.LogUserAction("The experiment does not exist.");
+            return;
+        }
+
+        logger.LogUserAction(" Experiment id : " + experimentDAO.getUuid());
+        if (experimentDAO.getWorkflowHistoryId() == null) {
+            logger.LogUserAction("History Id does not exist.");
+            return;
+        }
+
+        logger.LogUserAction("Starting Thread...");
+        new Thread(() -> {
+            while (true) {
+                // ATTENTION: Inside the Thread only LogExperimentAction should be used, not LogExperimentAction!
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Thread is running...");
+
+                try {
+                    sleep(2000);
+                } catch (InterruptedException e) {
+                    Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Sleep was disrupted: " + e.getMessage());
+                }
+
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Fetching status for experiment Id: " + experimentDAO.getUuid());
+
+                String state = getWorkflowStatus(experimentDAO);
+                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "State is: " + state);
+
+                switch (state) {
+                    case "pending":
+                        // Do nothing, when the experiment is created the status is set to running
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Workflow is still running.");
+                        break;
+
+                    case "success":
+                        // Get only the job result that is visible
+                        List<GalaxyWorkflowResult> workflowJobsResults = getWorkflowResults(experimentDAO);
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Results are: " + workflowJobsResults.toString());
+
+                        boolean resultFound = false;
+                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
+                            if (jobResult.getVisible()) {
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Visible result are: " + jobResult.getId());
+
+                                String result = getWorkflowResultBody(experimentDAO, jobResult.getId());
+
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "ResultDTO: " + result);
+                                if (result == null) {
+                                    experimentDAO.setStatus(ExperimentDAO.Status.error);
+                                } else {
+                                    experimentDAO.setResult(result);
+                                    experimentDAO.setStatus(ExperimentDAO.Status.success);
+                                    resultFound = true;
+                                }
+                            }
+                        }
+
+                        if (!resultFound) {      // If there is no visible result
+                            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "No visible result");
+                            experimentDAO.setStatus(ExperimentDAO.Status.error);
+                        }
+
+                        experimentRepository.finishExperiment(experimentDAO, logger);
+                        break;
+
+                    case "error":
+                        // Get the job result that failed
+                        workflowJobsResults = getWorkflowResults(experimentDAO);
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Error results are: " + workflowJobsResults.toString());
+
+                        boolean failedJobFound = false;
+                        for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
+                            if (jobResult.getState().equals("error")) {
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Failed job is: " + jobResult.getId());
+
+                                String result = getWorkflowJobError(jobResult.getId(), experimentDAO);
+
+                                Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "Job result: " + result);
+                                if (result == null) {
+                                    experimentDAO.setStatus(ExperimentDAO.Status.error);
+                                }
+                                experimentDAO.setStatus(ExperimentDAO.Status.error);
+                                failedJobFound = true;
+                            }
+                        }
+
+                        if (!failedJobFound) {      // If there is no visible failed job
+                            Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "No failed result");
+                            experimentDAO.setStatus(ExperimentDAO.Status.error);
+                        }
+                        experimentRepository.finishExperiment(experimentDAO, logger);
+                        break;
+
+                    default:        // InternalError or unexpected result
+                        Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "An unexpected error occurred.");
+                        experimentDAO.setStatus(ExperimentDAO.Status.error);
+                        experimentRepository.finishExperiment(experimentDAO, logger);
+                        break;
+                }
+
+                // If result exists return
+                if (experimentDAO.getResult() != null) {
+                    Logger.LogExperimentAction(experimentDAO.getName(), experimentDAO.getUuid(), "ResultDTO exists: " + experimentDAO.getResult());
+                    return;
+                }
+            }
+        }).start();
+    }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 8aadac388979fa2c7af445fa88c1f697fb8fed22..d8d542b6bb2d78a46f0f52d87057ab71acca04cd 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -35,7 +35,7 @@ spring:
 ### EXTERNAL SERVICES ###
 services:
   mipengine:
-    algorithmsUrl: "http://192.168.124.129:5000/algorithms"
+    algorithmsUrl: "http://127.0.0.1:5000/algorithms"
   exareme:
     queryExaremeUrl: "http://127.0.0.1:9090/mining/query"
     algorithmsUrl: "http://127.0.0.1:9090/mining/algorithms.json"