Chapter 26. Neo4j Server

Neo4j is not only available in embedded mode. It can also be installed and run as a stand-alone server accessible via a REST API. Developers can integrate Spring Data Graph into the Neo4j server infrastructure in two ways: in an unmanaged server extension, or via the REST API.

26.1. Server Extension

When should you write a server extension? The default REST API is essentially a REST'ified representation of the Neo4j core API. It is nice for getting started, and for simpler scenarios. For more involved solutions that require high-volume access or more complex operations, writing a server extension that is able to process external parameters, do all the computations locally in the plugin, and then return just the relevant information to the calling client is preferable.

The Neo4j Server has two built-in extension mechanisms. It is possible to extend existing URI endpoints like the graph database, nodes, or relationships, adding new URIs or methods to those. This is achieved by writing a server plugin. This plugin type has some restrictions though.

For complete freedom in the implementation, an unmanaged extension can be used. Unmanaged extensions are essentially Jersey resource implementations. The resource constructors or methods can get the GraphDatabaseService injected to execute the necessary operations and return appropriate Representations.

Both kinds of extensions have to be packaged as JAR files and added to the Neo4j Server's plugin directory. Server Plugins are picked up by the server at startup if they provide the necessary META-INF.services/org.neo4j.server.plugins.ServerPlugin file for Java's ServiceLoader facility. Unmanaged extensions have to be registered with the Neo4j Server configuration.

Example 26.1. Configuring an unmanaged extension

org.neo4j.server.thirdparty_jaxrs_classes=com.example.mypackage=/my-context

Running Spring Data Graph on the Neo4j Server is easy. You need to tell the server where to find the Spring context configuration file, and which beans from it to expose:

Example 26.2. Server plugin initialization

public class HelloWorldInitializer extends SpringPluginInitializer {
    public HelloWorldInitializer() {
        super(new String[]{"spring/helloWorldServer-Context.xml"},
              Pair.of("worldRepository", WorldRepository.class),
              Pair.of("graphRepositoryFactory", GraphRepositoryFactory.class));
    }
}


Now, your resources can be annotated with the beans they need, like this:

Example 26.3. Jersey resource

@Path( "/path" )
@POST
@Produces( MediaType.APPLICATION_JSON )
public void foo( @Context WorldRepository repo ) {
    ...
}


The SpringPluginInitializer merges the GraphDatabaseService with the Spring configuration and registers the named beans as Jersey Injectables. It is still necessary to list the initializer's fully qualified class name in a file named META-INF/services/org.neo4j.server.plugins.PluginLifecycle. The Neo4j Server can then pick up and run the initialization classes before the extensions are loaded.

26.2. Using Spring Data Graph as a REST client

Spring Data Graph can use a set of Java REST bindings which come as a drop in replacement for the GraphDatabaseService API. By simply configuring the graphDatabaseService to be a RestGraphDatabase pointing to a Neo4j Server instance.

Note

The Neo4j Server REST API does not allow for transactions to span across requests, which means that Spring Data Graph is not transactional when running with a RestGraphDatabase.

Please also keep in mind that performing graph operations via the REST-API is about one order of magnitude slower than location operations. Try to use the Neo4j Cypher query language, server-side traversals (RestTraversal) or Gremlin expressions whenever possible for retrieving large sets of data. Future versions of Spring Data Graph will use the more performant batching as well as a binary protocol.

To set up your project to use the REST bindings, add this dependency to your pom.xml:

Example 26.4. REST-Client configuration - pom.xml

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-neo4j-rest</artifactId>
  <version>1.1.0.M2</version>
</dependency>


Now, you set up the normal Spring Data Graph configuration, but point the database to an URL instead of a local directory, like so:

Example 26.5. REST client configuration - application context

<datagraph:config graphDatabaseService="graphDatabaseService"/>

<bean id="graphDatabaseService" class="org.neo4j.rest.graphdb.RestGraphDatabase">
    <constructor-arg value="http://localhost:7474/db/data/"/>
</bean>


Your project is now set up to work against a remote Neo4j Server.

The remote REST implementation works for both the Neo4jTemplate as well as the GraphEntities. For traversals and cypher-graph-queries it is sensible to forward those to the remote and execute them there instead of walking the graph over the wire. RestGraphDatabase already supports that by providing methods that forward to the remote instance. (e.g. queryEngineFor(), index() and createTraversalDescription()). Please use those methods when interacting with a remote server for optimal performance.