I am building a Java application that needs to connect to a remote JanusGraph server and create graphs on the fly.
I have installed/configured a single node JanusGraph Server with a Berkeley database backend and ConfigurationManagementGraph support so that I can create/manage multiple graphs on the server.
In a Gremlin console I can connect to the remote server, create graphs, create vertexes, etc. Example:
gremlin> :remote connect tinkerpop.server conf/remote.yaml session
gremlin> :remote console
gremlin> map = new HashMap<String, Object>();
gremlin> map.put("storage.backend", "berkeleyje");
gremlin> map.put("storage.directory", "db/test");
gremlin> ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));
gremlin> ConfiguredGraphFactory.create("test");
gremlin> graph = ConfiguredGraphFactory.open("test");
gremlin> g = graph.traversal();
gremlin> g.addV("person").property("name", "peter");
gremlin> g.tx().commit();
gremlin> graph.vertices().size();
==>1
gremlin> g.V();
==>v[4288]
gremlin> g.V().count();
==>1
gremlin> g.close();
So far so good. On the Java side, I can connect to the remote server and issue commands via Client.submit() method. In the following example, I connect to the remote server and create a new graph called "test2":
Cluster cluster = Cluster.build()
.addContactPoint(host)
.port(port)
.serializer(Serializers.GRYO_V3D0)
.create();
String name = "test2";
String sessionId = UUID.randomUUID().toString();
Client client = cluster.connect(sessionId);
client.submit("map = new HashMap<String, Object>();");
client.submit("map.put(\"storage.backend\", \"berkeleyje\");");
client.submit("map.put(\"storage.directory\", \"db/" + name + "\");");
client.submit("ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));");
client.submit("ConfiguredGraphFactory.create(\"" + name + "\");");
I can confirm that the graph was created and see other graphs programmatically as well using the client.submit() method:
ResultSet results = client.submit("ConfiguredGraphFactory.getGraphNames()");
Iterator<Result> it = results.iterator();
while (it.hasNext()){
Result result = it.next();
String graphName = result.getString();
System.out.println(graphName);
}
Next I want to connect to a graph and traverse the nodes programmatically (in Java). However, I can't seem to figure out how to do this. From what I've read, it should be something as simple as this:
DriverRemoteConnection conn = DriverRemoteConnection.using(client, name); //"_traversal"
GraphTraversalSource g = AnonymousTraversalSource.traversal().withRemote(conn);
These commands don't raise any errors but the GraphTraversalSource appears to be empty:
System.out.println(g.getGraph()); //always returns emptygraph[empty]
System.out.prinltn(g.V()); //Appears to be empty [GraphStep(vertex,[])]
Iterator<Vertex> it = g.getGraph().vertices(); //empty
Any suggestions of how to get a GraphTraversalSource for a remote JanusGraph server in Java? I suspect that my issue something to do with ConfigurationManagementGraph but I can't put my finger on it. Again, the client.submit() works. It would be cool if I could do something like this:
GraphTraversalSource g = (GraphTraversalSource) client.submit("ConfiguredGraphFactory.open(\"" + name + "\");").iterator().next();
...but of course, that doesn't work
UPDATE
Looking at the code, it appears that the graph name (remoteTraversalSourceName) passed to the DriverRemoteConnection is being ignored.
Starting with the DriverRemoteConnection:
DriverRemoteConnection conn = DriverRemoteConnection.using(client, name);
Under the hood, the graph name (remoteTraversalSourceName) is simply used to set an alias (e.g. client.alias(name);)
Next, in the AnonymousTraversalSource.traversal().withRemote() method
GraphTraversalSource g = AnonymousTraversalSource.traversal().withRemote(conn);
Under the hood, withRemote() is calling:
traversalSourceClass.getConstructor(RemoteConnection.class).newInstance(remoteConnection);
Where traversalSourceClass is GraphTraversalSource.class
Which is the same as this:
g = GraphTraversalSource.class.getConstructor(RemoteConnection.class).newInstance(conn);
Finally, the constructor for the GraphTraversalSource looks like this:
public GraphTraversalSource(final RemoteConnection connection) {
this(EmptyGraph.instance(), TraversalStrategies.GlobalCache.getStrategies(EmptyGraph.class).clone());
this.connection = connection;
this.strategies.addStrategies(new RemoteStrategy(connection));
}
As you can see, the graph variable in the GraphTraversalSource is never set.
I suspect that either (a) I shouldn't be using the AnonymousTraversalSource or (b) that I need to instantiate the GraphTraversalSource some other way, perhaps using a Graph object.