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
  2. 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 }
  3. 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
  4. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666

    7 Spring Data Neo4j Team @meistermeier @rotnroll666
  5. What would you do if you could create yet another

    object mapper from scratch? Why
  6. 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
  7. 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
  8. 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
  9. 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
  10. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666

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

    • Bolt protocol • Driver type system 100%-based on Neo4j Java Driver
  12. 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<String> 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.
  13. 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<String> 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
  14. 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<String> 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<PersonEntity, Roles> actorsAndRoles; /# Full immutable class, works also with @Data, /# Kotlin and JDK 14 records public MovieEntity(String title, String description, Map<PersonEntity, Roles> actorsAndRoles ) { this.title = title; this.description = description; this.actorsAndRoles = actorsAndRoles; } }
  15. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666

    public interface MovieRepository extends ReactiveNeo4jRepository<MovieEntity, String> {} @Service public class MovieService { private final MovieRepository repository; public MovieService(MovieRepository repository) { this.repository = repository; } @Transactional public Flux<String> 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
  16. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666

    • Instances via • (persistent) constructor • wither • setter • No reflection violating the contract Immutable Mapping
  17. 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
  18. 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!
  19. Introducing SDN 6 at SpringOne 2020 by @meistermeier and @rotnroll666

    Cypher DSL • Zero dependency library • Compile-time checked query construction • Re-usable instances
  20. 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");
  21. 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
  22. 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
  23. 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/