Contents
Overview
Neo4j is a graph database management system developed by Neo4j, Inc. It is an ACID-compliant transactional database with native graph storage and processing. Neo4j is available in a GPL3-licensed open-source “community edition”.
Maven Coordinates
To enable Neo4j add the following dependency to your project’s pom.xml (see Managing Dependencies).
<dependency>
<groupId>io.helidon.integrations.neo4j</groupId>
<artifactId>helidon-integrations-neo4j</artifactId>
</dependency>Check Neo4j Metrics Propagation and Neo4j Health Checks for additional dependencies for Neo4j Metrics and Health Checks integration.
Usage
The support for Neo4j is implemented in Neo4j driver level. Just add the dependency, add configuration in application.yaml file and Neo4j driver will be configured by Helidon and can be used with Neo4j support object.
To implement Neo4j, you must first provide the connection properties as shown below:
neo4j:
uri: bolt://localhost:7687
authentication:
username: neo4j
password: secret
pool:
metricsEnabled: trueThen just get the driver:
Neo4j neo4j = Neo4j.create(config.get("neo4j"));
Driver neo4jDriver = neo4j.driver();The driver can be used according to the Neo4j documentation.
Configuration
MicroProfile configuration options:
| key | type | default value | description |
|---|---|---|---|
mp.jwt.verify.publickey | string | The property allows the Public Verification Key text itself to be supplied as a string. | |
authentication.username | string | Neo4j authentication user name | |
authentication.password | string | Neo4j authentication password | |
authentication.enabled | boolean | TRUE | If Neo4j authentication is enabled |
encrypted | boolean | FALSE | If Neo4j encryption is enabled |
pool.metricsEnabled | boolean | FALSE | If Neo4J metrics is enabled |
pool.logLeakedSessions | boolean | Log leaking sessions | |
pool.maxConnectionPoolSize | string | Maximum connection pool size | |
pool.idleTimeBeforeConnectionTest | string | Idle time before connection test | |
pool.maxConnectionLifetime | string | Connection lifetime in seconds | |
pool.connectionAcquisitionTimeout | string | Connection Acquisition Timeout | |
trustsettings.trustStrategy | string | Trust Strategy: Trust All certificates, TRUST_ALL_CERTIFICATES, Trust custom certificates - TRUST_CUSTOM_CA_SIGNED_CERTIFICATES, Trust system CA - TRUST_SYSTEM_CA_SIGNED_CERTIFICATES | |
trustsettings.certificate | string | Path to trusted certificate | |
trustsettings.hostnameVerificationEnabled | string | FALSE | If hostname verification is enabled. |
Examples
This example implements a simple Neo4j REST service using MicroProfile. For this example a working Neo4j database is required. The Neo4j Movie database is used for this example.
Bring up a Neo4j instance via Docker
docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/secret' neo4j:latestGo to the Neo4j browser and play the first step of the movies graph: :play movies
Now go to the pom.xml and add the following dependencies:
<dependency>
<groupId>io.helidon.integrations.neo4j</groupId>
<artifactId>helidon-integrations-neo4j</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.integrations.neo4j</groupId>
<artifactId>helidon-integrations-neo4j-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.integrations.neo4j</groupId>
<artifactId>helidon-integrations-neo4j-health</artifactId>
</dependency>Next add the connection configuration properties for Neo4j:
neo4j:
uri: bolt://localhost:7687
authentication:
username: neo4j
password: secret
pool:
metricsEnabled: trueThis includes both connection information and enables Neo4j metrics propagation.
Finally, we are able to use the Neo4j driver.
@ApplicationScoped
public class MovieRepository {
private final Driver driver;
public MovieRepository(Driver driver) {
this.driver = driver;
}
public List<Movie> findAll() {
try (var session = driver.session()) {
var query = ""
+ "match (m:Movie) "
+ "match (m) <- [:DIRECTED] - (d:Person) "
+ "match (m) <- [r:ACTED_IN] - (a:Person) "
+ "return m, collect(d) as directors, collect({name:a.name, roles: r.roles}) as actors";
return session.readTransaction(tx -> tx.run(query).list(r -> {
var movieNode = r.get("m").asNode();
var directors = r.get("directors").asList(v -> {
var personNode = v.asNode();
return new Person(personNode.get("born").asInt(), personNode.get("name").asString());
});
var actors = r.get("actors").asList(v -> {
return new Actor(v.get("name").asString(), v.get("roles").asList(Value::asString));
});
var m = new Movie(movieNode.get("title").asString(), movieNode.get("tagline").asString());
m.setReleased(movieNode.get("released").asInt());
m.setDirectorss(directors);
m.setActors(actors);
return m;
}));
}
}
}- Constructor with
Neo4jdriver parameter - Use
Neo4jdriver to extract all Movies
Movies can now be returned as JSON objects:
public class MovieService implements Service {
private final MovieRepository movieRepository;
public MovieService(MovieRepository movieRepository) {
this.movieRepository = movieRepository;
}
@Override
public void update(Routing.Rules rules) {
rules.get("/api/movies", this::findMoviesHandler);
}
private void findMoviesHandler(ServerRequest request, ServerResponse response) {
response.send(this.movieRepository.findAll());
}
}To use the service, as well as to add metrics and health support, the following routing should be created:
private static Routing createRouting(Config config) {
MetricsSupport metrics = MetricsSupport.create();
Neo4j neo4j = Neo4j.create(config.get("neo4j"));
// registers all metrics
Neo4jMetricsSupport.builder()
.driver(neo4j.driver())
.build()
.initialize();
Neo4jHealthCheck healthCheck = Neo4jHealthCheck.create(neo4j.driver());
Driver neo4jDriver = neo4j.driver();
MovieService movieService = new MovieService(new MovieRepository(neo4jDriver));
HealthSupport health = HealthSupport.builder()
.addLiveness(HealthChecks.healthChecks()) // Adds a convenient set of checks
.addReadiness(healthCheck)
.build();
return Routing.builder()
.register(health) // Health at "/health"
.register(metrics) // Metrics at "/metrics"
.register(movieService)
.build();
}- Use of
Neo4jsupport object to initialise and configure the driver. - Use of
Neo4jMetricsSupportto add Neo4j metrics to/metricsoutput. - Use of
Neo4jHealthCheckto add Neo4j health support. - Initialize
MovieServicewith Neo4j driver. - Register the services in Routing.
Now build and run with JDK17+
mvn package
java -jar target/helidon-examples-integration-neo4j-mp.jarExercise the application:
curl -X GET http://localhost:8080/movies
{. . .}
# Try health and metrics
curl -s -X GET http://localhost:8080/health
{"outcome":"UP",...
. . .
# Prometheus Format
curl -s -X GET http://localhost:8080/metrics
# TYPE base:gc_g1_young_generation_count gauge
. . .
# JSON Format
curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
{"base":...
. . .Full example code is available in Helidon GitHub Repository.
Additional Information
Neo4j Metrics Propagation
Neo4j metrics can be propagated to the user as MicroProfile metrics. This is implemented in a separate Maven module. Just add:
<dependency>
<groupId>io.helidon.integrations.neo4j</groupId>
<artifactId>helidon-integrations-neo4j-metrics</artifactId>
</dependency>Works with Neo4j Integration main dependency described in Maven Coordinates.
To enable metrics in Neo4j, add the following property to application.yaml:
pool:
metricsEnabled: trueFinally, to initialize metrics run:
Neo4jMetricsSupport.builder()
.driver(neo4j.driver())
.build()
.initialize();Neo4j metrics will be automatically added to the output of the /metrics endpoint.
Neo4j Health Checks
If your application is highly dependent on Neo4j database, health and liveness checks are essential for this application to work correctly.
MicroProfile Health checks for Neo4j are implemented in a separate Maven module:
<dependency>
<groupId>io.helidon.integrations.neo4j</groupId>
<artifactId>helidon-integrations-neo4j-health</artifactId>
</dependency>Works with Neo4j Integration main dependency described in Maven Coordinates.
To enable health checks run the following code:
Neo4jHealthCheck healthCheck = Neo4jHealthCheck.create(neo4j.driver());
HealthSupport health = HealthSupport.builder()
.addReadiness(healthCheck)
.build();Health checks for Neo4j will be included in /health endpoint output.