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

Spring up Your Graph

Michael Simons
September 03, 2020

Spring up Your Graph

Spring Data Neo4j is the de facto standard when it comes to accessing Neo4j in the Spring ecosystem. With Spring Data Neo4j 6, we present the next generation.

Rewritten from the ground up and with first-class support for the reactive programming model and immutable objects, Spring Data Neo4j 6 as the successor of Spring Data Neo4j brings also new features and support for Neo4j 4 with it.

Being a little bit opinionated helped us a lot to provide an easier and more understandable API. What’s in there? How does it differ from the classic Spring Data Neo4j 5 and prior?

The answers to these questions and others will be given in this talk, together with a dive into an example application.

Michael Simons

September 03, 2020
Tweet

More Decks by Michael Simons

Other Decks in Programming

Transcript

  1. Spice up Your Graph
    Gerrit Meier and Michael Simons
    introducing the all new Spring Data Neo4j (SDN 6)
    SpringOne 2020
    Spring

    View Slide

  2. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 2

    View Slide

  3. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 4
    Label
    Type

    View Slide

  4. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 5
    Person
    KNOWS
    {
    name: "Mr. X"

    dob: 26.02.1982
    }
    {
    met: "Spring One"

    contact: 03.09.2020
    }

    View Slide

  5. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 6
    Person
    KNOWS
    Person
    Topic
    INTERESTED_IN INTERESTED_IN
    {
    term: "Spring Data"

    description: " … "
    }
    Graph Databases

    View Slide

  6. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 7
    Spring Data Neo4j Team
    @meistermeier @rotnroll666

    View Slide

  7. What would you do if you could create
    yet another object mapper from
    scratch?

    View Slide

  8. What would you do if you could create
    yet another object mapper from
    scratch?
    Why

    View Slide

  9. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 9
    Current Spring Data Neoj4 + Neo4j-OGM
    • start.spring.io gives you SDN and Neo4j-OGM
    • 3 different modes available (Embedded, HTTP and native)
    • Makes usage of Cypher harder than necessary
    • Custom queries are possible but go all through the Neo4j-OGM
    abstraction
    • Some building parts stack vertically, some horizontally
    ➡ Confusing options for beginners

    View Slide

  10. Spring Data Neo4j 6

    View Slide

  11. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 11
    What do we want?
    • A composable stack
    • Nicely integrated in Spring Boot
    • Access at all abstraction levels
    • Raw queries (outside application level transactions)
    • Raw queries (inside application level transactions)
    • Plus ad-hoc mapping
    • Mapping
    • Repository abstraction
    • Reactive (and imperative) database access

    View Slide

  12. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    • Java Driver
    • Direct usage
    • Simple Client
    • RowMapper-like
    • Neo4jTemplate
    • Entity-Metadata aware
    • Repositories
    • DDD way of accessing your data
    Multiple, ordered
    levels of
    Abstraction

    View Slide

  13. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 13
    Spring Data Repositories
    Neo4j Template
    Neo4j Client
    Neo4j Java Driver
    spring-boot-starter-data-neo4j
    spring-boot-autoconfigure
    SDN 6
    provides
    configures
    A composable stack

    View Slide

  14. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    • Imperative and reactive on par
    • New: Reactive transactions
    Reactive support

    View Slide

  15. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    • Bolt protocol
    • Driver type system
    100%-based on
    Neo4j Java Driver

    View Slide

  16. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 18
    @Autowired org.neo4j.driver.Driver
    @RestController
    public class MoviesController {
    private final Driver driver;
    public MoviesController(Driver driver) {
    this.driver = driver;
    }
    @GetMapping(path = "/movies", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux getMovieTitles() {
    /# Using an implicit, driver managed transaction
    return Flux.usingWhen(
    Mono.fromSupplier(driver:%rxSession),
    s -' Flux.from(s.run("MATCH (m:Movie) RETURN m ORDER BY m.name ASC").records()),
    RxSession:%close
    ).map(r -' r.get("m").asNode().get("title").asString());
    }
    }
    Based on open standards: Reactive Streams. Can be used with RxJava2, too.

    View Slide

  17. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    @Service
    public class MovieService {
    private final ReactiveNeo4jClient client;
    public MovieService(ReactiveNeo4jClient client) {
    this.client = client;
    }
    /# Fully integrated with Springs declarative
    /# or explicit transactions (via TransactionalOperator or TransactionTemplate)
    @Transactional
    public Flux getMovieTitles() {
    return client.query("MATCH (m:Movie) RETURN m ORDER BY m.name ASC")
    .fetchAs(String.class)
    .mappedBy((typeSystem, record) -' record.get("m").asNode().get("title").asString())
    .all();
    }
    }
    19
    @Autowired
    org.springframework.data.neo4j.core.ReactiveNeo4jClient

    View Slide

  18. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 20
    @Autowired
    org.springframework.data.neo4j.core.ReactiveNeo4jTemplate
    @Service
    public class MovieService {
    private final ReactiveNeo4jTemplate template;
    public MovieService(ReactiveNeo4jTemplate template) {
    this.template = template;
    }
    @Transactional
    public Flux getMovieTitles() {
    /# Overload with custom query available
    return template.findAll(MovieEntity.class)
    .map(MovieEntity:%getTitle);
    }
    }
    @Node("Movie")
    class MovieEntity {
    private @Id final String title;
    private @Property("tagline") final String description;
    @Relationship(type = "ACTED_IN", direction = INCOMING)
    private final Map actorsAndRoles;
    /# Full immutable class, works also with @Data,
    /# Kotlin and JDK 14 records
    public MovieEntity(String title, String description,
    Map actorsAndRoles
    ) {
    this.title = title;
    this.description = description;
    this.actorsAndRoles = actorsAndRoles;
    }
    }

    View Slide

  19. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    public interface MovieRepository extends ReactiveNeo4jRepository {}
    @Service
    public class MovieService {
    private final MovieRepository repository;
    public MovieService(MovieRepository repository) {
    this.repository = repository;
    }
    @Transactional
    public Flux getMovieTitles() {
    /# Custom query via @Query on a method
    /# For simple cases, use derived query methods
    /# repository.findAllByOrderByTitle
    return repository.findAll()
    .map(MovieEntity:%getTitle);
    /# For the first time with Spring Data and Neo4j, query by Example
    /# return repository.findAll(Example.of(new MovieEntity("The Matrix", null)));
    }
    }
    21
    @Autowired org.springframework.data.neo4j.core.ReactiveNeo4jRepository

    View Slide

  20. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    • Instances via
    • (persistent) constructor
    • wither
    • setter
    • No reflection violating the
    contract
    Immutable Mapping

    View Slide

  21. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    • Neo4j Driver Java auto-config
    • Properties where they belong
    • Updated SDN starter
    • Getting you up to speed in a
    blink
    • Health Checks
    • Based on the Java Driver
    Spring Boot
    integration

    View Slide

  22. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    @ConfigurationProperties(prefix = "spring.neo4j")
    public class Neo4jProperties {
    public static class Authentication {
    /** The login of the user connecting to the database.**
    private String username;
    /** The password of the user connecting to the database. **
    private String password;
    /** The realm to connect to.**
    private String realm;
    }
    /** The uri this driver should connect to. The driver supports bolt or neo4j as schemes.**
    private URI uri;
    /** The authentication the driver is supposed to use. Maybe null. **
    private Authentication authentication = new Authentication();
    }
    24
    Access to all configuration settings
    Consistent across frameworks!

    View Slide

  23. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    Less Surprises

    View Slide

  24. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666
    Cypher DSL
    • Zero dependency library
    • Compile-time checked query
    construction
    • Re-usable instances

    View Slide

  25. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 27
    var tom = node("Person").named("tom").properties("name", literalOf("Tom Hanks"));
    var coActors = anyNode("coActors");
    var cocoActors = anyNode("cocoActors");
    var strength = count(asterisk()).as("Strength");
    var statement = Cypher
    .match(
    tom.relationshipTo(anyNode("m"), "ACTED_IN").relationshipFrom(coActors, "ACTED_IN"),
    coActors.relationshipTo(anyNode("m2"), "ACTED_IN").relationshipFrom(cocoActors, "ACTED_IN")
    )
    .where(not(tom.relationshipTo(anyNode(), "ACTED_IN").relationshipFrom(cocoActors, "ACTED_IN")))
    .and(tom.isNotEqualTo(cocoActors))
    .returning(
    cocoActors.property("name").as("Recommended"),
    strength
    ).orderBy(strength.asName().descending())
    .build();
    assertThat(cypherRenderer.render(statement))
    .isEqualTo(""
    + "MATCH "
    + "(tom:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]-$(m)%-[:`ACTED_IN`]-(coActors), "
    + "(coActors)-[:`ACTED_IN`]-$(m2)%-[:`ACTED_IN`]-(cocoActors) "
    + "WHERE (NOT (tom)-[:`ACTED_IN`]-$()%-[:`ACTED_IN`]-(cocoActors) AND tom <( cocoActors) "
    + "RETURN cocoActors.name AS Recommended, count(*) AS Strength ORDER BY Strength DESC");

    View Slide

  26. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 28
    Current status
    • Works with Neo4j 3.4+
    • Reactive database access needs 4.0
    • Multi-database feature needs Neo4j Enterprise Edition
    • Works with Neo4j Aura https://neo4j.com/aura/
    • Provides Neo4j support in JHipster https://www.jhipster.tech

    View Slide

  27. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 29
    Current status
    • Original version released as SDN/RX in April 2020
    • Used already by customers
    • Will replace SDN+Neo4j-OGM in Spring Boot 2.4 / Spring Data Release Train
    Ockham (2020.0.0)
    • SDN+Neo4j-OGM in Spring Boot 2.3 and before still supported and
    maintained
    • Good choice for new projects
    • More effort to migrate existing SDN+Neo4j-OGM code
    • Different packages
    • More opinionated behavior

    View Slide

  28. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666 30
    Links
    • Announcement of SDN 6.0
    https://bit.ly/welcome_sdn6
    • Spring Data Neo4j
    https://spring.io/projects/spring-data-neo4j
    • Neo4j Cypher-DSL
    https://github.com/neo4j-contrib/cypher-dsl
    • Neo4j Downloads
    https://neo4j.org/downloads
    • Neo4j Aura
    https://neo4j.org/aura
    • Neo4j Community Site
    https://community.neo4j.com/

    View Slide

  29. Thank you!

    View Slide