Neo4j Java Driver Spring Boot Starter

The Spring Boot starter will be superseded by the Neo4j Java Driver auto config in the upcoming Spring Boot 2.4. For Spring Boot 2.3. we will still provide support with this starter.

As with any other Spring Boot starter, the only thing you have to do is to include the starter module via your dependency management. If you don’t configure anything, than the starter assumes bolt://localhost:7687 as Neo4j URI and a server that has disabled authentication.

If only a single URI is provided, than the configuration tries to use that. Otherwise, it passes all URIs to the Java driver which in turn uses the first one that is a reachable bolt+routing instance.

The automatic configuration will fail fast if the driver cannot connect to a single Neo4j database or to a routing server.

The Neo4j driver supports three different programming models:

  • Blocking database access (much like standard JDBC)

  • Asynchronous programming based on JDKs completable futures and related infrastructure

  • Reactive programming based on Reactive Streams

Those are all included in the same binary. The reactive programming model however requires a 4.0 Neo4j server on the database side and reactive Spring on the other hand. To make the following intro as accessible as possible, we only display the blocking database access. Have a look at the examples directory for a reactive web application example.

Preparing the database

For this example, we stay within the movie graph, as it comes for free with every Neo4j instance.

If you don’t have a running database but Docker installed, please run:

Start a local Neo4j instance inside Docker.
docker run --publish=7474:7474 --publish=7687:7687 neo4j:4.0.7

You know can access http://localhost:7474. At first visit, you have to change your password. We chose secret in the examples. Note the command ready to run in the prompt. Execute it to fill your database with some test data.

Create a new Spring Boot project

The easiest way to setup a Spring Boot project is start.spring.io (which is integrated in the major IDEs as well, in case you don’t want to use the website).

Select the "Spring Web Starter" to get all the dependencies needed for creating a Spring based web application. The Spring Initializr will take care of creating a valid project structure for you, with all the files and settings in place for the selected build tool.

Don’t choose Spring Data Neo4j here, as it will get you the previous generation of Spring Data Neo4j including OGM and additional abstraction over the driver.

Maven

You can issue a CURL request against the Spring Initializer to create a basic Maven project:

Create a basic Maven project with the Spring Initializr
curl https://start.spring.io/starter.tgz \
  -d dependencies=web,actuator \
  -d bootVersion=2.3.2.RELEASE \
  -d baseDir=Neo4jSpringBootExample \
  -d name=Neo4j%20SpringBoot%20Example | tar -xzvf -

This will create a new folder Neo4jSpringBootExample. As this starter is not yet on the initializer, you’ll have to add the following dependency manually to your pom.xml:

Inclusion of the neo4j-java-driver-spring-boot-starter in a Maven project
<dependency>
	<groupId>org.neo4j.driver</groupId>
	<artifactId>neo4j-java-driver-spring-boot-starter</artifactId>
	<version>4.1-SNAPSHOT</version>
</dependency>

You would also add the dependency manually in case of an existing project.

Gradle

The idea is the same, just generate a Gradle project:

Create a basic Gradle project with the Spring Initializr
curl https://start.spring.io/starter.tgz \
  -d dependencies=web,actuator \
  -d type=gradle-project \
  -d bootVersion=2.3.2.RELEASE \
  -d baseDir=Neo4jSpringBootExampleGradle \
  -d name=Neo4j%20SpringBoot%20Example | tar -xzvf -

The dependency for Gradle looks like this and must be added to build.gradle:

Inclusion of the neo4j-java-driver-spring-boot-starter in a Gradle project
dependencies {
    compile 'org.neo4j.driver:neo4j-java-driver-spring-boot-starter:4.1-SNAPSHOT'
}

You would also add the dependency manually in case of an existing project.

Configuration

Now open any of those projects in your favorite IDE. Find application.properties and configure your Neo4j credentials:

org.neo4j.driver.uri=bolt://localhost:7687
org.neo4j.driver.authentication.username=neo4j
org.neo4j.driver.authentication.password=secret
The URI is required. Autoconfiguration will not be triggered without it. This is to avoid clashes with the Spring Boot SDN/OGM starter. The SDN/OGM starter defaults to localhost, but backs off when it detects a driver bean. If this starter here would default to localhost as well, a driver bean would always be provided and SDN/OGM would back off even when a user configured a different URI.

