JanusGraph / JanusGraph/janusgraph
Consecutive creation and deletion of Template/graph on remote server causes NullPointerException server side
- Dominant language
- Java
- Stars
- 5.8k
- Forks
- 1.2k
- Avg merge
- 13h 53m
- Merged PRs (30d)
- 6
Description
Hi all,
First of all, I would like to state that I am somewhat new to JanusGraph and might have missed something obvious (but I do not think so).
While writing some unit tests, I find myself creating and deleting many graphs with the `storage.backend=inmemory` configuration.
The few first graph creations and deletions of graph and associated templates unfold correctly, but after a while, the commands start to return errors.
In my code, I create the graph itself by injecting the following command via the java gremlin driver using ClusterClient.submit() (with remote connection):
```java
ConfiguredGraphFactory.removeTemplateConfiguration();
map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
```
Here is a section of my console (and underneath the associated server trace) using the same script:
```
bin/gremlin.sh
\,,,/
(o o)
-----oOOo-(3)-oOOo-----
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/illioren/Downloads/janusgraph-0.3.1-hadoop2/lib/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/illioren/Downloads/janusgraph-0.3.1-hadoop2/lib/logback-classic-1.1.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
plugin activated: janusgraph.imports
plugin activated: tinkerpop.server
plugin activated: tinkerpop.gephi
plugin activated: tinkerpop.utilities
09:58:18 WARN org.apache.hadoop.util.NativeCodeLoader - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
plugin activated: tinkerpop.hadoop
plugin activated: tinkerpop.spark
plugin activated: tinkerpop.tinkergraph
gremlin> :remote connect tinkerpop.server conf/remote.yaml session
==>Configured localhost/127.0.0.1:8182-[97c3cc46-57f5-4fe7-afdb-297b788521cb]
gremlin> :remote console
==>All scripts will now be sent to Gremlin Server - [localhost/127.0.0.1:8182]-[97c3cc46-57f5-4fe7-afdb-297b788521cb] - type ':remote console' to return to local mode
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
==>null
gremlin> ConfiguredGraphFactory.getGraphNames()ConfiguredGraphFactory.getGraphNames()
Exception evaluating property 'ConfiguredGraphFactory' for java.util.HashSet, Reason: groovy.lang.MissingPropertyException: No such property: ConfiguredGraphFactory for class: java.lang.String
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.getGraphNames()
==>testgraph2
gremlin> ConfiguredGraphFactory.drop("testgraph2")
==>null
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
==>null
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
Configuration for graph testgraph2 already exists.
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
Configuration for graph testgraph2 already exists.
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.drop("testgraph2")
==>null
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
==>null
gremlin> ConfiguredGraphFactory.drop("testgraph2")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.drop("testgraph2")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.getGraphNames()
==>testgraph2
gremlin> ConfiguredGraphFactory.drop("testgraph2")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.drop("testgraph2")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.drop("testgraph")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.drop("testgraph2")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.getGraphNames()
==>testgraph2
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
Configuration for graph testgraph2 already exists.
Type ':help' or ':h' for help.
Display stack trace? [yN]
gremlin> ConfiguredGraphFactory.drop("testgraph2")
org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
Type ':help' or ':h' for help.
Display stack trace? [yN]
```
for each org.apache.tinkerpop.gremlin.jsr223.console.RemoteException following a ConfiguredGraphFactory.drop("testgraph2") command, the servers produces the following trace:
```console
akmh_janusgraph_1 | 182325 [gremlin-server-session-1] WARN org.apache.tinkerpop.gremlin.server.op.AbstractEvalOpProcessor - Exception processing a script on request [RequestMessage{, requestId=a5b52250-f070-4428-bc2f-a219a05b7bae, op='eval', processor='session', args={gremlin=ConfiguredGraphFactory.drop("testgraph2"), session=97c3cc46-57f5-4fe7-afdb-297b788521cb, bindings={}, manageTransaction=false, batchSize=64}}].
akmh_janusgraph_1 | java.lang.NullPointerException
akmh_janusgraph_1 | at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:210)
akmh_janusgraph_1 | at org.janusgraph.core.JanusGraphFactory.drop(JanusGraphFactory.java:199)
akmh_janusgraph_1 | at org.janusgraph.core.ConfiguredGraphFactory.drop(ConfiguredGraphFactory.java:160)
akmh_janusgraph_1 | at org.janusgraph.core.ConfiguredGraphFactory$drop$3.call(Unknown Source)
akmh_janusgraph_1 | at Script8.run(Script8.groovy:1)
akmh_janusgraph_1 | at org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine.eval(GremlinGroovyScriptEngine.java:690)
akmh_janusgraph_1 | at org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine.eval(GremlinGroovyScriptEngine.java:395)
akmh_janusgraph_1 | at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
akmh_janusgraph_1 | at org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor.lambda$eval$0(GremlinExecutor.java:263)
akmh_janusgraph_1 | at java.util.concurrent.FutureTask.run(FutureTask.java:266)
akmh_janusgraph_1 | at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
akmh_janusgraph_1 | at java.util.concurrent.FutureTask.run(FutureTask.java:266)
akmh_janusgraph_1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
akmh_janusgraph_1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
akmh_janusgraph_1 | at java.lang.Thread.run(Thread.java:748)
```
The server seems to be confused regarding the existence of my graph. And this does not seem to settle regardless how much time I wait between commands and/or restart of my local gremlin console. The graph being configured with `storage.backend=inmemory`, the problem temporarily appearers after restarting the server.
The session pre-empting the restart that yielded the traces above displayed a similar problem but with the existence of the `root.storage.backend` argument within my creation command:
```
gremlin> ConfiguredGraphFactory.removeTemplateConfiguration();map=new HashMap();map.put("storage.backend","inmemory");ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));ConfiguredGraphFactory.create("testgraph2");ConfiguredGraphFactory.removeTemplateConfiguration();
Need to set configuration value: root.storage.backend
Type ':help' or ':h' for help.
Display stack trace? [yN]
```
And the sessions prior to this returned errors telling me that my configuration object was empty, or that a template was already existing (despite the command to delete it at the beginning and end of the submitted String). Unfortunately, I do not have access to those specific traces.
A few environmental details:
- I am running the JanusGraph Server within a docker container (Docker version 18.06.3-ce, build d7080c1), using the base openjdk:8-jdk image (following the [official JanusGraph image](https://github.com/JanusGraph/janusgraph-docker)).
- The docker container is ran within a docker-compose context (docker-compose version 1.24.0, build 0aa59064)
- JanusGraph version is 0.3.1.
- Tinkerpop is version 3.3.3 for both the client and server.
- The java gremlin server library is on version 3.3.3
- My OS is Ubuntu 17.10
- Local Java info:
openjdk version "1.8.0_171"
OpenJDK Runtime Environment (build 1.8.0_171-8u171-b11-0ubuntu0.17.10.1-b11)
OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)
- The server runs with `ConfigurationManagementGraph` enabled and no pre-configured graph
Thank you all for your time and efforts.
JanusGraph is currently - and as far as I know - one of the very few (if not only) open source graph database under the Apache2 license. Great work so far!
Contributor guide
Research direction
Reproduce the repeated remote-session sequence using ConfiguredGraphFactory.create, drop, and template configuration with the inmemory backend. Trace ConfiguredGraphFactory.drop into JanusGraphFactory.drop and ConfigurationManagementGraph, then add a regression test showing repeated create/delete cycles finish without a NullPointerException or stale graph configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100