From c9c43887e853d0122bce16a4f67d4d1b984a668c Mon Sep 17 00:00:00 2001 From: Ludovic Claude <ludovic.claude54@gmail.com> Date: Thu, 15 Mar 2018 18:45:41 +0100 Subject: [PATCH] Update woken-messages to 2.5.2, /datasets return [{code,label}] from Woken --- docker/README.md | 1 - docker/config/application.tmpl | 1 - docker/run.sh | 2 +- pom.xml | 2 +- .../hbp/mip/akka/WokenClientController.java | 45 +++++++---------- .../eu/hbp/mip/controllers/DatasetsApi.java | 49 +++++++++++++++---- .../eu/hbp/mip/controllers/MethodsApi.java | 2 +- 7 files changed, 60 insertions(+), 42 deletions(-) diff --git a/docker/README.md b/docker/README.md index 33262bdde..419dd0798 100644 --- a/docker/README.md +++ b/docker/README.md @@ -24,7 +24,6 @@ To use this image, you need a running instance of PostgreSQL and to configure th * FEATURES_DB_USER: User to use when connecting to the science database, default value is "postgres". * FEATURES_DB_PASSWORD: Password to use when connecting to the science database. * FEATURES_DB_MAIN_TABLE: Table that contains the scientific data to use, default value is "features". -* DATASETS (temporary hack): list of datasets available in the features table ### OAUTH2 LOGIN diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl index 3be9dac65..16a901f6b 100644 --- a/docker/config/application.tmpl +++ b/docker/config/application.tmpl @@ -21,7 +21,6 @@ spring: username: {{ default .Env.FEATURES_DB_USER "postgres" }} password: {{ .Env.FEATURES_DB_PASSWORD }} driver-class-name: org.postgresql.Driver - datasets: {{ .Env.DATASETS }} jpa: hibernate: dialect: org.hibernate.dialect.PostgreSQL9Dialect diff --git a/docker/run.sh b/docker/run.sh index 2b1ca22d1..a89331926 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -10,4 +10,4 @@ fi if [ ! -z "$FEATURES_DB_SERVER" ]; then OPTS="$OPTS -wait tcp://$FEATURES_DB_SERVER -timeout 60s" fi -dockerize $OPTS java -jar /usr/share/jars/portal-backend.jar +dockerize $OPTS java ${JAVA_OPTS} -jar /usr/share/jars/portal-backend.jar diff --git a/pom.xml b/pom.xml index 3f71142f1..d39be85f1 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ <spring-data-jpa.version>1.10.11.RELEASE</spring-data-jpa.version> <spring-boot-starter-actuator.version>1.4.7.RELEASE</spring-boot-starter-actuator.version> <aspectjweaver.version>1.8.9</aspectjweaver.version> - <woken-messages.version>2.4.9</woken-messages.version> + <woken-messages.version>2.5.2</woken-messages.version> <javax-inject.version>1</javax-inject.version> <akka.version>2.5.9</akka.version> <spring-context.version>4.3.4.RELEASE</spring-context.version> diff --git a/src/main/java/eu/hbp/mip/akka/WokenClientController.java b/src/main/java/eu/hbp/mip/akka/WokenClientController.java index 3cc463857..2504d6468 100644 --- a/src/main/java/eu/hbp/mip/akka/WokenClientController.java +++ b/src/main/java/eu/hbp/mip/akka/WokenClientController.java @@ -31,7 +31,7 @@ import java.util.function.Function; */ public abstract class WokenClientController { - private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); @Autowired private ActorSystem actorSystem; @@ -44,6 +44,7 @@ public abstract class WokenClientController { private ActorRef wokenClient; + @SuppressWarnings("unused") @PostConstruct public void initClusterClient() { LOGGER.info("Start Woken client " + wokenReceptionistPath); @@ -56,7 +57,8 @@ public abstract class WokenClientController { return Collections.singleton(ActorPaths.fromString(wokenReceptionistPath)); } - protected <A, B> ResponseEntity askWoken(A message, int waitInSeconds, Function<B, ResponseEntity> handleResponse) { + @SuppressWarnings("unchecked") + protected <A, B> B askWoken(A message, int waitInSeconds) throws Exception { LOGGER.info("Akka is trying to reach remote " + wokenPath); ClusterClient.Send queryMessage = new ClusterClient.Send(wokenPath, message, true); @@ -64,35 +66,29 @@ public abstract class WokenClientController { Future<Object> future = Patterns.ask(wokenClient, queryMessage, timeout); - B result; + return (B) Await.result(future, timeout.duration()); + } + + protected <A, B> ResponseEntity requestWoken(A message, int waitInSeconds, Function<B, ResponseEntity> handleResponse) { try { - result = (B) Await.result(future, timeout.duration()); + B result = askWoken(message, waitInSeconds); + return handleResponse.apply(result); } catch (Exception e) { - LOGGER.error("Cannot receive algorithm result from woken: " + e.getMessage(), e); - return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build(); + final String msg = "Cannot receive result from woken: " + e.getMessage(); + LOGGER.error(msg, e); + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(msg); } - - return handleResponse.apply(result); } - protected <A extends Query> ResponseEntity askWokenQuery(A query, int waitInSeconds, Function<QueryResult, ResponseEntity> handleResponse) { - LOGGER.info("Akka is trying to reach remote " + wokenPath); - - ClusterClient.Send queryMessage = new ClusterClient.Send(wokenPath, query, true); - Timeout timeout = new Timeout(Duration.create(waitInSeconds, "seconds")); - - Future<Object> future = Patterns.ask(wokenClient, queryMessage, timeout); - - QueryResult result; try { - result = (QueryResult) Await.result(future, timeout.duration()); + QueryResult result = askWoken(query, waitInSeconds); + return handleResponse.apply(result); } catch (Exception e) { - LOGGER.error("Cannot receive algorithm result from woken: " + e.getMessage(), e); - return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build(); + final String msg = "Cannot receive algorithm result from woken: " + e.getMessage(); + LOGGER.error(msg, e); + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(msg); } - - return handleResponse.apply(result); } protected <A extends Query> Future<Object> sendWokenQuery(A query, int timeout) { @@ -103,11 +99,6 @@ public abstract class WokenClientController { return Patterns.ask(wokenClient, queryMessage, timeout); } - protected ActorRef createActor(String actorBeanName, String actorName) { - return actorSystem.actorOf(SpringExtension.SPRING_EXTENSION_PROVIDER.get(actorSystem) - .props(actorBeanName), actorName); - } - protected ExecutionContext getExecutor() { return actorSystem.dispatcher(); } diff --git a/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java b/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java index 052486a5e..f4f67edd9 100644 --- a/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java +++ b/src/main/java/eu/hbp/mip/controllers/DatasetsApi.java @@ -5,7 +5,12 @@ package eu.hbp.mip.controllers; +import ch.chuv.lren.woken.messages.datasets.DatasetsQuery; +import ch.chuv.lren.woken.messages.datasets.DatasetsResponse; import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import eu.hbp.mip.akka.WokenClientController; import eu.hbp.mip.model.Dataset; import eu.hbp.mip.model.Variable; import eu.hbp.mip.repositories.VariableRepository; @@ -13,21 +18,25 @@ import io.swagger.annotations.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import scala.Option; import javax.annotation.PostConstruct; +import java.util.Set; +import java.util.stream.Stream; + import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @RestController @RequestMapping(value = "/datasets", produces = {APPLICATION_JSON_VALUE}) @Api(value = "/datasets", description = "the datasets API") -public class DatasetsApi { +public class DatasetsApi extends WokenClientController { private static final Logger LOGGER = LoggerFactory.getLogger(DatasetsApi.class); private static final Gson gson = new Gson(); @@ -35,15 +44,15 @@ public class DatasetsApi { @Autowired private VariableRepository variableRepository; - @Value("#{'${spring.featuresDatasource.datasets:adni,ppmi,edsd}'}") - private String datasets; - @PostConstruct - public void init() { - for (String dataset: datasets.split(",")) { - Variable v = variableRepository.findOne(dataset); + public void init() throws Exception { + // Pre-fill the local variable repository with the list of datasets, interpreted here as variables + // (a bit like a categorical variable can be split into a set of variables (a.k.a one hot encoding in Data science) ) + for (ch.chuv.lren.woken.messages.datasets.Dataset dataset: fetchDatasets()) { + final String code = dataset.dataset().code(); + Variable v = variableRepository.findOne(code); if (v == null) { - v = new Variable(dataset); + v = new Variable(code); variableRepository.save(v); } } @@ -55,7 +64,27 @@ public class DatasetsApi { ) { LOGGER.info("Get dataset list"); - return ResponseEntity.ok(datasets.split(",")); + try { + JsonArray datasets = new JsonArray(); + Stream<JsonObject> values = fetchDatasets().stream().map(d -> { + JsonObject jsObject = new JsonObject(); + jsObject.addProperty("code", d.dataset().code()); + jsObject.addProperty("label", d.label()); + datasets.add(jsObject); + return jsObject; + }); + + return ResponseEntity.ok(datasets); + } catch (Exception e) { + final String msg = "Cannot receive datasets from woken: " + e.getMessage(); + LOGGER.error(msg, e); + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(msg); + } + } + private Set<ch.chuv.lren.woken.messages.datasets.Dataset> fetchDatasets() throws Exception { + DatasetsResponse result = askWoken(new DatasetsQuery(Option.empty()), 30); + return scala.collection.JavaConversions.setAsJavaSet(result.datasets()); + } } diff --git a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java index f25187d58..5e7f36b2d 100644 --- a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java +++ b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java @@ -35,7 +35,7 @@ public class MethodsApi extends WokenClientController { public ResponseEntity listAvailableMethodsAndValidations() { LOGGER.info("List available methods and validations"); - return askWoken(MethodsQuery$.MODULE$, 10, r -> { + return requestWoken(MethodsQuery$.MODULE$, 10, r -> { MethodsResponse result = (MethodsResponse) r; // >> Temporary : should return result.methods() in the future -- GitLab