Search code examples
configuration-filesjanusgraphjava-17gremlin-servergraph-traversal

Connect to External JanusGraph Server With JanusGraphFactory


Problem

How do you connect to an external JanusGraph Server with JanusGraphFactory?
I don't know what I'm doing and new to JanusGraph and Graph-Databases in-general.
What is the JanusGraph > Configuration > "storage.backend" property supposed to be to connect?

│   pom.xml
│
├───src
│   ├───main
│   │   ├───java
│   │   │       Main.java
│   │   │
│   │   └───resources
│   │       │   log4j2.xml
│   │       │
│   │       ├───conf
│   │       │       remote-graph.properties
│   │       │       remote-objects.yaml

I've tried switching through the storage-backends' names shorthands: berkeleyje, cql, hbase, inmemory.
And I expected at least one of them to work.
But nothing seems to actually change it using the external JanusGraph-Server instance.

import org.apache.commons.configuration2.BaseConfiguration;
import org.apache.commons.configuration2.Configuration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.janusgraph.core.JanusGraph;
import org.janusgraph.core.JanusGraphFactory;

public class Main {
    private static final Logger logger = LogManager.getLogger(Main.class);
    public static void main(String[] args) {
        Configuration configuration = new BaseConfiguration();
        configuration.setProperty("storage.backend", "inmemory");
        JanusGraph janusGraph = JanusGraphFactory.open(configuration);
        GraphTraversalSource g = janusGraph.traversal();
        logger.info(g.V().next());
        janusGraph.close();
    }
}

remote-graph.properties

gremlin.remote.remoteConnectionClass=org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection
gremlin.remote.driver.clusterFile=src/main/resources/conf/remote-objects.yaml
gremlin.remote.driver.sourceName=g

remote-objects.yaml

hosts: [localhost]
port: 18182
serializer: {
  className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0,
  config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}

pom.xml

    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.20.0</version>
        </dependency>
        <dependency>
            <groupId>org.janusgraph</groupId>
            <artifactId>janusgraph-core</artifactId>
            <version>1.0.0-20230424-065649.dcd3240</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tinkerpop</groupId>
            <artifactId>gremlin-core</artifactId>
            <version>3.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.janusgraph</groupId>
            <artifactId>janusgraph-inmemory</artifactId>
            <version>1.0.0-20230427-155952.3f229ac</version>
        </dependency>
    </dependencies>
</project>

The JanusGraph-Server I'm using is a docker container:
docker run -it -p 18182:8182 janusgraph/janusgraph.
Its Gremlin-Server's Console is the standard TCP-Port:8182 exposed on TCP-Port:18182.
What do you do to connect to the external JanusGraph-Server?

java.lang.Throwable: Hook creation trace
    at org.janusgraph.graphdb.database.StandardJanusGraph.<init>(StandardJanusGraph.java:250) [janusgraph-core-1.0.0-20230424-065649.dcd3240.jar:?]
    at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:176) [janusgraph-core-1.0.0-20230424-065649.dcd3240.jar:?]
    at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:147) [janusgraph-core-1.0.0-20230424-065649.dcd3240.jar:?]
    at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:127) [janusgraph-core-1.0.0-20230424-065649.dcd3240.jar:?]
    at Main.main(Main.java:14) [classes/:?]
2023-05-01 10:36:13,446 [DEBUG] [o.j.g.t.StandardJanusGraphTx.main] ::   Caffeine vertex cache size: requested=20000 effective=20000 (min=100)
2023-05-01 10:36:13,448 [DEBUG] [o.j.g.t.v.CaffeineVertexCache.main] ::  Created dirty vertex map with initial size 32
2023-05-01 10:36:13,450 [DEBUG] [o.j.g.t.v.CaffeineVertexCache.main] ::  Created vertex cache with max size 20000
2023-05-01 10:36:13,455 [DEBUG] [o.j.g.t.JanusGraphBlueprintsGraph.main] ::  Created new thread-bound transaction standardjanusgraphtx[0x79c5636f]
2023-05-01 10:36:13,466 [WARN] [o.j.g.t.StandardJanusGraphTx.main] ::    Query requires iterating over all vertices [[]]. For better performance, use indexes
Exception in thread "main" java.util.NoSuchElementException
    at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.next(DefaultTraversal.java:257)
    at Main.main(Main.java:16)
