Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Quarkus meets Neo4j

Quarkus meets Neo4j

I’m gonna first speak briefly about Neo4j itself, what’s the core product and why you might interested in it.
Give you an idea about my background (while this is often irrelevant or marketing, it may be of interest in the context of Quarkus)
Praise the Java community, which despite some other rumors manages to work closely together with great benefit for the whole ecosystem
We will than have a look at the building blocks of a Quarkus extension as well as the Neo4j database drivers
Quarkus calls itself „Supersonic subatomic Java“ and „a Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM“, meaning that applications build with it should be able to use GraalVM’s native-image tool to produce binary running GraalVMs SubstrateVM. For us this required changes to our Java driver which I would like to discuss as well.
And last but not least, I want to show you the resulting pieces in action

Michael Simons

September 09, 2020
Tweet

More Decks by Michael Simons

Other Decks in Programming

Transcript

  1. About writing a natively compilable Quarkus extension
    Michael Simons, @rotnroll666
    Quarkus meets Neo4j

    View Slide

  2. Quarkus meets Neo4j by @rotnroll666
    • About Neo4j
    • About me and Quarkus
    • Building blocks of…
    • … the Neo4j database driver
    • … a Quarkus extension
    • The search for the holy Graal(VM): AoT compiling a database driver.
    2
    Agenda

    View Slide

  3. About Neo4j

    View Slide

  4. Ecosystem
    Neo4j Professional Services
    300+ partners
    47,000 group members
    61,000 trained engineers
    3.5M downloads
    Mindset
    “Graph Thinking” is all about
    considering connections in
    data as important as the
    data itself.
    Native Graph Platform
    Neo4j is an internet-scale,
    native graph database which
    executes connected workloads
    faster than any other database
    management system.
    Neo4j
    4

    View Slide

  5. The whiteboard model
    IS the physical model
    • Bands are founded in and
    solo artists are born in countries
    • Sometimes Artists are
    associated with other Artists
    and bands have member
    • Artists used to release
    Albums
    :Artist
    :Band
    :SoloArtist
    :Country
    :FOUNDED_IN
    :BORN_IN
    :ASSOCIATED_WITH
    :HAS_MEMBER
    :Album
    :RELEASED_BY
    5

    View Slide

  6. Querying with Cypher
    • Cypher is to Neo4j what SQL is to RDBMS:
    A declarative, powerful query language
    • https://www.opencypher.org / The GQL Manifesto
    MATCH (a:Album) -[:RELEASED_BY]-# (b:Band),
    (c) $-[:FOUNDED_IN]- (b) -[:HAS_MEMBER]-# (m) -[:BORN_IN]-# (c2)
    WHERE a.name = 'Innuendo'
    RETURN b, m, c, c2
    6

    View Slide

  7. About me and Quarkus

    View Slide

  8. Quarkus meets Neo4j by @rotnroll666
    • Neo4j since July 2018
    • Java Champion
    • Co-Founder and current lead of Java User Group EuregJUG
    • Author (Spring Boot 2 und Arc42 by example)
    About me
    8
    First contact to Neo4j through

    View Slide

  9. Quarkus meets Neo4j by @rotnroll666
    Graph Tour 2019
    9
    Now online:
    https://neo4j.com/graphtour/

    View Slide

  10. Quarkus meets Neo4j by @rotnroll666
    Graph Tour 2019
    9
    Now online:
    https://neo4j.com/graphtour/

    View Slide

  11. Quarkus meets Neo4j by @rotnroll666
    A Hibernate team lead appears…
    10
    With Sanne Grinovero,
    Hibernate Team Lead & Quarkus R&D

    View Slide

  12. Building blocks

    View Slide

  13. Quarkus meets Neo4j by @rotnroll666 12
    The Neo4j Java-Driver


    org.neo4j.driver#$groupId>

    neo4j-java-driver#$artifactId>

    4.1.1#$version>

    #$dependency>

    var driver = GraphDatabase.driver(

    "bolt:#%localhost:7687",

    AuthTokens.basic("neo4j", "secret"),

    Config.builder().withLogging(Logging.console(Level.INFO)).build()

    );

    View Slide

  14. Quarkus meets Neo4j by @rotnroll666 13
    Imperative sessions
    Function getNameFromRecord =

    record #& record.get("name").asString();

    try (var session = driver.session()) {

    var names = session.readTransaction(

    tx #& tx

    .run("MATCH (n:Artist) RETURN n.name AS name")

    .stream().map(getNameFromRecord)

    .collect(toList())

    );

    names.forEach(System.out#'println);

    }

    View Slide

  15. Quarkus meets Neo4j by @rotnroll666 14
    Reactive sessions with Project Reactor
    Function getNameFromRecord =

    record #& record.get("name").asString();

    RxTransactionWork
    tx #& tx.run("MATCH (n:Artist) RETURN n.name AS name").records();

    Flux.usingWhen(

    Mono.fromSupplier(driver#'rxSession),

    session #& session.readTransaction(txFunction),

    RxSession#'close

    )

    .map(getNameFromRecord)

    .doOnNext(System.out#'println)

    .blockLast(); !" Don't block at home

    View Slide

  16. Quarkus meets Neo4j by @rotnroll666 15
    Reactive sessions with SmallRye Mutiny
    Function getNameFromRecord =

    record #& record.get("name").asString();

    RxTransactionWork
    tx #& tx.run("MATCH (n:Artist) RETURN n.name AS name").records();

    Uni.createFrom().item(driver#'rxSession).toMulti()

    .flatMap(session #& session.readTransaction(txFunction))

    .map(getNameFromRecord)

    .subscribe()

    .asStream()

    .forEach(System.out#'println);

    View Slide

  17. Quarkus meets Neo4j by @rotnroll666 16
    The Quarkus extension system
    var driver = GraphDatabase.driver(

    "bolt:#%localhost:7687",

    AuthTokens.basic("neo4j", "secret"),

    Config.builder().withLogging(Logging.console(Level.INFO)).build()

    );

    View Slide

  18. Quarkus meets Neo4j by @rotnroll666 16
    The Quarkus extension system
    quarkus.neo4j.uri = bolt:#%localhost:7687

    quarkus.neo4j.authentication.username = neo4j

    quarkus.neo4j.authentication.password = secret
    @Path("/hello")

    public class ExampleResource {

    private final Driver driver;

    @Inject

    public ExampleResource(Driver driver) {

    this.driver = driver;

    }

    }

    View Slide

  19. Quarkus meets Neo4j by @rotnroll666
    • The runtime module which represents the capabilities the
    extension developer exposes to the application’s developer
    • The deployment module which is used during the
    augmentation phase of the build, it describes how to "deploy" a
    library following the Quarkus philosophy
    The deployment module often depends on the runtime
    module.
    17
    The Quarkus extension system
    A Quarkus extension consists of two parts:

    View Slide

  20. Quarkus meets Neo4j by @rotnroll666
    • GraalVM restrictions
    • Dynamic class loading (Classes must be enumerated)
    • Reflection (Must be enumerated, too)
    • JCA (Java Cryptography Architecture) needs special treatment
    • Optimizing things (i.e. Replacing Service Loader with an index)
    • @BuildStep’s record byte code with @Recorder’s
    18
    The Quarkus extension system
    Three phases of bootstrapping: 1. Augmentation via build step processors

    View Slide

  21. Quarkus meets Neo4j by @rotnroll666
    •@Record(STATIC_INIT)

    • Will run in a static init method on the main class during native
    build
    • Executed on the standard JVM during build
    • Objects will be directly serialized into the native executable
    19
    The Quarkus extension system
    Three phases of bootstrapping: 2. Static init

    View Slide

  22. Quarkus meets Neo4j by @rotnroll666
    •@Record(RUNTIME_INIT)

    • Will run from the applications main method during native boot
    20
    The Quarkus extension system
    Three phases of bootstrapping: 3. Runtime init

    View Slide

  23. Quarkus meets Neo4j by @rotnroll666
    •@Record(RUNTIME_INIT)

    • Will run from the applications main method during native boot
    21

    View Slide

  24. Quarkus meets Neo4j by @rotnroll666
    •@Record(RUNTIME_INIT)

    • Will run from the applications main method during native boot
    21

    View Slide

  25. Quarkus meets Neo4j by @rotnroll666
    •@Record(RUNTIME_INIT)

    • Will run from the applications main method during native boot
    21

    View Slide

  26. Quarkus meets Neo4j by @rotnroll666
    •@Record(RUNTIME_INIT)

    • Will run from the applications main method during native boot
    21

    View Slide

  27. Quarkus meets Neo4j by @rotnroll666
    •@Record(RUNTIME_INIT)

    • Will run from the applications main method during native boot
    21

    View Slide

  28. Quarkus meets Neo4j by @rotnroll666
    •BUILD_TIME

    •BUILD_AND_RUN_TIME_FIXED

    •RUN_TIME
    22
    The Quarkus extension system
    Phases of configuration

    View Slide

  29. Quarkus meets Neo4j by @rotnroll666 23
    Demo
    @Path("/artists")

    public class ArtistsResource {

    private final Driver driver;

    @Inject

    public ArtistsResource(Driver driver) {

    this.driver = driver;

    }

    private Multi executeArtistQuery(RxSession session) {

    return Multi.createFrom().publisher(

    session.readTransaction(tx #& tx.run("MATCH (n:Artist) RETURN n.name AS name").records())

    );

    }

    @GET

    @Produces(MediaType.APPLICATION_JSON)

    public Multi getArtists() {

    return Uni.createFrom().item(driver#'rxSession)

    .toMulti()

    .flatMap(this#'executeArtistQuery)

    .map(record #& record.get("name").asString());

    }

    }

    View Slide

  30. The search for the holy Graal(VM):
    AoT compiling a database driver.

    View Slide

  31. Quarkus meets Neo4j by @rotnroll666 25

    View Slide

  32. Quarkus meets Neo4j by @rotnroll666
    • Neo4j: https://neo4j.com
    • Neo4j Quarkus Guide: https://quarkus.io/guides/neo4j
    • Neo4j Java Driver Manual:
    https://neo4j.com/docs/driver-manual/current/
    • The demo project:
    https://github.com/michael-simons/neo4j-sdn-ogm-tips/tree/master/
    examples/simple-quarkus
    • Neo4j Migrations: https://github.com/michael-simons/neo4j-migrations
    • Cypher-DSL: https://github.com/neo4j-contrib/cypher-dsl
    26
    Resources

    View Slide