Neo4j: Testing an unmanaged extension using CommunityServerBuilder
I’ve been playing around with Neo4j unmanaged extensions recently and I wanted to be able to check that it worked properly without having to deploy it to a real Neo4j server.
I’d previously used http://grepcode.com/file/repo1.maven.org/maven2/org.neo4j/neo4j-kernel/1.2-1.2/org/neo4j/kernel/ImpermanentGraphDatabase.java when using Neo4j embedded and Ian pointed me towards CommunityServerBuilder which allows us to do a similar thing in Neo4j server world.
I’ve created an example of a dummy unmanaged extension and test showing this approach but it’s reasonably simple.
Given the following unmanaged extension:
package org.neo4j.unmanaged;
@Path("/dummy")
public class DummyResource
{
private final ExecutionEngine executionEngine;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public DummyResource( @Context GraphDatabaseService database )
{
this.executionEngine = new ExecutionEngine(database);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/all-nodes")
public Response uploadNodesFile( ) throws IOException
{
ExecutionResult result = executionEngine.execute("START n = node(*) RETURN n.name ORDER BY n.name");
ObjectNode root = JsonNodeFactory.instance.objectNode();
for (String column : result.columns()) {
ResourceIterator<Object> rows = result.columnAs(column);
ArrayNode resultRows = JsonNodeFactory.instance.arrayNode();
while(rows.hasNext()) {
Object row = rows.next();
if(row != null) {
resultRows.add(row.toString());
}
}
root.put(column, resultRows);
}
return Response.status( 200 )
.entity(OBJECT_MAPPER.writeValueAsString(root))
.type(MediaType.APPLICATION_JSON).build();
}
}
We would write the following test which exposes the 'all-nodes' resource at '/unmanaged/dummy/all-nodes':
package org.neo4j.unmanaged;
public class DummyResourceTest {
private GraphDatabaseAPI db;
private CommunityNeoServer server;
@Before
public void before() throws IOException {
ServerSocket serverSocket = new ServerSocket(0);
server = CommunityServerBuilder
.server()
.onPort(serverSocket.getLocalPort())
.withThirdPartyJaxRsPackage("org.neo4j.unmanaged", "/unmanaged")
.build();
server.start();
db = server.getDatabase().getGraph();
}
@After
public void after() {
server.stop();
}
@Test
public void shouldReturnAllTheNodes() {
Transaction tx = db.beginTx();
db.createNode().setProperty("name", "Mark");
db.createNode().setProperty("name", "Dave");
tx.success();
tx.close();
JsonNode response = jerseyClient()
.resource(server.baseUri().toString() + "unmanaged/dummy/all-nodes")
.get(ClientResponse.class)
.getEntity(JsonNode.class);
assertEquals("Dave", response.get("n.name").get(0).asText());
assertEquals("Mark", response.get("n.name").get(1).asText());
}
private Client jerseyClient() {
DefaultClientConfig defaultClientConfig = new DefaultClientConfig();
defaultClientConfig.getClasses().add(JacksonJsonProvider.class);
return Client.create(defaultClientConfig);
}
}
Here we add a couple of nodes directly against the Java API and then call our unmanaged extension using a Jersey HTTP client. CommunityServerBuilder spins up an ephemeral store under the covers and we pick a random free port for Neo4j server by using ServerSocket#getLocalPort.
We import CommunityServerBuilder by including the following dependency:
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<version>${neo4j.version}</version>
<type>test-jar</type>
</dependency>
And that’s it!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.