Quarkus

For Java developers who use Quarkus and want to take advantage of a pre-configured Java driver instance as well as the integration with OGM. Please consult the linked documentations for more information.

What we will cover

  • Movies example application

  • Quarkus Neo4j driver integration

  • Neo4j OGM integration

  • Health & metrics support

Getting started

Over the next few sections, we will walk through all of the steps for creating a Quarkus application with Neo4j.

You can fetch the Movies example project from GitHub:

git clone https://github.com/sdaschner/movies-java-quarkus/
cd movies-java-quarkus/

Building & running locally

You can build the project via Maven:

mvn package

Additionally, you can execute the integration test, which fires up a local Neo4j instance via Testcontainers:

mvn test-compile failsafe:integration-test failsafe:verify

You run the Quarkus application via executable JAR:

java -jar target/quarkus-app/quarkus-run.jar

This starts up your Quarkus application which then is available under http://localhost:8080/

Now, you can give it a try and explore the movies queries examples.

Run the database locally

Per default, the example runs with a generally-available database under https://demo.neo4jlabs.com:7473

You can also run a local Neo4j database with the example project as Docker container. For this, execute the ./run-graph-db.sh script, and change the Quarkus application properties under src/main/resources/application.properties.

# run in a separate shell, starts up a Docker container from neo4j:4.4.12
./run-graph-db.sh
Quarkus application.properties
quarkus.neo4j.uri=bolt://localhost:7687
quarkus.neo4j.authentication.username=neo4j
quarkus.neo4j.authentication.password=test

Quarkus dev mode

In order to improve the development experience and to quickly change code, you can use Quarkus' dev mode, which is compatible with the Neo4j and Neo4j OGM extensions:

mvn quarkus:dev

This also starts up your application with port 8080, but keeps the connection to your source code and allows for quick redeploys.

Congratulations! Now you have everything to develop Quarkus applications with Neo4j.

The following explains how our Quarkus application accesses the Neo4j database, and how the OGM mapping is integrated.

Understanding the examples

Our Quarkus application uses the Neo4j-OGM Quarkus extension that we recommend to use in case you want to make use of the Object Graph Mapper.

The pom.xml includes this dependency which transitively adds the Neo4j Quarkus extension and OGM dependencies:

Neo4j-OGM Quarkus dependency
<dependency>
  <groupId>org.neo4j</groupId>
  <artifactId>neo4j-ogm-quarkus</artifactId>
  <version>1.5.1</version>
</dependency>

With that being included, your Quarkus application configures the Neo4j driver and sets up the OGM mapping session factory as injectable bean.

You can get an idea of the OGM session factory usage in the following classes:

@ApplicationScoped
public class Searches {

    @Inject
    SessionFactory sessionFactory;

    public List<Movie> searchMoviesByTitle(String title) {
        Session session = sessionFactory.openSession();
        Iterable<Movie> iterable = session.query(Movie.class, "MATCH (movie:Movie) WHERE movie.title CONTAINS $title RETURN movie", Map.of("title", title));

        // [...]
    }
}

The domain entities, such as Movie are declared as OGM node entity classes:

@NodeEntity
public class Movie {

    @Id
    public String title;
    public String tagline;
    public Integer released;
    public int votes;

    @Relationship(value = "DIRECTED", direction = INCOMING)
    @JsonbTypeSerializer(PersonNamesSerializer.class)
    public Set<Person> directors = new HashSet<>();

    @Relationship(value = "WROTE", direction = INCOMING)
    @JsonbTypeSerializer(PersonNamesSerializer.class)
    public Set<Person> writers = new HashSet<>();

    @Relationship(value = "PRODUCED", direction = INCOMING)
    @JsonbTypeSerializer(PersonNamesSerializer.class)
    public Set<Person> producers = new HashSet<>();

    @Relationship(value = "REVIEWED", direction = INCOMING)
    @JsonbTypeSerializer(ReviewsSerializer.class)
    public Set<Review> reviewers = new HashSet<>();

