Trinity - Internal Java 8 Utilities

Trinity is a versatile Cypher query runner for the JVM, supporting all setup types of Neo4j v2 and v3.

License

License

Apache License
Categories

Categories

Java 8 Languages
GroupId

GroupId

org.liquigraph.trinity
ArtifactId

ArtifactId

java8-utilities
Last Version

Last Version

1.0.0-M01
Release Date

Release Date

Type

Type

jar
Description

Description

Trinity - Internal Java 8 Utilities
Trinity is a versatile Cypher query runner for the JVM, supporting all setup types of Neo4j v2 and v3.

Download java8-utilities

How to add to project

<!-- https://jarcasting.com/artifacts/org.liquigraph.trinity/java8-utilities/ -->
<dependency>
    <groupId>org.liquigraph.trinity</groupId>
    <artifactId>java8-utilities</artifactId>
    <version>1.0.0-M01</version>
</dependency>
// https://jarcasting.com/artifacts/org.liquigraph.trinity/java8-utilities/
implementation 'org.liquigraph.trinity:java8-utilities:1.0.0-M01'
// https://jarcasting.com/artifacts/org.liquigraph.trinity/java8-utilities/
implementation ("org.liquigraph.trinity:java8-utilities:1.0.0-M01")
'org.liquigraph.trinity:java8-utilities:jar:1.0.0-M01'
<dependency org="org.liquigraph.trinity" name="java8-utilities" rev="1.0.0-M01">
  <artifact name="java8-utilities" type="jar" />
</dependency>
@Grapes(
@Grab(group='org.liquigraph.trinity', module='java8-utilities', version='1.0.0-M01')
)
libraryDependencies += "org.liquigraph.trinity" % "java8-utilities" % "1.0.0-M01"
[org.liquigraph.trinity/java8-utilities "1.0.0-M01"]

Dependencies

compile (1)

Group / Artifact Type Version
org.liquigraph.trinity : trinity-api jar 1.0.0-M01

Project Modules

There are no modules declared in this project.

Trinity

Neo4j is a graph database.

Cypher is Neo4j’s query language.

Trinity is the preferred choice to run Cypher queries for client applications and libraries running on the Java Virtual Machine.

Build status

Build Status Maven Central

Why Trinity?

While working on Liquigraph, we realized that having to keep several branches per Neo4j version was a pain.

This was mainly due to the fact there was no JDBC driver supporting both Neo4j v2 and Neo4j v3.

Moreover, we did not need a full-fledged JDBC implementation, we just needed to run Cypher queries.

And then, Trinity was born! With a simple API in mind, some build and implementation tricks to work around Neo4j incompatibilities, we achieved what we wanted: having a single way to run Cypher with any Neo4j setup.

Why the name?

  1. Because badass women for the win!

  2. And also because Twitter!

Minimum Viable Snippet

Bolt

package in.da.matrix;

import org.liquigraph.trinity.bolt.BoltClient;
import org.neo4j.driver.v1.AuthToken;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.GraphDatabase;

import java.util.List;

public class TrinityBoltExample {

    public static void main(String[] args) {
        AuthToken authentication = AuthTokens.basic("neo4j", "toto");
        try (BoltClient trinity =
             new BoltClient(GraphDatabase.driver("bolt://localhost:7687", authentication))) {

            trinity.runSingleTransaction("MATCH (n:Crew) RETURN COUNT(n)")
               .consume(
                   (List<Fault> errors) -> {
                       // do something amazingly useful
                   },
                   (List<Data> data) -> {
                       // do something usefully amazing with it
                   }
               );
        }
    }
}

HTTP

package in.da.matrix;

import org.liquigraph.trinity.Data;
import org.liquigraph.trinity.Either;
import org.liquigraph.trinity.Fault;
import org.liquigraph.trinity.http.BasicAuthenticator;
import org.liquigraph.trinity.http.HttpClient;
import java.util.List;
import okhttp3.OkHttpClient;

public class TrinityHttpExample {

    public static void main(String... args) {
        // if auth is disabled, just use: new HttpClient("http://localhost:7474")
        HttpClient trinity = new HttpClient(
            "http://localhost:7474",
            okHttpClient("neo4j", "s3cr3t")
        );

        Either<List<Fault>, List<Data>> either =
            trinity.runSingleTransaction("MATCH (n:Crew) RETURN COUNT(n)");

        if (either.isRight()) {
            List<Data> data = either.getRight();
            // do something usefully amazing with it
        }
        else {
            List<Fault> errors = either.getLeft();
            // do something amazingly useful
        }
    }

    private static OkHttpClient okHttpClient(String username, String password) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder = builder.authenticator(new BasicAuthenticator(username, password));
        return builder.build();
    }
}

Embedded for Neo4j v3

package in.da.matrix;

import org.liquigraph.trinity.neo4jv3.EmbeddedClient;
import org.liquigraph.trinity.Data;
import org.liquigraph.trinity.Either;
import org.liquigraph.trinity.Fault;
import java.nio.file.Paths;
import java.util.List;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