2023-05-01 10:36:13,498 [DEBUG] [o.j.d.l.k.KCVSLog.pool-5-thread-1] ::   MessagePuller configured with ReadMarker timestamp slightly ahead of read lag time; waiting for the clock to catch up

Hook creation trace  at org.janusgraph.graphdb.database.StandardJanusGraph


Updates

Update 1

No known way to directly connect to JanusGraph.
Seems like there should be a way with AnonymousTraversalSource
But no example presented-or-found.

Update 2

Setting-up JanusGraph with another backend-server on Docker
Seems to be the only viable on a Windows machine, in this case Apache Cassandra is being used. Need to manually add janusgraph-cql.properties for Cassandra-JanusGraph, which is only found in janusgraph/janusgraph-dist/src/assemnbly/cfilter/conf/ and can be pulled from its ZIP Releases.

gremlin.graph=org.janusgraph.core.JanusGraphFactory
storage.backend=cql
storage.hostname=127.0.0.1
storage.cql.keyspace=janusgraph
storage.cql.local-datacenter=datacenter1
cache.db-cache = true
cache.db-cache-clean-wait = 20
cache.db-cache-time = 180000
cache.db-cache-size = 0.5

This is copy-pasted into the Cassandra-Docker-container.

docker exec -i jg-cassandra mkdir -p /opt/janusgraph/conf
docker cp janusgraph-cql.properties jq-cassandra:/opt/janusgraph/conf

Running the code again, returns this error now.

org.janusgraph.diskstorage.cql.CQLStoreManager

Notable Logging:

[INFO] [c.d.o.d.i.c.ContactPoints.main] ::   Contact point localhost:9042 resolves to multiple addresses, will use them all ([localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1])
[DEBUG] [c.d.o.d.i.c.u.Reflection.main] ::   Could not load com.esri.core.geometry.ogc.OGCGeometry with loader null: java.lang.ClassNotFoundException: com.esri.core.geometry.ogc.OGCGeometry
java.lang.ClassNotFoundException: com.esri.core.geometry.ogc.OGCGeometry
    ... 
    at Main.main(Main.java:6) [classes/:?]
2023-05-02 12:20:19,310 [WARN] [c.d.o.d.i.c.c.ControlConnection.JanusGraph Session-admin-1] ::   [JanusGraph Session] Error connecting to Node(endPoint=localhost/127.0.0.1:9042, hostId=null, hashCode=34665a95), trying next node
com.datastax.oss.driver.api.core.connection.ConnectionInitException: [JanusGraph Session|control|id: 0x5cf58f41, L:/127.0.0.1:58140 - R:localhost/127.0.0.1:9042] Protocol initialization request, step 1 (OPTIONS): unexpected failure (com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer)
... 
Caused by: com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer
[WARN] [c.d.o.d.i.c.c.ControlConnection.JanusGraph Session-admin-1] ::   [JanusGraph Session] Error connecting to Node(endPoint=localhost/[0:0:0:0:0:0:0:1]:9042, hostId=null, hashCode=ef8c065), trying next node
com.datastax.oss.driver.api.core.connection.ConnectionInitException: [JanusGraph Session|control|id: 0xea4dcd74, L:/[0:0:0:0:0:0:0:1]:58141 - R:localhost/[0:0:0:0:0:0:0:1]:9042] Protocol initialization request, step 1 (OPTIONS): unexpected failure (com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer)
...
Caused by: com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer
java.util.concurrent.CompletionException: com.datastax.oss.driver.api.core.AllNodesFailedException: Could not reach any contact point, make sure you've provided valid addresses (showing first 2 nodes, use getAllErrors() for more): Node(endPoint=localhost/127.0.0.1:9042, hostId=null, hashCode=34665a95): [com.datastax.oss.driver.api.core.connection.ConnectionInitException: [JanusGraph Session|control|id: 0x5cf58f41, L:/127.0.0.1:58140 - R:localhost/127.0.0.1:9042] Protocol initialization request, step 1 (OPTIONS): unexpected failure (com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer)], Node(endPoint=localhost/[0:0:0:0:0:0:0:1]:9042, hostId=null, hashCode=ef8c065): [com.datastax.oss.driver.api.core.connection.ConnectionInitException: [JanusGraph Session|control|id: 0xea4dcd74, L:/[0:0:0:0:0:0:0:1]:58141 - R:localhost/[0:0:0:0:0:0:0:1]:9042] Protocol initialization request, step 1 (OPTIONS): unexpected failure (com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer)]
...
    Caused by: com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer
    Suppressed: com.datastax.oss.driver.api.core.connection.ConnectionInitException: [JanusGraph Session|control|id: 0xea4dcd74, L:/[0:0:0:0:0:0:0:1]:58141 - R:localhost/[0:0:0:0:0:0:0:1]:9042] Protocol initialization request, step 1 (OPTIONS): unexpected failure (com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer)
