diff --git a/pom.xml b/pom.xml
index 24e95d4..365a18c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
1.3.1
0.3.2
- 1.19.3
+ 1.19
2.8.0
3.3.0
@@ -34,6 +34,33 @@
1.8
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.3
+
+
+
+ package
+
+ shade
+
+
+ gradoop-demo-shaded
+
+
+
+ org.gradoop.demo.server.Server
+
+
+ reference.conf
+
+
+
+
+
+
@@ -43,6 +70,16 @@
org.gradoop
gradoop-flink
${dep.gradoop.version}
+
+
+ org.apache.hadoop
+ hadoop-common
+
+
+ org.apache.flink
+ flink-hadoop-compatibility_2.11
+
+
@@ -50,12 +87,29 @@
org.apache.flink
flink-java
${dep.flink.version}
+
+
+ org.apache.hadoop
+ hadoop-common
+
+
+ org.apache.flink
+ flink-shaded-hadoop2
+
+
+
org.apache.flink
flink-clients_2.11
${dep.flink.version}
+
+
+ org.apache.flink
+ flink-shaded-hadoop2
+
+
@@ -77,5 +131,39 @@
${dep.jersey.version}
+
+
+ org.apache.hadoop
+ hadoop-hdfs
+ 2.8.3
+
+
+ org.apache.hadoop
+ hadoop-hdfs
+ 2.8.3
+ test-jar
+
+
+ org.apache.hadoop
+ hadoop-common
+ 2.8.3
+ test-jar
+
+
+ org.apache.hadoop
+ hadoop-client
+ 2.8.3
+
+
+ org.apache.hadoop
+ hadoop-hdfs-client
+ 2.8.3
+
+
+ junit
+ junit
+ 4.12
+ test
+
-
\ No newline at end of file
+
diff --git a/src/main/java/org/gradoop/demo/server/Constants.java b/src/main/java/org/gradoop/demo/server/Constants.java
new file mode 100644
index 0000000..44d80e7
--- /dev/null
+++ b/src/main/java/org/gradoop/demo/server/Constants.java
@@ -0,0 +1,18 @@
+package org.gradoop.demo.server;
+
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+import static java.util.Collections.unmodifiableSet;
+
+public final class Constants {
+ static final Set BUNDLED_DATABASE_NAMES =
+ unmodifiableSet(newHashSet("Pokec_Sample", "Graphalytics_SF1_Sample", "Example"));
+
+ static final Set GRADOOP_FILE_NAMES =
+ unmodifiableSet(newHashSet("metadata.csv", "vertices.csv", "edges.csv"));
+
+ static final String DATASOURCES_NAME_KEY = "datasourceNames";
+ private Constants() {
+ }
+}
diff --git a/src/main/java/org/gradoop/demo/server/FetchStatus.java b/src/main/java/org/gradoop/demo/server/FetchStatus.java
new file mode 100644
index 0000000..0144da4
--- /dev/null
+++ b/src/main/java/org/gradoop/demo/server/FetchStatus.java
@@ -0,0 +1,32 @@
+package org.gradoop.demo.server;
+
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+final class FetchStatus {
+ enum Status {
+ FETCH_ERROR,
+ FETCHED_FROM_HDFS,
+ PRESENT_LOCALLY
+ }
+ private final String name;
+ private final Status status;
+
+ FetchStatus(String name, Status status) {
+ requireNonNull(name);
+ requireNonNull(status);
+ this.name = name;
+ this.status = status;
+ }
+ String getName() {
+ return name;
+ }
+ Status getStatus() {
+ return status;
+ }
+ @Override
+ public String toString() {
+ return "[name: " + name + ", status: " + status + "]";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/gradoop/demo/server/GradoopGraphsetStore.java b/src/main/java/org/gradoop/demo/server/GradoopGraphsetStore.java
new file mode 100644
index 0000000..678300b
--- /dev/null
+++ b/src/main/java/org/gradoop/demo/server/GradoopGraphsetStore.java
@@ -0,0 +1,49 @@
+package org.gradoop.demo.server;
+
+import org.gradoop.flink.io.api.DataSource;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Represents a Store for Graphsets.
+ */
+interface GradoopGraphsetStore {
+ /**
+ * Returns a {@linkplain List} of names of {@linkplain DataSource}s that are available for exploration. A DataSource
+ * could be a set of files, for instance, if the DataSource is a {@linkplain org.gradoop.flink.io.impl.csv.CSVDataSource},
+ * then it is a folder with three files: vertices.csv, edges.csv, and metadata.csv.
+ */
+ Set getDataSourceNames();
+
+ /**
+ * Returns the absolute path of the files that represent this data source. Remember that every data source
+ * is a collection of three files: vertices.csv, edges.csv, and metadata.csv.
+ * @param dataSourceName
+ * @return a String representing the absolute path of the datasource, null otherwise
+ */
+ String getPath(String dataSourceName);
+
+ /**
+ * Updates the Gradoop Graphsets from remote (HDFS, e.g.) location. It returns a list of strings
+ * indicating the status of the refresh operation. A graphset that is available locally is fetched again
+ * when this operation is done.
+ *
+ *
+ * Details:
+ *
+ * Get the set of locally available graphsets (A)
+ * Get the set of graphsets available in HDFS (B)
+ * For each graphset b in B, remove it from A, (re) fetch it from HDFS, set its status as
+ * {@linkplain FetchStatus.Status#FETCHED_FROM_HDFS}, add the status to the return set (C)
+ * For each graphset a in A, set a status {@linkplain FetchStatus.Status#PRESENT_LOCALLY}
+ * Return C
+ *
+ *
+ */
+ Set refresh() throws IOException;
+
+ /** Decides whether this store is "local-only" */
+ boolean isLocal();
+}
diff --git a/src/main/java/org/gradoop/demo/server/HdfsGradoopGraphsetStore.java b/src/main/java/org/gradoop/demo/server/HdfsGradoopGraphsetStore.java
new file mode 100644
index 0000000..c072b57
--- /dev/null
+++ b/src/main/java/org/gradoop/demo/server/HdfsGradoopGraphsetStore.java
@@ -0,0 +1,123 @@
+package org.gradoop.demo.server;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.fs.LocatedFileStatus;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.RemoteIterator;
+import org.apache.hadoop.hdfs.HdfsConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Objects.requireNonNull;
+import static org.gradoop.demo.server.Constants.GRADOOP_FILE_NAMES;
+
+/**
+ * Represents a store of graphsets that are available to explore using Gradoop and that are stored in HDFS.
+ */
+public class HdfsGradoopGraphsetStore extends Configured {
+
+ public static final String DEFAULT_BASE_PATH_IN_HDFS = "/app/ugraph/gradoop-graphsets/";
+ private static final Logger log = LoggerFactory.getLogger(HdfsGradoopGraphsetStore.class);
+
+ private final String basePath;
+ private final Configuration config;
+
+ public HdfsGradoopGraphsetStore() {
+ this(new Configuration(), DEFAULT_BASE_PATH_IN_HDFS);
+ }
+
+ public HdfsGradoopGraphsetStore(Configuration config, String basePath) {
+ requireNonNull(config);
+ requireNonNull(basePath);
+ this.basePath = basePath;
+ this.config = config;
+ this.config.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());
+ this.config.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName());
+ }
+
+ public Set getDataSourceNames() throws IOException {
+ Path basePath = new Path(this.basePath);
+ FileSystem fs = basePath.getFileSystem(config);
+// if (!fs.getFileStatus(basePath).isDirectory()) {
+// throw new RuntimeException("path is not a directory: " + basePath);
+// }
+ Set dataSources = new HashSet<>(16); // expected to be fewer than this
+ try {
+ RemoteIterator iter = fs.listFiles(basePath, true);
+ while (iter.hasNext()) {
+ LocatedFileStatus fstat = iter.next();
+ String name = getGradoopGraphsetName(fstat.getPath().toUri().getPath());
+ if (name != null && ! dataSources.contains(name)) {
+ boolean added = dataSources.add(name);
+ assert added;
+ log.debug("adding graphset: {}", name);
+ }
+ }
+ } catch (Exception e) {
+ throw new IOException(e);
+ } finally {
+ if (fs != null) {
+ fs.close();
+ }
+ }
+ return dataSources;
+ }
+
+ @Override
+ public String toString() {
+ return "[fs.default.name:" + config.get("fs.default.name") + ", fs.hdfs.impl: " +
+ config.get("fs.hdfs.impl") + ", basePath: " + basePath + "]";
+ }
+
+ private String getGradoopGraphsetName(String path) {
+ //TODO improve this logic
+ String prefix = basePath;
+ String rem = path.substring(prefix.length());
+ int fsi = rem.indexOf('/'); // index of first slash in rem e.g. "one/foo"
+ if (fsi < 0) {
+ log.debug("Returning null, this is not a gradoop graphset: {}", path);
+ return null;
+ }
+ String folder = rem.substring(0, fsi);
+ if (rem.length() - folder.length() > 1) {
+ return folder;
+ }
+ log.debug("Returning null, this is not a gradoop graphset: {}", path);
+ return null;
+ }
+
+ /* package-private */void copyGradoopFiles(String graphsetName, File localBase) throws Exception {
+ // copying all the files is critical, so make it an all-or-nothing operations, cleaning up
+ // however, transactional semantics are not intended here
+ Path basePath = new Path(this.basePath);
+ FileSystem fs = basePath.getFileSystem(config);
+ File localGraphsetFolder = new File(localBase, graphsetName);
+ boolean a = localGraphsetFolder.mkdirs();
+ if (! a) {
+ throw new RuntimeException("Unlikely error in making the local folder: " + localGraphsetFolder);
+ }
+ Path localPath = new Path(localGraphsetFolder.getAbsolutePath());
+ try {
+ for (String f : GRADOOP_FILE_NAMES) {
+ Path remotePath = new Path(this.basePath + "/" + graphsetName + "/" + f);
+ fs.copyToLocalFile(false, remotePath, localPath);
+ log.info("Copied {} to {}", remotePath.toString(), localPath);
+ File gf = new File(localPath.toString(), f);
+ log.debug("File {} -- is it copied? : {}", gf.getAbsolutePath(), gf.exists());
+ }
+ } catch (Exception e) {
+ log.warn("Error copying graphset: {}, deleting the whole folder: " + e.getMessage());
+ FileUtil.fullyDelete(localGraphsetFolder);
+ throw e; //rethrow
+ }
+ }
+}
diff --git a/src/main/java/org/gradoop/demo/server/LocalGradoopGraphsetStore.java b/src/main/java/org/gradoop/demo/server/LocalGradoopGraphsetStore.java
new file mode 100644
index 0000000..b261513
--- /dev/null
+++ b/src/main/java/org/gradoop/demo/server/LocalGradoopGraphsetStore.java
@@ -0,0 +1,117 @@
+package org.gradoop.demo.server;
+
+import org.apache.hadoop.conf.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Arrays.stream;
+import static java.util.Collections.emptySet;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.toSet;
+import static org.gradoop.demo.server.FetchStatus.Status.FETCHED_FROM_HDFS;
+import static org.gradoop.demo.server.FetchStatus.Status.FETCH_ERROR;
+import static org.gradoop.demo.server.FetchStatus.Status.PRESENT_LOCALLY;
+
+class LocalGradoopGraphsetStore implements GradoopGraphsetStore {
+
+ private static final Logger log = LoggerFactory.getLogger(LocalGradoopGraphsetStore.class);
+ static final String DEFAULT_LOCAL_PATH = System.getProperty("user.dir") + "/target/classes/data";
+ private final File localBase;
+ private final HdfsGradoopGraphsetStore hdfsStore;
+
+ LocalGradoopGraphsetStore(Configuration config, String localPath) {
+ this(config, HdfsGradoopGraphsetStore.DEFAULT_BASE_PATH_IN_HDFS, localPath);
+ }
+
+ LocalGradoopGraphsetStore(Configuration config, String remoteBasePath, String localPath) {
+ requireNonNull(remoteBasePath);
+ requireNonNull(localPath);
+ localBase = Paths.get(localPath).toFile();
+ if (!localBase.isDirectory()) {
+ throw new IllegalArgumentException("not a directory: " + localBase);
+ }
+ if (config != null) {
+ hdfsStore = new HdfsGradoopGraphsetStore(config, remoteBasePath);
+ } else {
+ hdfsStore = null; // we are configured to run off local
+ }
+ }
+
+ @Override
+ public Set getDataSourceNames() {
+ // we are sure here that localBase is a directory!
+ return stream(localBase.listFiles(File::isDirectory)).map(File::getName).collect(toSet());
+ }
+
+ @Override
+ public String getPath(String dataSourceName) {
+ return localBase.getAbsolutePath() + "/" + dataSourceName;
+ }
+
+ @Override
+ public Set refresh() throws IOException {
+ if (hdfsStore == null) {
+ return emptySet();
+ }
+ Set localNames = this.getDataSourceNames();
+ Set remoteNames = hdfsStore.getDataSourceNames();
+ Set result = new HashSet<>(remoteNames.size() + localNames.size());
+ for (String remoteName : remoteNames) {
+ FetchStatus fetched = fetch(remoteName);
+ if (fetched.getStatus() == FETCHED_FROM_HDFS) {
+ boolean a = result.add(fetched);
+ assert a;
+ boolean b = localNames.remove(remoteName);
+ if (!b) {
+ log.debug("graphset was not available locally: ", remoteName);
+ }
+ log.info("**********************************************");
+ log.info("Graphset was copied from HDFS: {}", remoteName);
+ log.info("**********************************************");
+ }
+ }
+ // remaining
+ localNames.forEach(name -> {
+ FetchStatus e = new FetchStatus(name, PRESENT_LOCALLY);
+ log.info("**********************************************");
+ log.info("Graphset was present locally: {}", name);
+ log.info("**********************************************");
+ result.add(e);
+ });
+ return result;
+ }
+
+ @Override
+ public boolean isLocal() {
+ return this.hdfsStore == null;
+ }
+
+ /**
+ * Fetch the required files (metadata.csv, vertices.csv, edges.csv) for the given Gradoop graphset name
+ * the files are copied to {@linkplain #localBase}. The structure would be:
+ */
+ private FetchStatus fetch(String graphsetName) {
+ try {
+ hdfsStore.copyGradoopFiles(graphsetName, localBase);
+ return new FetchStatus(graphsetName, FETCHED_FROM_HDFS);
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ log.warn("{} could not be fetched from HDFS", graphsetName);
+ return new FetchStatus(graphsetName, FETCH_ERROR);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String hdfs = this.hdfsStore == null ? null : this.hdfsStore.toString();
+ return "**** [HDFS Store: " + hdfs + ", Local Base Path: " +
+ this.localBase.getAbsolutePath() + "] ****";
+ }
+}
diff --git a/src/main/java/org/gradoop/demo/server/RequestHandler.java b/src/main/java/org/gradoop/demo/server/RequestHandler.java
index 9f2a369..1389ce2 100644
--- a/src/main/java/org/gradoop/demo/server/RequestHandler.java
+++ b/src/main/java/org/gradoop/demo/server/RequestHandler.java
@@ -17,7 +17,6 @@
package org.gradoop.demo.server;
import org.apache.commons.lang.ArrayUtils;
-import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.io.LocalCollectionOutputFormat;
import org.apache.flink.api.java.tuple.Tuple3;
import org.codehaus.jettison.json.JSONArray;
@@ -26,7 +25,12 @@
import org.gradoop.common.model.impl.pojo.Edge;
import org.gradoop.common.model.impl.pojo.GraphHead;
import org.gradoop.common.model.impl.pojo.Vertex;
-import org.gradoop.demo.server.functions.*;
+import org.gradoop.demo.server.functions.AcceptNoneFilter;
+import org.gradoop.demo.server.functions.LabelFilter;
+import org.gradoop.demo.server.functions.LabelGroupReducer;
+import org.gradoop.demo.server.functions.LabelMapper;
+import org.gradoop.demo.server.functions.LabelReducer;
+import org.gradoop.demo.server.functions.PropertyKeyMapper;
import org.gradoop.demo.server.pojo.GroupingRequest;
import org.gradoop.flink.io.impl.csv.CSVDataSource;
import org.gradoop.flink.model.api.epgm.GraphCollection;
@@ -41,8 +45,6 @@
import org.gradoop.flink.model.impl.operators.matching.common.statistics.GraphStatistics;
import org.gradoop.flink.util.GradoopFlinkConfig;
-import javax.ws.rs.*;
-import javax.ws.rs.core.Response;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
@@ -54,404 +56,443 @@
import java.util.List;
import java.util.Set;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+import static org.gradoop.demo.server.Constants.DATASOURCES_NAME_KEY;
+import static org.gradoop.demo.server.Server.ENV;
+import static org.gradoop.demo.server.Server.LOCAL_STORE;
+
/**
* Handles REST requests to the server.
*/
@Path("")
public class RequestHandler {
- private final String META_FILENAME = "/metadata.json";
-
- private static final ExecutionEnvironment ENV = ExecutionEnvironment.createLocalEnvironment();
- private GradoopFlinkConfig config = GradoopFlinkConfig.createConfig(ENV);
-
- /**
- * Takes a database name via a POST request and returns the keys of all
- * vertex and edge properties, and a boolean value specifying if the property has a numerical
- * type. The return is a string in the JSON format, for easy usage in a JavaScript web page.
- *
- * @param databaseName name of the loaded database
- * @return A JSON containing the vertices and edges property keys
- */
- @POST
- @Path("/keys/{databaseName}")
- @Produces("application/json;charset=utf-8")
- public Response getKeysAndLabels(@PathParam("databaseName") String databaseName) {
- URL meta = RequestHandler.class.getResource("/data/" + databaseName + META_FILENAME);
- try {
- if (meta == null) {
- JSONObject result = computeKeysAndLabels(databaseName);
- if (result == null) {
- return Response.serverError().build();
+ private final String META_FILENAME = "/metadata.json";
+
+ private GradoopFlinkConfig config = GradoopFlinkConfig.createConfig(ENV);
+
+ static JSONObject toJson(Set dataSourceNames) throws JSONException {
+ // caters to a drop-down
+ JSONObject result = new JSONObject();
+ JSONArray array = new JSONArray(dataSourceNames);
+ result.put(DATASOURCES_NAME_KEY, array);
+ return result;
+ }
+
+ /**
+ * Returns the names of the databases to explore.
+ * Each database is a folder at a given location.
+ */
+ @GET
+ @Path("/dbnames")
+ @Produces("application/json;charset=utf-8")
+ public Response getDatabaseNames() throws JSONException {
+ // always refresh from HDFS todo provide a flag?
+ try {
+ LOCAL_STORE.refresh();
+ } catch (IOException e) {
+ // squelching exception here because we do not want to disrupt the other flow, let user use other datasets
+ e.printStackTrace(System.err);
}
+ JSONObject result = toJson(LOCAL_STORE.getDataSourceNames());
return Response.ok(result.toString()).build();
- } else {
- JSONObject result = readKeysAndLabels(databaseName);
- if (result == null) {
- return Response.serverError().build();
+ }
+
+ /**
+ * Takes a database name via a POST request and returns the keys of all
+ * vertex and edge properties, and a boolean value specifying if the property has a numerical
+ * type. The return is a string in the JSON format, for easy usage in a JavaScript web page.
+ *
+ * @param databaseName name of the loaded database
+ * @return A JSON containing the vertices and edges property keys
+ */
+ @POST
+ @Path("/keys/{databaseName}")
+ @Produces("application/json;charset=utf-8")
+ public Response getKeysAndLabels(@PathParam("databaseName") String databaseName) {
+ URL meta = RequestHandler.class.getResource("/data/" + databaseName + META_FILENAME);
+ try {
+ if (meta == null) {
+ JSONObject result = computeKeysAndLabels(databaseName);
+ if (result == null) {
+ return Response.serverError().build();
+ }
+ return Response.ok(result.toString()).build();
+ } else {
+ JSONObject result = readKeysAndLabels(databaseName);
+ if (result == null) {
+ return Response.serverError().build();
+ }
+ return Response.ok(readKeysAndLabels(databaseName).toString()).build();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // if any exception is thrown, return an error to the client
+ return Response.serverError().build();
}
- return Response.ok(readKeysAndLabels(databaseName).toString()).build();
- }
- } catch (Exception e) {
- e.printStackTrace();
- // if any exception is thrown, return an error to the client
- return Response.serverError().build();
}
- }
-
- @POST
- @Path("/cypher")
- @Produces("application/x-www-form-urlencoded;charset=utf-8")
- public Response executeCypher(
- @FormParam("databaseName") String databaseName,
- @FormParam("query") String query,
- @DefaultValue("false") @FormParam("attacheData") boolean attacheData) {
- //load the database
- String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
-
- CSVDataSource source = new CSVDataSource(path, config);
-
- LogicalGraph graph = source.getLogicalGraph();
-
- // TODO load proper statistics
- GraphStatistics graphStatistics = new GraphStatistics(1, 1, 1, 1);
- GraphCollection res = graph.cypher(query,attacheData, MatchStrategy.HOMOMORPHISM, MatchStrategy.ISOMORPHISM, graphStatistics);
-
- return createResponse(res);
- }
-
- /**
- * Compute property keys and labels.
- * @param databaseName name of the database
- * @return JSONObject containing property keys and labels
- */
- private JSONObject computeKeysAndLabels(String databaseName) throws IOException {
-
- String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
-
- CSVDataSource source = new CSVDataSource(path, config);
-
- LogicalGraph graph = source.getLogicalGraph();
-
- JSONObject jsonObject = new JSONObject();
-
- //compute the vertex and edge property keys and return them
- try {
- jsonObject.put("vertexKeys", getVertexKeys(graph));
- jsonObject.put("edgeKeys", getEdgeKeys(graph));
- jsonObject.put("vertexLabels", getVertexLabels(graph));
- jsonObject.put("edgeLabels", getEdgeLabels(graph));
- String dataPath = RequestHandler.class.getResource("/data/" + databaseName).getFile();
- FileWriter writer = new FileWriter(dataPath + META_FILENAME);
- jsonObject.write(writer);
- writer.flush();
- writer.close();
-
- return jsonObject;
- } catch (Exception e) {
- e.printStackTrace();
- // if any exception is thrown, return an error to the client
- return null;
+
+ @POST
+ @Path("/cypher")
+ @Produces("application/x-www-form-urlencoded;charset=utf-8")
+ public Response executeCypher(
+ @FormParam("databaseName") String databaseName,
+ @FormParam("query") String query,
+ @DefaultValue("false") @FormParam("attacheData") boolean attacheData) {
+ //load the database
+ String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
+
+ CSVDataSource source = new CSVDataSource(path, config);
+
+ LogicalGraph graph = source.getLogicalGraph();
+
+ // TODO load proper statistics
+ GraphStatistics graphStatistics = new GraphStatistics(1, 1, 1, 1);
+ GraphCollection res = graph.cypher(query, attacheData, MatchStrategy.HOMOMORPHISM, MatchStrategy.ISOMORPHISM, graphStatistics);
+
+ return createResponse(res);
+ }
+
+ /**
+ * Compute property keys and labels.
+ *
+ * @param databaseName name of the database
+ * @return JSONObject containing property keys and labels
+ */
+ private JSONObject computeKeysAndLabels(String databaseName) throws IOException {
+
+ String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
+
+ CSVDataSource source = new CSVDataSource(path, config);
+
+ LogicalGraph graph = source.getLogicalGraph();
+
+ JSONObject jsonObject = new JSONObject();
+
+ //compute the vertex and edge property keys and return them
+ try {
+ jsonObject.put("vertexKeys", getVertexKeys(graph));
+ jsonObject.put("edgeKeys", getEdgeKeys(graph));
+ jsonObject.put("vertexLabels", getVertexLabels(graph));
+ jsonObject.put("edgeLabels", getEdgeLabels(graph));
+ String dataPath = RequestHandler.class.getResource("/data/" + databaseName).getFile();
+ FileWriter writer = new FileWriter(dataPath + META_FILENAME);
+ jsonObject.write(writer);
+ writer.flush();
+ writer.close();
+
+ return jsonObject;
+ } catch (Exception e) {
+ e.printStackTrace();
+ // if any exception is thrown, return an error to the client
+ return null;
+ }
}
- }
-
- /**
- * Read the property keys and labels from the buffered JSON.
- * @param databaseName name of the database
- * @return JSONObject containing the property keys and labels
- * @throws IOException if reading fails
- * @throws JSONException if JSON creation fails
- */
- private JSONObject readKeysAndLabels(String databaseName) throws IOException, JSONException {
- String dataPath = RequestHandler.class.getResource("/data/" + databaseName).getFile();
- String content =
- new String(Files.readAllBytes(Paths.get(dataPath + META_FILENAME)), StandardCharsets.UTF_8);
-
- return new JSONObject(content);
- }
-
- /**
- * Takes any given graph and creates a JSONArray containing the vertex property keys and a
- * boolean,
- * specifying it the property has a numerical type.
- *
- * @param graph input graph
- * @return JSON array with property keys and boolean, that is true if the property type is
- * numercial
- * @throws Exception if the collecting of the distributed data fails
- */
- private JSONArray getVertexKeys(LogicalGraph graph) throws Exception {
-
- List, String, Boolean>> vertexKeys = graph.getVertices()
- .flatMap(new PropertyKeyMapper<>())
- .groupBy(1)
- .reduceGroup(new LabelGroupReducer())
- .collect();
-
- return buildArrayFromKeys(vertexKeys);
- }
-
- /**
- * Takes any given graph and creates a JSONArray containing the edge property keys and a boolean,
- * specifying it the property has a numerical type.
- *
- * @param graph input graph
- * @return JSON array with property keys and boolean, that is true if the property type is
- * numercial
- * @throws Exception if the collecting of the distributed data fails
- */
- private JSONArray getEdgeKeys(LogicalGraph graph) throws Exception {
-
- List, String, Boolean>> edgeKeys = graph.getEdges()
- .flatMap(new PropertyKeyMapper<>())
- .groupBy(1)
- .reduceGroup(new LabelGroupReducer())
- .collect();
-
- return buildArrayFromKeys(edgeKeys);
- }
-
- /**
- * Convenience method.
- * Takes a set of tuples of property keys and booleans, specifying if the property is numerical,
- * and creates a JSON array containing the same data.
- *
- * @param keys set of tuples of property keys and booleans, that are true if the property type
- * is numerical
- * @return JSONArray containing the same data as the input
- * @throws JSONException if the construction of the JSON fails
- */
- private JSONArray buildArrayFromKeys(List, String, Boolean>> keys)
- throws JSONException {
- JSONArray keyArray = new JSONArray();
- for(Tuple3, String, Boolean> key : keys) {
- JSONObject keyObject = new JSONObject();
- JSONArray labels = new JSONArray();
- key.f0.forEach(labels::put);
- keyObject.put("labels", labels);
- keyObject.put("name", key.f1);
- keyObject.put("numerical", key.f2);
- keyArray.put(keyObject);
+
+ /**
+ * Read the property keys and labels from the buffered JSON.
+ *
+ * @param databaseName name of the database
+ * @return JSONObject containing the property keys and labels
+ * @throws IOException if reading fails
+ * @throws JSONException if JSON creation fails
+ */
+ private JSONObject readKeysAndLabels(String databaseName) throws IOException, JSONException {
+ String dataPath = RequestHandler.class.getResource("/data/" + databaseName).getFile();
+ String content =
+ new String(Files.readAllBytes(Paths.get(dataPath + META_FILENAME)), StandardCharsets.UTF_8);
+
+ return new JSONObject(content);
}
- return keyArray;
- }
-
- /**
- * Compute the labels of the vertices.
- *
- * @param graph logical graph
- * @return JSONArray containing the vertex labels
- * @throws Exception if the computation fails
- */
- private JSONArray getVertexLabels(LogicalGraph graph) throws Exception {
- List> vertexLabels = graph.getVertices()
- .map(new LabelMapper<>())
- .reduce(new LabelReducer())
- .collect();
-
- if(vertexLabels.size() > 0) {
- return buildArrayFromLabels(vertexLabels.get(0));
- } else {
- return new JSONArray();
+
+ /**
+ * Takes any given graph and creates a JSONArray containing the vertex property keys and a
+ * boolean,
+ * specifying it the property has a numerical type.
+ *
+ * @param graph input graph
+ * @return JSON array with property keys and boolean, that is true if the property type is
+ * numercial
+ * @throws Exception if the collecting of the distributed data fails
+ */
+ private JSONArray getVertexKeys(LogicalGraph graph) throws Exception {
+
+ List, String, Boolean>> vertexKeys = graph.getVertices()
+ .flatMap(new PropertyKeyMapper<>())
+ .groupBy(1)
+ .reduceGroup(new LabelGroupReducer())
+ .collect();
+
+ return buildArrayFromKeys(vertexKeys);
}
- }
-
- /**
- * Compute the labels of the edges.
- *
- * @param graph logical graph
- * @return JSONArray containing the edge labels
- * @throws Exception if the computation fails
- */
- private JSONArray getEdgeLabels(LogicalGraph graph ) throws Exception {
- List> edgeLabels = graph.getEdges()
- .map(new LabelMapper<>())
- .reduce(new LabelReducer())
- .collect();
-
- if(edgeLabels.size() > 0) {
- return buildArrayFromLabels(edgeLabels.get(0));
- } else {
- return new JSONArray();
+
+ /**
+ * Takes any given graph and creates a JSONArray containing the edge property keys and a boolean,
+ * specifying it the property has a numerical type.
+ *
+ * @param graph input graph
+ * @return JSON array with property keys and boolean, that is true if the property type is
+ * numercial
+ * @throws Exception if the collecting of the distributed data fails
+ */
+ private JSONArray getEdgeKeys(LogicalGraph graph) throws Exception {
+
+ List, String, Boolean>> edgeKeys = graph.getEdges()
+ .flatMap(new PropertyKeyMapper<>())
+ .groupBy(1)
+ .reduceGroup(new LabelGroupReducer())
+ .collect();
+
+ return buildArrayFromKeys(edgeKeys);
}
- }
-
- /**
- * Create a JSON array from the sets of labels.
- *
- * @param labels set of labels
- * @return JSON array of labels
- */
- private JSONArray buildArrayFromLabels(Set labels) {
- JSONArray labelArray = new JSONArray();
- labels.forEach(labelArray::put);
- return labelArray;
- }
-
- /**
- * Get the complete graph in cytoscape-conform form.
- *
- * @param databaseName name of the database
- * @return Response containing the graph as a JSON, in cytoscape conform format.
- * @throws JSONException if JSON creation fails
- * @throws IOException if reading fails
- */
-
- @POST
- @Path("/graph/{databaseName}")
- @Produces("application/json;charset=utf-8")
- public Response getGraph(@PathParam("databaseName") String databaseName) throws Exception {
-
- String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
-
- CSVDataSource source = new CSVDataSource(path, config);
-
- LogicalGraph graph = source.getLogicalGraph();
-
- String json = CytoJSONBuilder.getJSONString(
- graph.getGraphHead().collect(),
- graph.getVertices().collect(),
- graph.getEdges().collect());
-
- return Response.ok(json).build();
- }
-
-
-
- /**
- * Takes a {@link GroupingRequest}, executes a grouping with the parameters it contains and
- * returns the results as a JSON.
- *
- * @param request GroupingRequest send to the server, containing the parameters for a
- * {@link Grouping}.
- * @return a JSON containing the result of the executed Grouping, a graph
- * @throws Exception if the collecting of the distributed data fails
- */
- @POST
- @Path("/grouping")
- @Produces("application/json;charset=utf-8")
- public Response getData(GroupingRequest request) throws Exception {
-
- //load the database
- String databaseName = request.getDbName();
-
- String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
-
- CSVDataSource source = new CSVDataSource(path, config);
-
- LogicalGraph graph = source.getLogicalGraph();
-
- //if no edges are requested, remove them as early as possible
- //else, apply the normal filters
- if(request.getFilterAllEdges()) {
- graph = graph.subgraph(new LabelFilter<>(request.getVertexFilters()),
- new AcceptNoneFilter<>());
- } else{
- graph = graph.subgraph(new LabelFilter<>(request.getVertexFilters()),
- new LabelFilter<>(request.getEdgeFilters()));
+
+ /**
+ * Convenience method.
+ * Takes a set of tuples of property keys and booleans, specifying if the property is numerical,
+ * and creates a JSON array containing the same data.
+ *
+ * @param keys set of tuples of property keys and booleans, that are true if the property type
+ * is numerical
+ * @return JSONArray containing the same data as the input
+ * @throws JSONException if the construction of the JSON fails
+ */
+ private JSONArray buildArrayFromKeys(List, String, Boolean>> keys)
+ throws JSONException {
+ JSONArray keyArray = new JSONArray();
+ for (Tuple3, String, Boolean> key : keys) {
+ JSONObject keyObject = new JSONObject();
+ JSONArray labels = new JSONArray();
+ key.f0.forEach(labels::put);
+ keyObject.put("labels", labels);
+ keyObject.put("name", key.f1);
+ keyObject.put("numerical", key.f2);
+ keyArray.put(keyObject);
+ }
+ return keyArray;
}
- //construct the grouping with the parameters send by the request
- Grouping.GroupingBuilder builder = new Grouping.GroupingBuilder();
- int position;
- position = ArrayUtils.indexOf(request.getVertexKeys(), "label");
- if(position > -1) {
- builder.useVertexLabel(true);
- request.setVertexKeys((String[])ArrayUtils.remove(request.getVertexKeys(), position));
+ /**
+ * Compute the labels of the vertices.
+ *
+ * @param graph logical graph
+ * @return JSONArray containing the vertex labels
+ * @throws Exception if the computation fails
+ */
+ private JSONArray getVertexLabels(LogicalGraph graph) throws Exception {
+ List> vertexLabels = graph.getVertices()
+ .map(new LabelMapper<>())
+ .reduce(new LabelReducer())
+ .collect();
+
+ if (vertexLabels.size() > 0) {
+ return buildArrayFromLabels(vertexLabels.get(0));
+ } else {
+ return new JSONArray();
+ }
}
- builder.addVertexGroupingKeys(Arrays.asList(request.getVertexKeys()));
- position = ArrayUtils.indexOf(request.getEdgeKeys(), "label");
- if(position > -1) {
- builder.useEdgeLabel(true);
- request.setEdgeKeys((String[])ArrayUtils.remove(request.getEdgeKeys(), position));
+ /**
+ * Compute the labels of the edges.
+ *
+ * @param graph logical graph
+ * @return JSONArray containing the edge labels
+ * @throws Exception if the computation fails
+ */
+ private JSONArray getEdgeLabels(LogicalGraph graph) throws Exception {
+ List> edgeLabels = graph.getEdges()
+ .map(new LabelMapper<>())
+ .reduce(new LabelReducer())
+ .collect();
+
+ if (edgeLabels.size() > 0) {
+ return buildArrayFromLabels(edgeLabels.get(0));
+ } else {
+ return new JSONArray();
+ }
}
- builder.addEdgeGroupingKeys(Arrays.asList(request.getEdgeKeys()));
-
- String[] vertexAggrFuncs = request.getVertexAggrFuncs();
-
- for(String vertexAggrFunc : vertexAggrFuncs) {
- String[] split = vertexAggrFunc.split(" ");
- switch (split[0]) {
- case "max":
- builder.addVertexAggregator(new MaxAggregator(split[1], "max " + split[1]));
- break;
- case "min":
- builder.addVertexAggregator(new MinAggregator(split[1], "min " + split[1]));
- break;
- case "sum":
- builder.addVertexAggregator(new SumAggregator(split[1], "sum " + split[1]));
- break;
- case "count":
- builder.addVertexAggregator(new CountAggregator());
- break;
- }
+
+ /**
+ * Create a JSON array from the sets of labels.
+ *
+ * @param labels set of labels
+ * @return JSON array of labels
+ */
+ private JSONArray buildArrayFromLabels(Set labels) {
+ JSONArray labelArray = new JSONArray();
+ labels.forEach(labelArray::put);
+ return labelArray;
}
- String[] edgeAggrFuncs = request.getEdgeAggrFuncs();
-
- for(String edgeAggrFunc : edgeAggrFuncs) {
- String[] split = edgeAggrFunc.split(" ");
- switch (split[0]) {
- case "max":
- builder.addEdgeAggregator(new MaxAggregator(split[1], "max " + split[1]));
- break;
- case "min":
- builder.addEdgeAggregator(new MinAggregator(split[1], "min " + split[1]));
- break;
- case "sum":
- builder.addEdgeAggregator(new SumAggregator(split[1], "sum " + split[1]));
- break;
- case "count":
- builder.addEdgeAggregator(new CountAggregator());
- break;
- }
+ /**
+ * Get the complete graph in cytoscape-conform form.
+ *
+ * @param databaseName name of the database
+ * @return Response containing the graph as a JSON, in cytoscape conform format.
+ * @throws JSONException if JSON creation fails
+ * @throws IOException if reading fails
+ */
+
+ @POST
+ @Path("/graph/{databaseName}")
+ @Produces("application/json;charset=utf-8")
+ public Response getGraph(@PathParam("databaseName") String databaseName) throws Exception {
+
+ String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
+
+ CSVDataSource source = new CSVDataSource(path, config);
+
+ LogicalGraph graph = source.getLogicalGraph();
+
+ String json = CytoJSONBuilder.getJSONString(
+ graph.getGraphHead().collect(),
+ graph.getVertices().collect(),
+ graph.getEdges().collect());
+
+ return Response.ok(json).build();
}
- // by default, we use the group reduce strategy
- builder.setStrategy(GroupingStrategy.GROUP_REDUCE);
+ /**
+ * Takes a {@link GroupingRequest}, executes a grouping with the parameters it contains and
+ * returns the results as a JSON.
+ *
+ * @param request GroupingRequest send to the server, containing the parameters for a
+ * {@link Grouping}.
+ * @return a JSON containing the result of the executed Grouping, a graph
+ * @throws Exception if the collecting of the distributed data fails
+ */
+ @POST
+ @Path("/grouping")
+ @Produces("application/json;charset=utf-8")
+ public Response getData(GroupingRequest request) throws Exception {
+
+ //load the database
+ String databaseName = request.getDbName();
+
+ String path = RequestHandler.class.getResource("/data/" + databaseName).getPath();
+
+ CSVDataSource source = new CSVDataSource(path, config);
+
+ LogicalGraph graph = source.getLogicalGraph();
+
+ //if no edges are requested, remove them as early as possible
+ //else, apply the normal filters
+ if (request.getFilterAllEdges()) {
+ graph = graph.subgraph(new LabelFilter<>(request.getVertexFilters()),
+ new AcceptNoneFilter<>());
+ } else {
+ graph = graph.subgraph(new LabelFilter<>(request.getVertexFilters()),
+ new LabelFilter<>(request.getEdgeFilters()));
+ }
+
+ //construct the grouping with the parameters send by the request
+ Grouping.GroupingBuilder builder = new Grouping.GroupingBuilder();
+ int position;
+ position = ArrayUtils.indexOf(request.getVertexKeys(), "label");
+ if (position > -1) {
+ builder.useVertexLabel(true);
+ request.setVertexKeys((String[]) ArrayUtils.remove(request.getVertexKeys(), position));
+ }
+ builder.addVertexGroupingKeys(Arrays.asList(request.getVertexKeys()));
- graph = builder.build().execute(graph);
+ position = ArrayUtils.indexOf(request.getEdgeKeys(), "label");
+ if (position > -1) {
+ builder.useEdgeLabel(true);
+ request.setEdgeKeys((String[]) ArrayUtils.remove(request.getEdgeKeys(), position));
+ }
+ builder.addEdgeGroupingKeys(Arrays.asList(request.getEdgeKeys()));
+
+ String[] vertexAggrFuncs = request.getVertexAggrFuncs();
+
+ for (String vertexAggrFunc : vertexAggrFuncs) {
+ String[] split = vertexAggrFunc.split(" ");
+ switch (split[0]) {
+ case "max":
+ builder.addVertexAggregator(new MaxAggregator(split[1], "max " + split[1]));
+ break;
+ case "min":
+ builder.addVertexAggregator(new MinAggregator(split[1], "min " + split[1]));
+ break;
+ case "sum":
+ builder.addVertexAggregator(new SumAggregator(split[1], "sum " + split[1]));
+ break;
+ case "count":
+ builder.addVertexAggregator(new CountAggregator());
+ break;
+ }
+ }
- // specify the output collections
- return createResponse(graph);
- }
+ String[] edgeAggrFuncs = request.getEdgeAggrFuncs();
+
+ for (String edgeAggrFunc : edgeAggrFuncs) {
+ String[] split = edgeAggrFunc.split(" ");
+ switch (split[0]) {
+ case "max":
+ builder.addEdgeAggregator(new MaxAggregator(split[1], "max " + split[1]));
+ break;
+ case "min":
+ builder.addEdgeAggregator(new MinAggregator(split[1], "min " + split[1]));
+ break;
+ case "sum":
+ builder.addEdgeAggregator(new SumAggregator(split[1], "sum " + split[1]));
+ break;
+ case "count":
+ builder.addEdgeAggregator(new CountAggregator());
+ break;
+ }
+ }
- private Response createResponse(GraphCollection graph) {
- List resultHead = new ArrayList<>();
- List resultVertices = new ArrayList<>();
- List resultEdges = new ArrayList<>();
+ // by default, we use the group reduce strategy
+ builder.setStrategy(GroupingStrategy.GROUP_REDUCE);
- graph.getGraphHeads().output(new LocalCollectionOutputFormat<>(resultHead));
- graph.getVertices().output(new LocalCollectionOutputFormat<>(resultVertices));
- graph.getEdges().output(new LocalCollectionOutputFormat<>(resultEdges));
+ graph = builder.build().execute(graph);
- return getResponse(resultHead, resultVertices, resultEdges);
- }
+ // specify the output collections
+ return createResponse(graph);
+ }
- private Response createResponse(LogicalGraph graph) {
- List resultHead = new ArrayList<>();
- List resultVertices = new ArrayList<>();
- List resultEdges = new ArrayList<>();
+ private Response createResponse(GraphCollection graph) {
+ List resultHead = new ArrayList<>();
+ List resultVertices = new ArrayList<>();
+ List resultEdges = new ArrayList<>();
- graph.getGraphHead().output(new LocalCollectionOutputFormat<>(resultHead));
- graph.getVertices().output(new LocalCollectionOutputFormat<>(resultVertices));
- graph.getEdges().output(new LocalCollectionOutputFormat<>(resultEdges));
+ graph.getGraphHeads().output(new LocalCollectionOutputFormat<>(resultHead));
+ graph.getVertices().output(new LocalCollectionOutputFormat<>(resultVertices));
+ graph.getEdges().output(new LocalCollectionOutputFormat<>(resultEdges));
- return getResponse(resultHead, resultVertices, resultEdges);
- }
+ return getResponse(resultHead, resultVertices, resultEdges);
+ }
+
+ private Response createResponse(LogicalGraph graph) {
+ List resultHead = new ArrayList<>();
+ List resultVertices = new ArrayList<>();
+ List resultEdges = new ArrayList<>();
- private Response getResponse(List resultHead, List resultVertices, List resultEdges) {
- try {
- ENV.execute();
- // build the response JSON from the collections
- String json = CytoJSONBuilder.getJSONString(resultHead, resultVertices, resultEdges);
- return Response.ok(json).build();
+ graph.getGraphHead().output(new LocalCollectionOutputFormat<>(resultHead));
+ graph.getVertices().output(new LocalCollectionOutputFormat<>(resultVertices));
+ graph.getEdges().output(new LocalCollectionOutputFormat<>(resultEdges));
- } catch (Exception e) {
- e.printStackTrace();
- // if any exception is thrown, return an error to the client
- return Response.serverError().build();
+ return getResponse(resultHead, resultVertices, resultEdges);
+ }
+
+ private Response getResponse(List resultHead, List resultVertices, List resultEdges) {
+ try {
+ ENV.execute();
+ // build the response JSON from the collections
+ String json = CytoJSONBuilder.getJSONString(resultHead, resultVertices, resultEdges);
+ return Response.ok(json).build();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ // if any exception is thrown, return an error to the client
+ return Response.serverError().build();
+ }
}
- }
}
\ No newline at end of file
diff --git a/src/main/java/org/gradoop/demo/server/Server.java b/src/main/java/org/gradoop/demo/server/Server.java
index 99928f6..76aca16 100644
--- a/src/main/java/org/gradoop/demo/server/Server.java
+++ b/src/main/java/org/gradoop/demo/server/Server.java
@@ -20,69 +20,143 @@
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.api.json.JSONConfiguration;
+
+import org.apache.flink.api.java.ExecutionEnvironment;
+import org.apache.flink.api.java.RemoteEnvironment;
+import org.apache.flink.api.java.utils.ParameterTool;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.StaticHttpHandler;
-import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import javax.ws.rs.core.UriBuilder;
+
+import static java.lang.System.exit;
+import static java.lang.System.setOut;
+import static java.util.Objects.requireNonNull;
+import static org.apache.flink.api.java.ExecutionEnvironment.createLocalEnvironment;
+import static org.apache.flink.api.java.ExecutionEnvironment.createRemoteEnvironment;
+import static org.gradoop.demo.server.LocalGradoopGraphsetStore.DEFAULT_LOCAL_PATH;
/**
* Basic class, used for starting and stopping the server.
*/
public class Server {
- /**
- * URI that specifies where the server is run.
- */
- private static final URI BASE_URI = getBaseURI();
- /**
- * Default port
- */
- private static final int PORT = 2342;
- /**
- * Path to demo application
- */
- private static final String APPLICATION_PATH = "gradoop/html/grouping.html";
+ /**
+ * URI that specifies where the server is run.
+ */
+// private static final URI BASE_URI = getBaseURI();
+ public static final String DEFAULT_JM = "local";
+ static volatile ExecutionEnvironment ENV = null; // volatile is just to ensure visibility
+ static volatile GradoopGraphsetStore LOCAL_STORE = null;
+ /**
+ * Default port
+ */
+ private static final int PORT = 2342;
+ /**
+ * Path to demo application
+ */
+ private static final String APPLICATION_PATH = "gradoop/html/grouping.html";
+
+ /**
+ * Creates the base URI.
+ *
+ * @return Base URI
+ */
+ private static URI getBaseURI(String ip) {
+ return UriBuilder.fromUri("http://" + ip + "/").port(PORT).build();
+ }
- /**
- * Creates the base URI.
- * @return Base URI
- */
- private static URI getBaseURI() {
- return UriBuilder.fromUri("http://localhost/").port(PORT).build();
- }
+ /**
+ * Starts the server and adds the request handlers.
+ *
+ * @return the running server
+ * @throws IOException if server creation fails
+ */
+ private static HttpServer startServer(String[] args) throws IOException, URISyntaxException {
+ System.out.println("Starting grizzly...");
+ ResourceConfig rc = new PackagesResourceConfig("org/gradoop/demo/server");
+ rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
+ ParameterTool params = ParameterTool.fromArgs(args);
+ String ip = params.has("ip") ? params.get("ip") : "localhost";
+ String jmHost = params.has("jmhost") ? params.get("jmhost") : DEFAULT_JM;
+ int jmPort = -1;
+ if (!DEFAULT_JM.equals(jmHost) && !params.has("jmport")) {
+ System.out.println("Error: provide Job Manager Port; exiting");
+ exit(1);
+ }
+ if (!DEFAULT_JM.equals(jmHost)) {
+ jmPort = params.getInt("jmport");
+ }
+ URI baseURI = getBaseURI(ip);
+ ENV = getExecutionEnvironment(jmHost, jmPort);
+ String hdfsParam = "hdfs";
+ if (params.getBoolean(hdfsParam, false)) {
+ LOCAL_STORE = new LocalGradoopGraphsetStore(new HdfsConfiguration(true), DEFAULT_LOCAL_PATH);
+ } else {
+ LOCAL_STORE = new LocalGradoopGraphsetStore(null, DEFAULT_LOCAL_PATH);
+ }
+ System.out.println("Execution Environment: " + ENV);
+ System.out.println(LOCAL_STORE);
+ HttpServer server = GrizzlyServerFactory.createHttpServer(baseURI, rc);
+ HttpHandler staticHandler = new StaticHttpHandler(
+ Server.class.getResource("/web").getPath());
+ server.getServerConfiguration().addHttpHandler(staticHandler, "/gradoop");
+ System.out.printf("org.gradoop.demos.grouping.server started at %s%s%n" +
+ "Kill the process or ^c to stop it.%n", baseURI, APPLICATION_PATH);
+ return server;
+ }
- /**
- * Starts the server and adds the request handlers.
- *
- * @return the running server
- * @throws IOException if server creation fails
- */
- private static HttpServer startServer() throws IOException {
- System.out.println("Starting grizzly...");
- ResourceConfig rc = new PackagesResourceConfig("org/gradoop/demo/server");
- rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
- HttpServer server = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
- HttpHandler staticHandler = new StaticHttpHandler(
- Server.class.getResource("/web").getPath());
- server.getServerConfiguration().addHttpHandler( staticHandler, "/gradoop" );
+ private static ExecutionEnvironment getExecutionEnvironment(String jmHost, int jmPort) throws MalformedURLException {
+ requireNonNull(jmHost);
+ if (DEFAULT_JM.equals(jmHost)) {
+ return createLocalEnvironment();
+ }
+// String m2 = "/.m2/repository/org/gradoop";
+// String[] jarFiles = {
+// System.getProperty("user.home") + m2 + "/gradoop-common/0.3.2/gradoop-common-0.3.2.jar",
+// System.getProperty("user.home") + m2 + "/gradoop-flink/0.3.2/gradoop-flink-0.3.2.jar"
+// };
+ String[] jarFiles = {
+ System.getProperty("user.dir") + "/target/gradoop-demo-shaded.jar"
+ };
+// URL[] globalCP = {
+// new URL("file://" + System.getProperty("user.dir") + "/target/gradoop-demo-shaded.jar")
+// };
+ ExecutionEnvironment ee = ExecutionEnvironment.createRemoteEnvironment(jmHost, jmPort, null);
+// ExecutionEnvironment ee = ExecutionEnvironment.createRemoteEnvironment(jmHost, jmPort);
- return server;
- }
+ System.out.println("ee exec mode: " + ee.getConfig().getExecutionMode());
+ return ee;
+ }
- /**
- * Main method. Run this to start the server.
- *
- * @param args command line parameters
- * @throws IOException if server creation fails
- */
- public static void main(String[] args) throws IOException {
- HttpServer httpServer = startServer();
- System.out.printf("org.gradoop.demos.grouping.server started at %s%s%n" +
- "Press any key to stop it.%n", getBaseURI(), APPLICATION_PATH);
- System.in.read();
- httpServer.stop();
- }
+ /**
+ * Main method. Run this to start the server.
+ *
+ * @param args command line parameters
+ * @throws IOException if server creation fails
+ */
+ public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException {
+ HttpServer httpServer = startServer(args);
+// System.in.read();
+// httpServer.stop();
+ // for nohup
+ BlockingQueue q = new ArrayBlockingQueue<>(1);
+ synchronized (q) { // sync on local variable on for an indefinite wait
+ while (q.isEmpty()) {
+ q.wait();
+ }
+ }
+ httpServer.stop();
+ }
}
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
new file mode 100644
index 0000000..be00727
--- /dev/null
+++ b/src/main/resources/log4j.properties
@@ -0,0 +1,9 @@
+# Root logger option
+log4j.rootLogger=INFO, stdout
+log4j.logger.org.gradoop.demo.server=DEBUG, stdout
+
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
\ No newline at end of file
diff --git a/src/main/resources/web/html/cypher.html b/src/main/resources/web/html/cypher.html
index 6c9cf0c..e37c474 100644
--- a/src/main/resources/web/html/cypher.html
+++ b/src/main/resources/web/html/cypher.html
@@ -17,31 +17,33 @@
-
-
-
-
- Gradoop Demo
-
-
-
-
-
-
-
-
+
+
+
+
+ Gradoop Demo
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+