    @Relationship(value = "ACTED_IN", direction = INCOMING)
    @JsonbTypeSerializer(ActsSerializer.class)
    public Set<Act> actors = new HashSet<>();
}

Have a look at the Object Graph Mapper docs for a more detailed explanation. The @JsonbTypeSerializer annotation controls how the entity objects are mapped to JSON for the JAX-RS REST endpoints.

You can follow the code in the MovieResource, SearchResource, ActorsResource, and GraphResource JAX-RS classes to comprehend the individual use cases.

Another helpful OGM feature added in 4.0 is the mapping of DTO classes and Java records. These types are mapped from arbitrary query results and the corresponding classes don’t have to be annotated. For an example see the Persons class and the usage of the session.queryDto() method:

@ApplicationScoped
public class Persons {

    @Inject
    SessionFactory sessionFactory;

    public List<ActorRecommendation> recommendCoActor(String name) {
        Session session = sessionFactory.openSession();
        return session.queryDto(" MATCH (actor:Person {name: $name}) [...] " +
			      " [...] " +
            " RETURN cocoActors.name AS actor, count(*) AS strength ORDER BY strength DESC",
            Map.of("name", name), ActorRecommendation.class);
    }
}
public record ActorRecommendation(String actor, long strength) {

}

Quarkus Neo4j features

In the following, we have a look at the integration features that are available with Quarkus and Neo4j.

Driver integration

The goal of the Quarkus Neo4j integration is to provide support for getting a managed instance of the Neo4j driver. You can provide the driver properties via the Quarkus configuration mechanisms, usually in the application.properties file, to configure your application. In the end you will have an injectable driver instance that can be used with

@Inject
Driver driver;

in the business operation code base.

You probably noticed that we’re not using this injection in our Movies example, but instead injected the OGM session factory. Both works and it depends on your use case and application setup, which way you choose.

Additional to the managed driver bean creation, the integrations also expose health metrics for the driver and connection to your Neo4j instance.

In an existing Quarkus application you need to add the quarkus-neo4j dependency to your project.

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-neo4j</artifactId>
</dependency>
If you’re using the Neo4j-OGM Extension, this dependency will be included transitively and shouldn’t be declared explicitly.

You can configure the basic connection parameters as needed.

Quarkus application.properties
quarkus.neo4j.uri = bolt://localhost:7687
quarkus.neo4j.authentication.username = neo4j
quarkus.neo4j.authentication.password = secret

Health check integration

If you want to make use of the health check, the additional quarkus-smallrye-health dependency is needed.

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-health</artifactId>
</dependency>

Metrics integration

For metrics support, you would either need MicroMeter (recommended by Quarkus) or SmallRye Metrics (only if you really need MicroProfile specification) dependencies declared.

MicroMeter (Prometheus) dependency
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>

The metrics for Neo4j have to be manually enabled in the application.properties.

quarkus.neo4j.pool.metrics-enabled = true

OGM Integration

Your Quarkus application can be integrated with Neo4j OGM in order to provide declarative object mappings for your domain entities. There is an official Quarkus extension available, that we recommend to use unless you have a reason not to do so.

Neo4j-OGM Quarkus dependency
<dependency>
  <groupId>org.neo4j</groupId>
  <artifactId>neo4j-ogm-quarkus</artifactId>
  <version>1.5.1</version>
</dependency>
<!-- with this, you can remove io.quarkus:quarkus-neo4j from your pom.xml again -->

This dependency transitively includes Neo4j OGM and the Quarkus Neo4j dependency, so it’s the only Neo4j dependency you need in your pom.xml.

The Neo4j-OGM Quarkus dependency configures the OGM session factory and makes it injectable as bean:

@Inject
SessionFactory sessionFactory;

Resources

Quarkus Documentation

Neo4j integration, Configuration properties, Guide

Neo4j-OGM Quarkus Extension

GitHub

Examples

Quarkus examples