- This client service configures a connection to a Gremlin Server and allows Gremlin queries to be executed against - the Gremlin Server. For more information on Gremlin and Gremlin Server, see the Apache Tinkerpop project. -
-- A common issue when creating Gremlin scripts for first time users is to accidentally return an unserializable object. Gremlin - is a Groovy DSL and so it behaves like compiled Groovy including returning the last statement in the script. This is an example - of a Gremlin script that could cause unexpected failures: -
-- g.V().hasLabel("person").has("name", "John Smith").valueMap() --
- The valueMap() step is not directly serializable and will fail. To fix that you have two potential options: -
-- //Return a Map - g.V().hasLabel("person").has("name", "John Smith").valueMap().next() --
- Alternative: -
-- g.V().hasLabel("person").has("name", "John Smith").valueMap() - true //Return boolean literal -- - \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/main/resources/docs/org.apache.nifi.graph.TinkerpopClientService/additionalDetails.html b/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/main/resources/docs/org.apache.nifi.graph.TinkerpopClientService/additionalDetails.html new file mode 100644 index 0000000000..e14c372edf --- /dev/null +++ b/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/main/resources/docs/org.apache.nifi.graph.TinkerpopClientService/additionalDetails.html @@ -0,0 +1,93 @@ + + + + + +
+ This client service configures a connection to a Gremlin Server and allows Gremlin queries to be executed against + the Gremlin Server. For more information on Gremlin and Gremlin Server, see the Apache Tinkerpop project. +
+ ++ This client service supports two differnt modes of operation: Script Submission and Bytecode Submission, described below. +
+ ++ Script submission is the default way to interact with the gremlin server. This takes the input script and uses Script Submission + to interact with the gremlin server. Because the script is shipped to the gremlin server as a string, only simple queries are recommended (count, path, etc) + as there are no complex serializers available in this operation. This also means that NiFi will not be opinionated about what is returned, whatever the response from + the tinkerpop server is, the response will be deserialized assuming common Java types. In the case of a Map return, the values + will be returned as a record in the FlowFile response, in all other cases, the return of the query will be coerced into a + Map with key "result" and value being the result of your script submission for that specific response. +
+ ++ A common issue when creating Gremlin scripts for first time users is to accidentally return an unserializable object. Gremlin + is a Groovy DSL and so it behaves like compiled Groovy including returning the last statement in the script. This is an example + of a Gremlin script that could cause unexpected failures: +
++ g.V().hasLabel("person").has("name", "John Smith").valueMap() ++
+ The valueMap() step is not directly serializable and will fail. To fix that you have two potential options: +
++ //Return a Map + g.V().hasLabel("person").has("name", "John Smith").valueMap().next() ++
+ Alternative: +
++ g.V().hasLabel("person").has("name", "John Smith").valueMap() + true //Return boolean literal ++
+ Bytecode submission is the more flexible of the two submission method and will be much more performant in a production + system. When combined with the Yaml connection settings and a custom jar, very complex graph queries can be run directly + within the NiFi JVM, leveraging custom serializers to decrease serialization overhead. +
++ Instead of submitting a script to the gremlin server, requiring string serialization on both sides of the string result + set, the groovy script is compiled within the NiFi JVM. This compiled script has the bindings of g (the GraphTraversalSource) + and log (the NiFi logger) injected into the compiled code. Utilizing g, your result set is contained within NiFi and serialization + should take care of the overhead of your responses drastically decreasing the likelihood of serialization errors. +
++ As the result returned cannot be known by NiFi to be a specific type, your groovy script must rerun a Map<String, Object>, + otherwise the response will be ignored. Here is an example: +
++ Object results = g.V().hasLabel("person").has("name", "John Smith").valueMap().collect() + [result: results] ++
+ This will break up your response objects into an array within your result key, allowing further processing within nifi + if necessary. +
+ + \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/test/java/org/apache/nifi/graph/GremlinClientServiceIT.java b/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/test/java/org/apache/nifi/graph/GremlinClientServiceControllerSettingsIT.java similarity index 84% rename from nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/test/java/org/apache/nifi/graph/GremlinClientServiceIT.java rename to nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/test/java/org/apache/nifi/graph/GremlinClientServiceControllerSettingsIT.java index 15e8a87e83..92221731e1 100644 --- a/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/test/java/org/apache/nifi/graph/GremlinClientServiceIT.java +++ b/nifi-nar-bundles/nifi-graph-bundle/nifi-other-graph-services/src/test/java/org/apache/nifi/graph/GremlinClientServiceControllerSettingsIT.java @@ -33,21 +33,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; /* * As of JanusGraph 0.3.X these tests can be a little inconsistent for a few runs at first. */ -public class GremlinClientServiceIT { +public class GremlinClientServiceControllerSettingsIT { private TestRunner runner; private TestableGremlinClientService clientService; + @BeforeEach public void setup() throws Exception { clientService = new TestableGremlinClientService(); runner = TestRunners.newTestRunner(NoOpProcessor.class); runner.addControllerService("gremlinService", clientService); - runner.setProperty(clientService, AbstractTinkerpopClientService.CONTACT_POINTS, "localhost"); + runner.setProperty(clientService, TinkerpopClientService.CONTACT_POINTS, "localhost"); + runner.setProperty(clientService, TinkerpopClientService.PORT, "8182"); runner.enableControllerService(clientService); runner.assertValid(); + String teardown = IOUtils.toString(getClass().getResourceAsStream("/teardown.gremlin"), "UTF-8"); + clientService.getCluster().connect().submit(teardown); String setup = IOUtils.toString(getClass().getResourceAsStream("/setup.gremlin"), "UTF-8"); - clientService.getClient().submit(setup); + clientService.getCluster().connect().submit(setup); assertEquals("gremlin://localhost:8182/gremlin", clientService.getTransitUrl()); } @@ -55,7 +59,7 @@ public class GremlinClientServiceIT { @AfterEach public void tearDown() throws Exception { String teardown = IOUtils.toString(getClass().getResourceAsStream("/teardown.gremlin"), "UTF-8"); - clientService.getClient().submit(teardown); + clientService.getCluster().connect().submit(teardown); } @Test @@ -74,4 +78,4 @@ public class GremlinClientServiceIT { Map