This is the bare minimum of what you need to connect to a Neo4j instance.

Refer to the list of configuration properties for all options this driver supports.

While the above configuration is presented in the easiest format (an application.properties file), you are of course free to use any other declarative way to define properties in Spring Boot. Please checkout the chapter Externalized Configuration.

It is not necessary to add any programmatically configuration of the driver when you use this starter. While it may work, we strongly discourage and don’t support additional, pragmatical configuration of the Neo4j driver when using this starter.

Example CRUD Controller

Add the following @RESTController to your application:

MovieController.java
package com.example.demo;

import java.util.List;

import org.neo4j.driver.AccessMode;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.SessionConfig;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MoviesController {

	private final Driver driver; (1)

	public MoviesController(Driver driver) { (2)
		this.driver = driver;
	}

	@GetMapping(path = "/movies", produces = MediaType.APPLICATION_JSON_VALUE) (3)
	public List<String> getMovieTitles() {

		try (Session session = driver.session()) { (4)
			return session.run("MATCH (m:Movie) RETURN m ORDER BY m.name ASC")
				.list(r -> r.get("m").asNode().get("title").asString());
		}
	}
}
1 An instance field to hold the driver
2 The driver is injected via constructor injection
3 A mapping to the url /movies
4 Using the driver to get a short lived session and issue a query on it

If you generated your application via the commands given above, you can now run the class Neo4jSpringBootExampleApplication and after a short while, you can access http://localhost:8080/movies.

Logging

The Neo4j Spring Boot starter uses a small shim to integrate the driver with Springs JCL abstraction. Thus, all logging configuration can be done via Spring Boot’s application.properties. Important names used for logging are:

logging.level.org.neo4j.driver.GraphDatabase = debug
logging.level.org.neo4j.driver.Driver = debug

If you ever have the need to debug outgoing and incoming Bolt messages, use those two names:

logging.level.org.neo4j.driver.OutboundMessageHandler = debug
logging.level.org.neo4j.driver.InboundMessageDispatcher = debug
The prefix org.neo4j.driver is specific to the Drivers integration with Spring Boot.

Production-ready features

The Neo4j Spring Boot starter hooks into Spring Boot’s Production-ready features (or the so called Spring Boot Actuator). This happens automatically when you add the Spring Boot Actuator Starter like this:

Spring Boot Starter Actuator dependency with Maven
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

or with Gradle:

Spring Boot Starter Actuator dependency with Gradle
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-actuator'
}

We support both the health- and metrics-actuator.

Health information

Both reactive and imperative health checks are available, with the reactive health checks having precedence when Project Reactor is detected.

When calling the health endpoint /actuator/health and the driver can reach a Neo4j instance, an unauthenticated user will see

Health information
{
  "status": "UP"
}

and an authenticated user will see

Health information
{
  "status": "UP",
  "details": {
    "neo4j": {
      "status": "UP",
      "details": {
        "server": "Neo4j/4.0.0@localhost(127.0.0.1):7687",
        "database": "neo4j"
      }
    }
  }
}

In case no instance is reachable, the status will be DOWN and the details carry the error message.

To disable the Neo4j health indicator, use the standard Spring Boot property management.health.neo4j.enabled with a value of false.

Driver metrics

neo4j-java-driver-spring-boot-starter comes with support for Micrometer metrics out of the box. It detects Micrometer on the classpath and binds the metrics of all instances of org.neo4j.driver.Driver, that have enabled their metrics, to a micrometer registry.

To enable metrics for the driver instance provided by this starter, set org.neo4j.driver.config.metrics-enabled to true.

The following metrics are exposes

  • neo4j.driver.connections.inUse (Gauge)

  • neo4j.driver.connections.timedOutToAcquire (Counter)

  • neo4j.driver.connections.closed (Counter)

  • neo4j.driver.connections.failedToCreate (Counter)

  • neo4j.driver.connections.created (Counter)

  • neo4j.driver.connections.idle (Gauge)

  • neo4j.driver.connections.acquired (Counter)

All metrics will have the tags name (the bean of the driver they belong to) and poolId (the id of the connection pool, that contributed to the corresponding counter or gauge).