Skip to content
Snippets Groups Projects
Commit 6eff7e51 authored by Mirco Nasuti's avatar Mirco Nasuti
Browse files

Merge branch 'sonar_suggestions' into 'stable'

Sonar suggestions

Did some re-factoring.

See merge request !10
parents fde60129 12c95e0d
No related branches found
No related tags found
No related merge requests found
...@@ -4,22 +4,26 @@ import com.google.gson.*; ...@@ -4,22 +4,26 @@ import com.google.gson.*;
import io.swagger.annotations.*; import io.swagger.annotations.*;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.hbp.mip.MIPApplication; import org.hbp.mip.MIPApplication;
import org.hbp.mip.model.*; import org.hbp.mip.model.Experiment;
import org.hbp.mip.model.Model;
import org.hbp.mip.model.User;
import org.hbp.mip.utils.HTTPUtil; import org.hbp.mip.utils.HTTPUtil;
import org.hbp.mip.utils.HibernateUtil; import org.hbp.mip.utils.HibernateUtil;
import org.hbp.mip.utils.JSONUtil;
import org.hibernate.Query; import org.hibernate.Query;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.exception.DataException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.io.*; import java.io.BufferedReader;
import java.net.*; import java.io.IOException;
import java.util.Date; import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
...@@ -45,6 +49,8 @@ public class ExperimentApi { ...@@ -45,6 +49,8 @@ public class ExperimentApi {
.excludeFieldsWithoutExposeAnnotation() .excludeFieldsWithoutExposeAnnotation()
.create(); .create();
private static final String EXAREME_LR_ALGO = "WP_LINEAR_REGRESSION";
@Value("#{'${workflow.experimentUrl:http://dockerhost:8087/experiment}'}") @Value("#{'${workflow.experimentUrl:http://dockerhost:8087/experiment}'}")
private String experimentUrl; private String experimentUrl;
...@@ -57,82 +63,6 @@ public class ExperimentApi { ...@@ -57,82 +63,6 @@ public class ExperimentApi {
@Autowired @Autowired
MIPApplication mipApplication; MIPApplication mipApplication;
private void sendPost(Experiment experiment) throws MalformedURLException {
URL obj = new URL(experimentUrl);
// this runs in the background. For future optimization: use a thread pool
new Thread() {
@Override
public void run() {
try {
String query = experiment.computeQuery();
HttpURLConnection con = createConnection(obj, query);
writeQueryBody(con, query);
String response = readResponse(con);
// write to experiment
experiment.setResult(response.replace("\0", ""));
experiment.setHasError(con.getResponseCode() >= 400);
experiment.setHasServerError(con.getResponseCode() >= 500);
} catch (ProtocolException pe) {
LOGGER.trace(pe);
} catch (IOException ioe) {
// write error to
LOGGER.trace(ioe);
LOGGER.warn("Experiment failed to run properly !");
experiment.setHasError(true);
experiment.setHasServerError(true);
experiment.setResult(ioe.getMessage());
}
experiment.setFinished(new Date());
// finally
try {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.update(experiment);
transaction.commit();
session.close();
} catch (DataException e) {
LOGGER.trace(e);
throw e;
}
}
}.start();
}
private static String readResponse(HttpURLConnection con) throws IOException {
InputStream stream = con.getResponseCode() < 400 ? con.getInputStream() : con.getErrorStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine + '\n');
}
in.close();
return response.toString();
}
private static void writeQueryBody(HttpURLConnection con, String query) throws IOException {
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.write(query.getBytes("UTF8"));
wr.flush();
wr.close();
}
private static HttpURLConnection createConnection(URL url, String query) throws IOException {
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.addRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Content-Length", Integer.toString(query.length()));
con.setInstanceFollowRedirects(true);
con.setReadTimeout(3600000); // 1 hour: 60*60*1000 ms
con.setDoOutput(true);
return con;
}
@ApiOperation(value = "Send a request to the workflow to run an experiment", response = Experiment.class) @ApiOperation(value = "Send a request to the workflow to run an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
...@@ -175,125 +105,21 @@ public class ExperimentApi { ...@@ -175,125 +105,21 @@ public class ExperimentApi {
try { try {
if(isExaremeAlgo(experiment)) if(isExaremeAlgo(experiment))
{ {
sendExaremePost(experiment); sendExaremeExperiment(experiment);
} }
else else
{ {
sendPost(experiment); sendExperiment(experiment);
} }
} catch (MalformedURLException mue) { LOGGER.trace(mue.getMessage()); } // ignore } catch (MalformedURLException mue) { LOGGER.trace(mue.getMessage()); } // ignore
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK); return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
} }
private void sendExaremePost(Experiment experiment) {
Model model = experiment.getModel();
String algoCode = "WP_LINEAR_REGRESSION";
List<ExaremeQueryElement> queryElements = new LinkedList<>();
for (Variable var : model.getQuery().getVariables())
{
ExaremeQueryElement el = new ExaremeQueryElement();
el.setName("variable");
el.setDesc("");
el.setValue(var.getCode());
queryElements.add(el);
}
for (Variable var : model.getQuery().getCovariables())
{
ExaremeQueryElement el = new ExaremeQueryElement();
el.setName("covariables");
el.setDesc("");
el.setValue(var.getCode());
queryElements.add(el);
}
for (Variable var : model.getQuery().getGrouping())
{
ExaremeQueryElement el = new ExaremeQueryElement();
el.setName("groupings");
el.setDesc("");
el.setValue(var.getCode());
queryElements.add(el);
}
ExaremeQueryElement tableEl = new ExaremeQueryElement();
tableEl.setName("showtable");
tableEl.setDesc("");
tableEl.setValue("TotalResults");
queryElements.add(tableEl);
ExaremeQueryElement formatEl = new ExaremeQueryElement();
formatEl.setName("format");
formatEl.setDesc("");
formatEl.setValue("True");
queryElements.add(formatEl);
String jsonQuery = new Gson().toJson(queryElements);
new Thread() {
@Override
public void run() {
try {
String url = miningExaremeQueryUrl + "/" + algoCode;
StringBuilder results = new StringBuilder();
int code = HTTPUtil.sendPost(url, jsonQuery, results);
experiment.setResult(results.toString().replace("\0", ""));
experiment.setHasError(code >= 400);
experiment.setHasServerError(code >= 500);
if(!isJSONValid(experiment.getResult()))
{
experiment.setResult("Unsupported variables !");
}
} catch (Exception e) {
LOGGER.trace(e);
LOGGER.warn("Failed to run Exareme algorithm !");
experiment.setHasError(true);
experiment.setHasServerError(true);
experiment.setResult(e.getMessage());
}
experiment.setFinished(new Date());
try {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.update(experiment);
transaction.commit();
session.close();
} catch (DataException e) {
LOGGER.trace(e);
throw e;
}
}
}.start();
}
public boolean isJSONValid(String test) {
try {
new JsonParser().parse(test);
} catch (JsonParseException jpe)
{
LOGGER.trace(jpe); // This is the normal behavior when the input string is not JSON-ified
return false;
}
return true;
}
private boolean isExaremeAlgo(Experiment experiment) {
JsonArray algorithms = new JsonParser().parse(experiment.getAlgorithms()).getAsJsonArray();
String algoCode = algorithms.get(0).getAsJsonObject().get("code").getAsString();
return "glm_exareme".equals(algoCode);
}
@ApiOperation(value = "get an experiment", response = Experiment.class) @ApiOperation(value = "get an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/{uuid}", method = RequestMethod.GET) @RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
public ResponseEntity<String> getExperiment(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) { public ResponseEntity<String> getExperiment(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
Experiment experiment; Experiment experiment;
UUID experimentUuid; UUID experimentUuid;
try { try {
...@@ -372,48 +198,6 @@ public class ExperimentApi { ...@@ -372,48 +198,6 @@ public class ExperimentApi {
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK); return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
} }
public ResponseEntity<String> doMarkExperimentAsShared(String uuid, boolean shared) {
Experiment experiment;
UUID experimentUuid;
User user = mipApplication.getUser();
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
LOGGER.trace(iae);
LOGGER.warn("An invalid Experiment UUID was received !");
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
hibernateQuery.setParameter("uuid", experimentUuid);
experiment = (Experiment) hibernateQuery.uniqueResult();
if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
experiment.setShared(shared);
session.update(experiment);
transaction.commit();
} catch (Exception e) {
// 404 here probably
if(transaction != null)
{
transaction.rollback();
}
throw e;
}
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
}
@ApiOperation(value = "get an experiment", response = Experiment.class) @ApiOperation(value = "get an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/{uuid}/markAsShared", method = RequestMethod.GET) @RequestMapping(value = "/{uuid}/markAsShared", method = RequestMethod.GET)
...@@ -428,7 +212,55 @@ public class ExperimentApi { ...@@ -428,7 +212,55 @@ public class ExperimentApi {
return doMarkExperimentAsShared(uuid, false); return doMarkExperimentAsShared(uuid, false);
} }
public ResponseEntity<String> doListExperiments( @ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/mine", method = RequestMethod.GET, params = {"maxResultCount"})
public ResponseEntity<String> listExperiments(
@ApiParam(value = "maxResultCount", required = false) @RequestParam int maxResultCount
) {
return doListExperiments(true, maxResultCount, null);
}
@ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(method = RequestMethod.GET, params = {"slug", "maxResultCount"})
public ResponseEntity<String> listExperiments(
@ApiParam(value = "slug", required = false) @RequestParam("slug") String modelSlug,
@ApiParam(value = "maxResultCount", required = false) @RequestParam("maxResultCount") int maxResultCount
) {
if (maxResultCount <= 0 && (modelSlug == null || "".equals(modelSlug))) {
return new ResponseEntity<>("You must provide at least a slug or a limit of result", HttpStatus.BAD_REQUEST);
}
return doListExperiments(false, maxResultCount, modelSlug);
}
@ApiOperation(value = "List available methods and validations", response = String.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(path = "/methods", method = RequestMethod.GET)
public ResponseEntity<String> listAvailableMethodsAndValidations() throws IOException {
StringBuilder response = new StringBuilder();
int code = HTTPUtil.sendGet(listMethodsUrl, response);
if (code < 200 || code > 299) {
return new ResponseEntity<>(response.toString(), HttpStatus.valueOf(code));
}
JsonObject catalog = new JsonParser().parse(response.toString()).getAsJsonObject();
InputStream is = ExperimentApi.class.getClassLoader().getResourceAsStream(EXAREME_ALGO_JSON_FILE);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
JsonObject exaremeAlgo = new JsonParser().parse(br).getAsJsonObject();
catalog.get("algorithms").getAsJsonArray().add(exaremeAlgo);
return new ResponseEntity<>(new Gson().toJson(catalog), HttpStatus.valueOf(code));
}
private ResponseEntity<String> doListExperiments(
boolean mine, boolean mine,
int maxResultCount, int maxResultCount,
String modelSlug String modelSlug
...@@ -484,51 +316,113 @@ public class ExperimentApi { ...@@ -484,51 +316,113 @@ public class ExperimentApi {
return new ResponseEntity<>(gson.toJson(experiments), HttpStatus.OK); return new ResponseEntity<>(gson.toJson(experiments), HttpStatus.OK);
} }
@ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List") private ResponseEntity<String> doMarkExperimentAsShared(String uuid, boolean shared) {
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") }) Experiment experiment;
@RequestMapping(value = "/mine", method = RequestMethod.GET, params = {"maxResultCount"}) UUID experimentUuid;
public ResponseEntity<String> listExperiments( User user = mipApplication.getUser();
@ApiParam(value = "maxResultCount", required = false) @RequestParam int maxResultCount try {
) { experimentUuid = UUID.fromString(uuid);
return doListExperiments(true, maxResultCount, null); } catch (IllegalArgumentException iae) {
} LOGGER.trace(iae);
LOGGER.warn("An invalid Experiment UUID was received !");
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
@ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List") Session session = HibernateUtil.getSessionFactory().getCurrentSession();
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") }) Transaction transaction = null;
@RequestMapping(method = RequestMethod.GET, params = {"slug", "maxResultCount"}) try {
public ResponseEntity<String> listExperiments( transaction = session.beginTransaction();
@ApiParam(value = "slug", required = false) @RequestParam("slug") String modelSlug,
@ApiParam(value = "maxResultCount", required = false) @RequestParam("maxResultCount") int maxResultCount
) {
if (maxResultCount <= 0 && (modelSlug == null || "".equals(modelSlug))) { Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
return new ResponseEntity<>("You must provide at least a slug or a limit of result", HttpStatus.BAD_REQUEST); hibernateQuery.setParameter("uuid", experimentUuid);
experiment = (Experiment) hibernateQuery.uniqueResult();
if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
experiment.setShared(shared);
session.update(experiment);
transaction.commit();
} catch (Exception e) {
// 404 here probably
if(transaction != null)
{
transaction.rollback();
}
throw e;
} }
return doListExperiments(false, maxResultCount, modelSlug); return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
} }
@ApiOperation(value = "List available methods and validations", response = String.class) private void sendExperiment(Experiment experiment) throws MalformedURLException {
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") }) // this runs in the background. For future optimization: use a thread pool
@RequestMapping(path = "/methods", method = RequestMethod.GET) new Thread() {
public ResponseEntity<String> listAvailableMethodsAndValidations() throws IOException { @Override
public void run() {
String url = experimentUrl;
String query = experiment.computeQuery();
StringBuilder response = new StringBuilder(); // Results are stored in the experiment object
try {
executeExperiment(url, query, experiment);
} catch (IOException e) {
LOGGER.trace(e);
LOGGER.warn("Experiment failed to run properly !");
setExperimentError(e, experiment);
}
int code = HTTPUtil.sendGet(listMethodsUrl, response); experiment.finish();
if (code < 200 || code > 299) { }
return new ResponseEntity<>(response.toString(), HttpStatus.valueOf(code)); }.start();
} }
JsonObject catalog = new JsonParser().parse(response.toString()).getAsJsonObject(); private void sendExaremeExperiment(Experiment experiment) {
// this runs in the background. For future optimization: use a thread pool
new Thread() {
@Override
public void run() {
String query = experiment.computeExaremeQuery();
String url = miningExaremeQueryUrl + "/" + EXAREME_LR_ALGO;
InputStream is = ExperimentApi.class.getClassLoader().getResourceAsStream(EXAREME_ALGO_JSON_FILE); // Results are stored in the experiment object
InputStreamReader isr = new InputStreamReader(is); try {
BufferedReader br = new BufferedReader(isr); executeExperiment(url, query, experiment);
JsonObject exaremeAlgo = new JsonParser().parse(br).getAsJsonObject(); } catch (IOException e) {
LOGGER.trace(e);
LOGGER.warn("Exareme experiment failed to run properly !");
setExperimentError(e, experiment);
}
catalog.get("algorithms").getAsJsonArray().add(exaremeAlgo); if(!JSONUtil.isJSONValid(experiment.getResult()))
{
experiment.setResult("Unsupported variables !");
}
return new ResponseEntity<>(new Gson().toJson(catalog), HttpStatus.valueOf(code)); experiment.finish();
}
}.start();
}
private static void executeExperiment(String url, String query, Experiment experiment) throws IOException {
StringBuilder results = new StringBuilder();
int code = HTTPUtil.sendPost(url, query, results);
experiment.setResult(results.toString().replace("\0", ""));
experiment.setHasError(code >= 400);
experiment.setHasServerError(code >= 500);
} }
private static void setExperimentError(IOException e, Experiment experiment) {
experiment.setHasError(true);
experiment.setHasServerError(true);
experiment.setResult(e.getMessage());
}
private static boolean isExaremeAlgo(Experiment experiment) {
JsonArray algorithms = new JsonParser().parse(experiment.getAlgorithms()).getAsJsonArray();
String algoCode = algorithms.get(0).getAsJsonObject().get("code").getAsString();
return "glm_exareme".equals(algoCode);
}
} }
...@@ -5,12 +5,19 @@ import com.google.gson.GsonBuilder; ...@@ -5,12 +5,19 @@ import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import org.apache.log4j.Logger;
import org.hbp.mip.utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.annotations.*; import org.hibernate.annotations.*;
import org.hibernate.exception.DataException;
import javax.persistence.*; import javax.persistence.*;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
/** /**
...@@ -20,6 +27,8 @@ import java.util.UUID; ...@@ -20,6 +27,8 @@ import java.util.UUID;
@Table(name = "`experiment`") @Table(name = "`experiment`")
public class Experiment { public class Experiment {
private static final Logger LOGGER = Logger.getLogger(Experiment.class);
private static final Gson gson = new GsonBuilder() private static final Gson gson = new GsonBuilder()
.serializeNulls() .serializeNulls()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
...@@ -94,6 +103,63 @@ public class Experiment { ...@@ -94,6 +103,63 @@ public class Experiment {
return outgoingQuery.toString(); return outgoingQuery.toString();
} }
public String computeExaremeQuery() {
List<ExaremeQueryElement> queryElements = new LinkedList<>();
for (Variable var : model.getQuery().getVariables())
{
ExaremeQueryElement el = new ExaremeQueryElement();
el.setName("variable");
el.setDesc("");
el.setValue(var.getCode());
queryElements.add(el);
}
for (Variable var : model.getQuery().getCovariables())
{
ExaremeQueryElement el = new ExaremeQueryElement();
el.setName("covariables");
el.setDesc("");
el.setValue(var.getCode());
queryElements.add(el);
}
for (Variable var : model.getQuery().getGrouping())
{
ExaremeQueryElement el = new ExaremeQueryElement();
el.setName("groupings");
el.setDesc("");
el.setValue(var.getCode());
queryElements.add(el);
}
ExaremeQueryElement tableEl = new ExaremeQueryElement();
tableEl.setName("showtable");
tableEl.setDesc("");
tableEl.setValue("TotalResults");
queryElements.add(tableEl);
ExaremeQueryElement formatEl = new ExaremeQueryElement();
formatEl.setName("format");
formatEl.setDesc("");
formatEl.setValue("True");
queryElements.add(formatEl);
return new Gson().toJson(queryElements);
}
public void finish() {
this.setFinished(new Date());
try {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.update(this);
transaction.commit();
session.close();
} catch (DataException e) {
LOGGER.trace(e);
throw e;
}
}
public String getValidations() { public String getValidations() {
return validations; return validations;
} }
......
package org.hbp.mip.utils;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import org.apache.log4j.Logger;
/**
* Created by mirco on 01.07.16.
*/
public class JSONUtil {
private static final Logger LOGGER = Logger.getLogger(JSONUtil.class);
private JSONUtil() {
/* Hide implicit public constructor */
throw new IllegalAccessError("JSONUtil class");
}
public static boolean isJSONValid(String test) {
try {
new JsonParser().parse(test);
} catch (JsonParseException jpe)
{
LOGGER.trace(jpe); // This is the normal behavior when the input string is not JSON-ified
return false;
}
return true;
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment