Apache TinkerPop™ client integration

As an alternative to its native graph API, the DataStax Enterprise Java driver provides an integration layer to interact with DSE through the Apache TinkerPop™ library. This integration has also been referred to as the ‘Fluent API’.

This component is published in Maven central as a separate artifact:

<dependency>
  <groupId>com.datastax.dse</groupId>
  <artifactId>dse-java-driver-graph</artifactId>
  <version>1.2.7</version>
</dependency>

Note: The TinkerPop integration layer has a direct dependency on org.apache.tinkerpop:gremlin-groovy, which in turn as a dependency on com.github.jeremyh:jBCrypt – an artifact that is not available from Maven Central.

This is a known problem, and until it is solved, users need to either:

  1. Exclude the com.github.jeremyh:jBCrypt dependency and add a dependency to org.mindrot:jbcrypt:0.4, the official Maven artifact for the jBCrypt library: “`xml com.datastax.dse dse-java-driver-graph 1.2.7 com.github.jeremyh jBCrypt

org.mindrot jbcrypt 0.4 With Gradle: groovy dependencies { compile(‘com.datastax.dse:dse-java-driver-graph:1.2.7’) { exclude group: ‘com.github.jeremyh’, module: ‘jBCrypt’ } compile(‘corg.mindrot:jbcrypt:0.4’) } With sbt: scala “com.datastax.dse” % “dse-java-driver-graph” % “1.2.7” exclude(“com.github.jeremyh”,“jBCrypt”), “org.mindrot” % “jbcrypt” % “0.4” 2. Manually install `com.github.jeremyh:jBCrypt:jar:jbcrypt-0.4` in their local and/or corporate Maven repository. Simply [clone this project](https://github.com/jeremyh/jBCrypt) and `mvn install` it. 3. Use [Jitpack](https://jitpack.io/). Jitpack is a repository that serves artifacts whose source code is hosted on Github. With Maven: xml jitpack.io https://jitpack.io With Gradle: groovy allprojects { repositories { maven { url ‘https://jitpack.io’ } } } With sbt: scala resolvers += “jitpack” at “https://jitpack.io” “`

DataStax drivers execution compatibility

This new package provides the necessary tools to get the most out the popular Apache TinkerPop Traversal API, while still getting the benefits of the DataStax drivers execution model. A Traversal is considered as a query, that can then be wrapped inside a GraphStatement.

Here’s how to create a DSE Java driver‘s GraphStatement out of a Apache TinkerPop Traversal:

// traversal() returns a simple GraphTraversalSource that is not meant to be iterated itself
GraphTraversalSource g = DseGraph.traversal();

GraphStatement graphStatement = DseGraph.statementFromTraversal(g.V().has("name", "marko"));
GraphResultSet grs = dseSession.executeGraph(graphStatement);

// the API does not change, whether what's executed is a String, or a Statement created from a Traversal, and so on.
for (GraphNode graphNode : grs) {
    Vertex v = graphNode.asVertex();
}

Statements created from Traversal instances will behave, with regards to the cluster, the same way the DSE Java driver behaves with DSE. All the advanced features of the DSE Java driver come into play, automatic retries, load balancing, DataCenter awareness, smart query logging, and so on.

Information about the returned result types with the DSE Java driver can be found on this page.

TinkerPop direct compatibility

This package also provides full compatibility with Apache TinkerPop’s query execution model and result types.

Here’s an example of how to get a Apache TinkerPop GraphTraversalSource that is remotely connected to a DseGraph server, communicating internally via the DSE Java driver:

DseCluster dseCluster = DseCluster.builder()
    .addContactPoint("1.2.3.4")
    .withGraphOptions(new GraphOptions()
    .setGraphName("mygraph"))
    .build();
DseSession dseSession = dseCluster.connect();

GraphTraversalSource g = DseGraph.traversal(dseSession);

// Now you can use the Traversal source and use it **as if** it was working against a local graph, and with the usual TinkerPop API. All the communication with the DSE Graph server is done transparently.
List<Vertex> vertices = g.V().hasLabel("person").toList();

Traversal sources with different configurations can easily be created. By default the options specific to DSE Graph are taken from the DseCluster configuration, however the API exposes a way to override each individual setting, per traversal source:

GraphTraversalSource gOLTP = DseGraph.traversal(dseSession, new GraphOptions().setGraphName("mygraph"));
GraphTraversalSource gOLAP = DseGraph.traversal(dseSession, new GraphOptions().setGraphName("myothergraph").setGraphSource(ANALYTICS_SOURCE_NAME));

Vertex v = gOLTP.V().has("name", "marko").next();
long count = gOLAP.V().count().next();

Please note that there is no interactivity with DSE Graph until a Terminal Step (such as next, toList, etc.) is performed.

A word on Results

Objects returned after the Remote traversal execution are objects that are detached from the original DSE Graph on the server. A detached element is an element that lives on its own, even though the detached elements contains the complete data, modifications made to a detached element do not affect the data stored in the DSE Graph.

Search and Geo

For ease of use, DSE Search and Geo predicates are directly integrated and provided in the programmatic API:

GraphTraversalSource g = DseGraph.traversal(dseSession, new GraphOptions().setGraphName("thegraph"));
Vertex v = g.V().has("textProp", Search.tokenPrefix("1")).next();

Or:

GraphTraversalSource g = DseGraph.traversal(dseSession, new GraphOptions().setGraphName("thegraph"));

Vertex v1 = g.addV(T.label, "geopoint", "point", Geo.point(50, 50)).next();
Vertex v2 = g.addV(T.label, "geopoint", "point", Geo.point(120, 120)).next();

List<Vertex> v3 = g.V().has("point", Geo.inside(49, 49, 4)).toList();

assert v3.size() == 1;
assert v1 == v3.get(0);

Please check out the Javadoc of the Geo and Search classes for more information.

Programmatic Schema API

Available soon!…