public class TrinityEmbeddedV3Example {

    public static void main(String... args) {
        File path = Paths.get("some", "path").toFile();
        EmbeddedClient trinity = new EmbeddedClient(graphDatabase(path));

        Either<List<Fault>, List<Data>> either =
            trinity.runSingleTransaction("MATCH (n:Crew) RETURN COUNT(n)");

        if (either.isRight()) {
            List<Data> data = either.getRight();
            // do something usefully amazing with it
        }
        else {
            List<Fault> errors = either.getLeft();
            // do something amazingly useful
        }
    }

    private static GraphDatabaseService graphDatabase(File path) {
        return new GraphDatabaseFactory().newEmbeddedDatabase(path);
    }
}

Embedded for Neo4j v2

package in.da.matrix;

import org.liquigraph.trinity.neo4jv2.EmbeddedClient;
import org.liquigraph.trinity.Data;
import org.liquigraph.trinity.Either;
import org.liquigraph.trinity.Fault;
import java.util.List;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

public class TrinityEmbeddedV2Example {

    public static void main(String... args) {
        EmbeddedClient trinity = new EmbeddedClient(graphDatabase("/some/path"));

        Either<List<Fault>, List<Data>> either =
            trinity.runSingleTransaction("MATCH (n:Crew) RETURN COUNT(n)");

        if (either.isRight()) {
            List<Data> data = either.getRight();
            // do something usefully amazing with it
        }
        else {
            List<Fault> errors = either.getLeft();
            // do something amazingly useful
        }
    }

    private static GraphDatabaseService graphDatabase(String path) {
        return new GraphDatabaseFactory().newEmbeddedDatabase(path);
    }
}

Download

Application developers

Picking the right implementation is just a matter of selecting the right artifact:

pun absolutely intended Table 1. Trinity artefact matrix ()
Artifact coordinates Version of Neo4j JRE prerequisites

trinity-embedded-2x

2.0.0 to latest 2.x

JRE 7 or later

trinity-embedded-3x

3.0.0 to latest 3.x

JRE 8 or later

trinity-http

2.0.0 to latest 3.x

JRE 7 or later

trinity-bolt

3.0.0 to latest 3.x

JRE 8 or later

Note

Trinity groupId is always org.liquigraph.trinity. If you pick Trinity for Neo4j embedded v2, then you must add the dependency:

<dependency>
    <groupId>org.liquigraph.trinity</groupId>
    <artifactId>trinity-embedded-2x</artifactId>
    <version><!-- CURRENT VERSION --></version>
</dependency>

Library developers

If you develop a library that needs to support several Neo4j setups as well, you can pick any of the two bundles:

  • Neo4j 2:

<dependency>
    <groupId>org.liquigraph.trinity</groupId>
    <artifactId>trinity-neo4j-v2</artifactId>
    <version><!-- CURRENT VERSION --></version>
</dependency>
  • Neo4j 3:

<dependency>
    <groupId>org.liquigraph.trinity</groupId>
    <artifactId>trinity-neo4j-v3</artifactId>
    <version><!-- CURRENT VERSION --></version>
</dependency>
Note

These two bundles cannot be included together, as they require different versions of Neo4j and JRE.

Please note that Trinity instance discovery is implemented via the good old Java Service Provider Interfaces.

To retrieve a Trinity instance, one just needs to include one of the two bundles and use org.liquigraph.trinity.CypherClientLookup like in the example below:

package in.da.matrix;

import org.liquigraph.trinity.CypherClientLookup;
import org.liquigraph.trinity.CypherTransport;
import org.liquigraph.trinity.OngoingTransaction;
import org.liquigraph.trinity.Optional; // for trinity-neo4j-v2
import java.util.Optional; // for trinity-neo4j-v3
import java.util.Properties;

public class TrinityHttpDiscoveryExample {

    public static void main(String... args) {
        CypherClientLookup lookup = new CypherClientLookup();
        Optional<CypherClient<OngoingTransaction>> maybeTrinity = lookup.getInstance(
            CypherTransport.HTTP,
            httpProperties()
        );

        // trinity-neo4j-v3 users can rely on the primitive Java 8 Optional
        // they are encouraged to use instead maybeTrinity.ifPresent(trinity -> ...)
        if (maybeTrinity.isPresent()) {
            CypherClient<OngoingTransaction> trinity = maybeTrinity.get();
            // then you can run Cypher queries as in the above examples
        }
    }

    private static Properties httpProperties() {
        Properties props = new Properties();
        props.setProperty("cypher.http.baseurl", "http://localhost:7474");
        props.setProperty("cypher.http.username", "neo4j");
        props.setProperty("cypher.http.password", "s3cr3t");
        return props;
    }
}
org.liquigraph.trinity

Liquigraph

Migrations for Neo4j

Versions

Version
1.0.0-M01