This is a knowledge base like checklist meant to support in you in
finding out what parts of Neo4j-OGM or Spring Data (Neo4j) an existing application uses
finding out if and on which version of Spring Boot you are
knowing which properties are relevant for your configuration
judging if you need custom configuration classes for your deployment or not
finding the relevant documentation and versions
If possible, things have been ordered roughly from lower level connectivity and data access to data mapping specific or in other words, from very little abstraction to high abstraction.
Less is more! That applies to dependencies and to manual, programmatic configuration. Most scenarios are covered with a restricted set of dependencies and configurable with properties or one additional config bean. |
1. Terminology
A couple of classes have similar names which is confusing. Therefore some of the relevant classes have been included below.
Classes named Config
or Configuration
are nearly everywhere.
-
org.neo4j.driver.Config
is the pure Driver config -
org.neo4j.ogm.config.Configuration
is Neo4j-OGM config -
org.springframework.context.annotation.Configuration
is an annotation of the Spring Framework, annotating a class as a source of Beans and configuration.
1.1. Neo4j Java Driver
The Neo4j Java Driver is a Java based implementation of Neo4j’s Bolt protocol and can be used throughout the Java ecosystem. It can be used standalone, in different frameworks and from within different languages on the JVM. It works with Groovy and Kotlin. There are integrations with Quarkus and Micronaut.
The following classes are part of the Neo4j Java Driver
-
org.neo4j.driver.Config
-
org.neo4j.driver.Driver
-
org.neo4j.driver.GraphDatabase
-
org.neo4j.driver.Record
-
org.neo4j.driver.Result
-
org.neo4j.driver.Session
1.2. Neo4j-OGM
Neo4j-OGM is a general purpose Object Graph Mapper for Neo4j. Neo4j-OGM can be used in standalone applications and with other frameworks outside the Spring ecosystem.
Neo4j-OGM supports a couple of different transports to a Neo4j database. It’s primary transport is the Bolt transport, but it can use the HTTP endpoint as well as an embedded database. Read about the building blocks here.
Neo4j-OGM has similar classes to the driver. Be aware they are only similar and have different semantics:
-
org.neo4j.ogm.annotation.GeneratedValue
-
org.neo4j.ogm.annotation.Id
-
org.neo4j.ogm.annotation.NodeEntity
-
org.neo4j.ogm.annotation.RelationshipEntity
-
org.neo4j.ogm.driver.Driver
-
org.neo4j.ogm.drivers.bolt.driver.BoltDriver
-
org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver
-
org.neo4j.ogm.drivers.http.driver.HttpDriver
-
org.neo4j.ogm.model.Result
-
org.neo4j.ogm.session.Session
-
org.neo4j.ogm.session.SessionFactory
Inside a Spring Boot application, both the Neo4j-OGM SessionFactory and Session are injectable (via @Autowired or constructor injection).
The Session will be a proxy, participating in Spring transactions and reopened transparently for you.
If you need access to the OGM session, this would be the preferred way.
Opening one yourself via the SessionFactory is possible, but can lead to issues.
|
1.3. Spring Data Neo4j vs. Spring Data Neo4j⚡️RX
Spring Data Neo4j (in short SDN) is the current, officially released Spring Data module for Neo4j. It lives in VMware / Pivotal repositories but is maintained by Neo4j. It is part of the Spring Data release train and you get it when you generate a project with Neo4j support on start.spring.io. SDN is build on top of Neo4j-OGM.
Spring Data Neo4j⚡️RX (in short SDN/RX) is a new approach to OGM in the Spring Ecosystem. It is currently in beta phase, but feature complete. It will eventually replace SDN. Object mapping is facilitated through Spring Data. While SDN/RX has a different approach and opinion on mappings, it supports all Spring Data features, like immutable entity-classes, reactive database access with Neo4j 4.0, query by example.
The modules must not be used together in one application.
SDN/RX brings it’s one set of annotations for marking entities:
-
org.neo4j.springframework.data.core.schema.Node
-
org.neo4j.springframework.data.core.schema.GeneratedValue
-
org.neo4j.springframework.data.core.schema.Id
-
org.neo4j.springframework.data.core.schema.Property
-
org.neo4j.springframework.data.core.schema.Relationship
1.4. Release trains
All Spring data projects that are handled by the core Spring Data Team at VMware use so called "release trains". These release trains are given names that sort alphabetically. This is done to mitigate the fact that the modules that are part of a release train usually have different version numbers (Spring Data Neo4j is not the only Spring Data module).
Modules and projects handled by Neo4j don’t have that concept. Neo4j-OGM, the Neo4j Java driver, SDN/RX and the starters have standard version numbers only.
2. Spring Boot or not Spring?
A project with a dependency to org.springframework.boot:spring-boot-starter
and a single Java class similar to this:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
is a Spring Boot application.
The key indicator to look for is the presence of @SpringBootApplication
.
3. Version management in Spring Boot applications
One of Spring Boots main features and advantages is that it does version management for you. That is: You can declare most dependencies in your build file without a version. That works through a mechanism called Bill of material. Please read the linked post.
To use a different version of a library than the one that is part of Spring, you don’t declare that library as a dependency with a concrete version number. First, have a look if it’s a managed library. You find all managed dependencies here: Managed Dependency Coordinates and the corresponding property names under Version Properties.
If you’re library is on that list, you can overwrite the version of it as follows:
4. Custom programmatic configuration for Neo4j-OGM?
With Spring Boot it is often possible to abstain from a lot of custom, programmatic configuration. Instead you can rely on Spring Boot’s auto configuration mechanism (find some slides and talks about that here and here)
There are some rare cases where programmatic configuration is necessary.
4.1. Things you can configure via properties and annotations
-
Database connection via
spring.data.neo4j.uri
It supportsbolt
,bolt+routing
,neo4j
for Bolt transport,http
andhttps
for Http transport andfile
for embedded if you must. -
spring.data.neo4j.username
andspring.data.neo4j.password
are complementary for the aboveuri
property. -
spring.data.neo4j.use-native-types
can be set to true with the necessary libraries on the classpath to use native date and spatial types without converters -
The packages to look for entities can be configured via
@EntityScan
, see Listing 1 -
The same applies for Neo4j repositories
@EntityScan("your.domain.package") (1)
@EnableNeo4jRepositories("your.repository.pacakge") (2)
public class Neo4jConfig {
}
1 | One or more packages to scan for annoted entities (@NodeEntity and @RelationshipEntity ) |
2 | One or more packages to scan for interfaces extending (Neo4jRepository or generic Spring Data repository interfaces) |
4.2. Configuring the Neo4j Java Driver
In case you want to use only the Java Driver in your Spring Boot application or you only want to use the Bolt transport for your Neo4j-OGM application,
you can bring in the Neo4j Spring Boot Starter.
The only thing it does is to configure a Spring bean of type org.neo4j.driver.Driver
.
That bean is automatically recognized by Neo4j-OGM as long as you don’t put in other custom, programmatic Java configuration.
The above starter gives you direct access to all configuration options that the Neo4j Java Driver others, via Spring Boots properties (applicable from files, config server etc.). Here is the full reference.
Be aware that the configuration prefix needs to be org.neo4j.driver in this case! If you don’t provide org.neo4j.driver.uri ,
the additional starter will be inactive!
|
4.3. Specialized Neo4j-OGM configuration
If you need to configure Neo4j-OGM beyond the currently exposed properties inside Spring Boot, it is enough to provide a bean of type org.neo4j.ogm.config.Configuration
.
With the latest versions of Spring Boot 2.1 and 2.2 it is not necessary anymore to add a Neo4j-OGM SessionFactory.
Your configuration would look similar like this:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
@Configuration
@EnableNeo4jRepositories("your.repository.pacakge")
public class Neo4jConfig {
@Bean
org.neo4j.ogm.config.Configuration neo4jOgmConfiguration() {
return new org.neo4j.ogm.config.Configuration.Builder().credentials("some user", "somepassword")
.withBasePackages("your.domain.package")
.strictQuerying()
.useNativeTypes()
.database("myDatabase")
.uri("neo4j://somehost")
.build();
}
}
You don’t usually need more. The best choice however is to see if our additional Neo4j Spring Boot starter already solves your problem.
5. Using exiting properties
In most cases, there is no reason to use @Value from Spring Boot to map custom properties.
You can always inject the following classes (depending on the starter you are using):
|
-
org.springframework.boot.autoconfigure.data.neo4j.Neo4jProperties
(For the current Spring Boot Neo4j integration) -
org.neo4j.driver.springframework.boot.autoconfigure.Neo4jDriverProperties
(For the new Neo4j Spring Boot Start)Those will automatically contain the configured properties, they don't need to be duplicated in your classes. You can just build on top of them, as shown https://github.com/neo4j/neo4j-java-driver-spring-boot-starter/blob/4.0.0.1/examples/dedicated-routing-driver/src/main/java/org/neo4j/doc/driver/springframework/boot/dedicated_routing_driver/RoutingDriverConfiguration.java#L23-L27[here].
6. Maven / Gradle coordinates
Those are the official Maven central coordinates, given in the form groupId:artifactId
for a quick reference.
6.1. Driver
6.1.1. Neo4j Java Driver
For a Spring Boot application, always use: org.neo4j.driver:neo4j-java-driver-spring-boot-starter
.
Use org.neo4j.driver:neo4j-java-driver
only for Spring applications not based on Spring Boot.
Don’t add both.
The starter gives you IDE support in application.properties
and application.yml
for all configuration options.
6.2. Data mapping and higher level abstractions
6.2.1. Neo4j-OGM
-
The core module (You always need this):
org.neo4j:neo4j-ogm-core
-
One of the transport modules (You should have only one per dependency scope)
-
The Bolt implementation:
org.neo4j:neo4j-ogm-bolt-driver
-
The embedded implementation:
org.neo4j:neo4j-ogm-embedded-driver
-
The HTT implementation:
org.neo4j:neo4j-ogm-http-driver
-
-
Optional (only supported for the Bolt and embedded implementation): Support for additional Neo4j native types
-
Native types for the Bolt implementation:
org.neo4j:neo4j-ogm-bolt-native-types
-
Native types for the embedded implementation:
org.neo4j:neo4j-ogm-embedded-native-types
-
6.2.2. Spring Data Neo4j
For a Spring Boot application, always use: org.springframework.boot:spring-boot-starter-data-neo4j
.
Use org.springframework.data:spring-data-neo4j
only for Spring applications not based on Spring Boot.
Don’t add both.
In either way, you will get all the necessary, transitive dependencies.
For Spring Data Neo4j it is not necessary to add the core or bolt module of Neo4j-OGM. They are transitive dependencies. To be able to use the other transports, you have to configure the relevant dependencies. |
You can add org.neo4j.driver:neo4j-java-driver-spring-boot-starter
to a Spring Boot based SDN application
and Neo4j-OGM and SDN will recognize the driver bean.
Please read more about it here.
6.2.3. SDN/RX
For a Spring Boot application, always use: org.neo4j.springframework.data:spring-data-neo4j-rx-spring-boot-starter
.
Use org.neo4j.springframework.data:spring-data-neo4j-rx
only for Spring applications not based on Spring Boot.
In either way, you will get all the necessary, transitive dependencies.
For SDN/RX it is not necessary to add the Section 6.1.1. You’ll receive the Starter for the Driver through the SDN/RX starter. You’ll receive the Driver through SDN/RX. |
7. Documentation
Given the various modules, the documentation lives in a couple of places as well.
This checklist is part of repository containing a bunch of useful other information. Please find it here: https://github.com/michael-simons/neo4j-sdn-ogm-tips
7.2. Data mapping and higher level abstractions
8. Various important things
8.1. Causal cluster setup
Please read Spring Data Neo4j, Neo4j-OGM and Open Session in View (OSIV). If you are on Spring Boot before Spring Boot 2.3, you have to turn off the Open-Session-In-View-Filter, otherwise all queries will go to the leader.
You can do this via a configuration property: spring.data.neo4j.open-in-view=false
.
8.2. Routing driver
There are a couple of ways to configure a driver to use routing.
The canonical way is to use bolt+routing://
or neo4j://
from Neo4j 4.0 on upwards with a single entry URL into the cluster.
The driver manual is very clear on that: Connection URIs.
You can configure multiple URIs through a custom Neo4j-OGM configuration as follows:
@Bean
org.neo4j.ogm.config.Configuration neo4jOgmConfiguration() {
return new org.neo4j.ogm.config.Configuration.Builder()
.credentials("some user", "somepassword")
.uris(
"bolt+routing://server1",
"bolt+routing://server2",
"bolt+routing://server3")
.build();
}
or use a setup as shown in our example here: RoutingDriverConfiguration
.
The idea is to define only one single property containing multiple URIs and build your driver instance with that.
A better solution however is the usage of a custom resolver function.
Given some arbitrary org.neo4j.driver.net.ServerAddressResolver
like this:
ServerAddressResolver serverAddressResolver = address -> {
if ("datacenter1".equals(address.host())) {
return new HashSet<>(
Arrays.asList(ServerAddress.of("dc1-core1", 7687), ServerAddress.of("dc1-core2", 7687)));
} else {
return new HashSet<>(Arrays.asList(ServerAddress.of("other-core", 7687)));
}
};
Here’s how to use it with OGM+SDN only:
import java.util.Arrays;
import java.util.HashSet;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.springframework.boot.autoconfigure.data.neo4j.Neo4jProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Neo4jConfig {
@Bean
public Driver neo4jDriver(Neo4jProperties springDataNeo4jProperties) {
Config config = Config.builder()
.withResolver(serverAddressResolver).build();
return GraphDatabase.driver(springDataNeo4jProperties.getUri(),
AuthTokens.basic(springDataNeo4jProperties.getUsername(), springDataNeo4jProperties.getPassword()), config);
}
}
Or use with the Neo4j Spring Boot starter (mind the slightly different import).
import java.util.Arrays;
import java.util.HashSet;
import org.neo4j.driver.AuthToken;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.springframework.boot.autoconfigure.Neo4jDriverProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class DriverWithCustomResolverFunctionConfiguration {
@Bean
public Driver neo4jDriver(Neo4jDriverProperties neo4jDriverProperties) {
Config config = Config.builder()
.withResolver(serverAddressResolver).build();
AuthToken authToken = neo4jDriverProperties.getAuthToken();
return GraphDatabase.driver(neo4jDriverProperties.getUri(), authToken, config);
}
}