...
    Caused by: com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer
Exception in thread "main" java.lang.IllegalArgumentException: Could not instantiate implementation: org.janusgraph.diskstorage.cql.CQLStoreManager
...
    Caused by: com.datastax.oss.driver.api.core.connection.ClosedConnectionException: Lost connection to remote peer

Process finished with exit code 1

Solution

  • All you need is making a valid JanusGraph instance from JanusGraphFactory call.
    Which is a bit of a misnomer on how hard this is to find information on configuring JanusGraphFactory (at time of recording).

    JanusGraphFactory Gremlin Console

    JanusGraphFactory

    Gremlin Console

    The JanusGraph distribution contains a command line Gremlin Console which makes it easy to get started and interact with JanusGraph. Invoke bin/gremlin.sh (Unix/Linux) or bin/gremlin.bat (Windows) to start the Console and then open a JanusGraph graph using the factory with the configuration stored in an accessible properties configuration file:

    graph = JanusGraphFactory.open('path/to/configuration.properties')

    This is what you'll need:

    Code

    │   pom.xml
    │   
    ├───src
    │   ├───main
    │   │   ├───java
    │   │   │       Main.java
    │   │   │
    │   │   └───resources
    │   │       │   log4j2.xml
    

    Main.java

    //import org.apache.tinkerpop.gremlin.structure.Vertex;
    import org.janusgraph.core.JanusGraph;
    import org.janusgraph.core.JanusGraphFactory;
    //import org.janusgraph.core.PropertyKey;
    //import org.janusgraph.core.schema.JanusGraphManagement;
    
    public class Main {
        public static void main(String[] args) {
            JanusGraph janusGraph = JanusGraphFactory.build().set("storage.backend", "cql").set("storage.hostname", "localhost:9042").open();
    //        JanusGraphManagement janusGraphManagement = janusGraph.openManagement();
    //        PropertyKey propertyKey = janusGraphManagement.getPropertyKey("_id");
    //        janusGraphManagement.buildIndex("_id", Vertex.class).addKey(propertyKey).buildCompositeIndex();
    //        janusGraphManagement.commit();
            janusGraph.close();
        }
    }
    

    log4j2.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="warn" name="MyApp">
        <Properties>
            <Property name="baseDir">logs</Property>
        </Properties>
        <Appenders>
            <RollingFile name="RollingFile" fileName="${baseDir}/${date:yyyy-MM-dd}/log-${date:yyyy-MM-dd}.log"
                         filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
                <PatternLayout>
                    <Pattern>%d [%p] [%c{1.}.%t] ::&#x09; %m%n</Pattern>
                </PatternLayout>
                <Policies>
                    <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
                    <SizeBasedTriggeringPolicy size="250 MB"/>
                </Policies>
            </RollingFile>
            <Console name="STDOUT" target="SYSTEM_OUT">
                <PatternLayout>
                    <Pattern>%d [%p] [%c{1.}.%t] ::&#x09; %m%n</Pattern>
                </PatternLayout>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="info">
                <AppenderRef ref="STDOUT"/>
                <AppenderRef ref="RollingFile"/>
            </Root>
        </Loggers>
    </Configuration>
    

    pom.xml

        <dependencies>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-slf4j2-impl</artifactId>
                <version>2.20.0</version>
            </dependency>
            <dependency>
                <groupId>org.janusgraph</groupId>
                <artifactId>janusgraph-cql</artifactId>
                <version>1.0.0-20230504-014643.988c094</version>
            </dependency>
        </dependencies>