Our previous article demonstrated how easy it was to build an application using Spring Data Neo4j 4.
The first milestone of Spring Data Neo4j 4.1 has just been released (based on Neo4j OGM 2.0), and it delivers significant performance improvements for write operations, the ability to map nodes and relationships returned in custom Cypher queries to domain entities, as well as the much awaited support for embedded Neo4j.
The new Components framework in Neo4j OGM 2.0 allows you to configure your application by specifying which driver you want to use to connect to Neo4j. Currently supported are the Http and Embedded drivers. A Bolt driver will be available in the near future when Neo4j 3.0 is released. The great news is that swapping drivers in your application is trivial!
Upgrading Flavorwocky to use Spring Data Neo4j 4.1 requires us to use one of these Drivers instead of the RemoteServer
provided in SDN 4.0. We’re still using a remote Neo4j server so the Http Driver is appropriate.
The source code discussed in this article is available on Github.
Dependencies
First, let us update the versions of Spring Data Neo4j and Spring Data Commons –
<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-neo4j</artifactId><version>4.1.0.M1</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-commons</artifactId><version>1.12.0.M1</version></dependency>
Include the milestone repository too –
<repository><id>spring-milestones</id><url>http://repo.spring.io/milestone</url></repository>
Configuring the HTTP Driver
There are two ways to configure our application. The easiest way is to have the OGM auto-configure itself by providing a properties file called ogm.properties
in the classpath. This file contains the driver to use and the URI of the Neo4j database. An example of this is
driver=org.neo4j.ogm.drivers.http.driver.HttpDriver URI=http://user:password@localhost:7474
We’re not going to use this because Flavorwocky is deployed on Heroku and uses the GrapheneDB add-on. Our Neo4j connection URI is conveniently available in an environment variable called GRAPHENEDB_URL
which looks like http://<neo4j-server-username>:<neo4j-server-password@<neo4j-host>:<neo4j-port>
Hence, we will configure the driver programmatically and not embed our credentials in the properties file.
Recall that Application.java must extend Neo4jConfiguration. We do not need neo4jServer()
any more and instead create a Configuration bean. The Configuration
is supplied with the driver class name, which in our case is org.neo4j.ogm.drivers.http.driver.HttpDriver
, as well as the URI of the remote Neo4j server. This is provided by the GRAPHENEDB_URL
environment variable as discussed earlier.
importorg.neo4j.ogm.session.Sessionimportorg.neo4j.ogm.session.SessionFactoryimportorg.springframework.boot.SpringApplicationimportorg.springframework.boot.autoconfigure.EnableAutoConfigurationimportorg.springframework.context.annotation.Beanimportorg.springframework.context.annotation.ComponentScanimportorg.springframework.context.annotation.Configurationimportorg.springframework.context.annotation.Scopeimportorg.springframework.context.annotation.ScopedProxyModeimportorg.springframework.data.neo4j.config.Neo4jConfigurationimportorg.springframework.data.neo4j.repository.config.EnableNeo4jRepositoriesimportorg.springframework.transaction.annotation.EnableTransactionManagement@Configuration@ComponentScan("com.flavorwocky")@EnableAutoConfiguration@EnableTransactionManagement@EnableNeo4jRepositories("com.flavorwocky.repository")publicclassApplicationextendsNeo4jConfiguration{finalStringgrapheneUrlpublicApplication(){grapheneUrl=System.getenv("GRAPHENEDB_URL"}publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args}@Beanpublicorg.neo4j.ogm.config.ConfigurationgetConfiguration(){org.neo4j.ogm.config.Configurationconfig=neworg.neo4j.ogm.config.Configurationconfig.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver").setURI(grapheneUrlreturnconfig}@Override@BeanpublicSessionFactorygetSessionFactory(){returnnewSessionFactory(getConfiguration(),"com.flavorwocky.domain"}@Override@Bean@Scope(value="session",proxyMode=ScopedProxyMode.TARGET_CLASS)publicSessiongetSession()throwsException{returnsuper.getSession}}
The Configuration
we set up is now passed as the first argument to the SessionFactory
constructor.
That’s it, we’ve successfully configured the application to use Spring Data Neo4j 4.1.
Mapped entities in custom queries
Nodes and relationships returned by custom queries i.e. @Query
are now automatically mapped to domain entities. This is a huge benefit – earlier the only option was to return node and relationship entity IDs and load the entities by ID via a separate API call. Returning paths are not supported- instead, we return nodes and relationships in the path and this will map and wire up all our domain objects represented by those returned entities.
Recall that we defined this custom query to help us build a tree of flavour pairings as the input to the D3.js visualization-
@Query("match p=(i:Ingredient {name:{0}})-[r:PAIRS_WITH*0..3]-(i2)-[:HAS_CATEGORY]->(cat) return p;")Iterable<Map<String,Object>>getFlavorPaths(StringingredientName
This query represented each row as a List<Map<String, Object>>
@Query("match p=(ingredient:Ingredient {name:{0}})-[pairsWith:PAIRS_WITH*0..3]-(otherIngredient)-[r:HAS_CATEGORY]->(cat) return nodes(p) as nodes, rels(p) as rels")Iterable<Map<String,Object>>getFlavorPaths(StringingredientName
We still have every element in the path, only now they are represented as easy-to-work-with domain objects.
Testing
In SDN 4.1, the InProcessServer
we used in our tests earlier has been deprecated. Instead, we will use an impermanent embedded database.
The test dependencies required are
<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-neo4j</artifactId><version>4.1.0.RELEASE</version><type>test-jar</type></dependency><dependency><groupId>org.neo4j</groupId><artifactId>neo4j-kernel</artifactId><version>2.3.2</version><type>test-jar</type></dependency><dependency><groupId>org.neo4j.app</groupId><artifactId>neo4j-server</artifactId><version>2.3.2</version><type>test-jar</type></dependency><dependency><groupId>org.neo4j</groupId><artifactId>neo4j-ogm-test</artifactId><version>2.0.0-M02</version><scope>test</scope></dependency><dependency><groupId>org.neo4j.test</groupId><artifactId>neo4j-harness</artifactId><version>2.3.2</version><scope>test</scope></dependency>
We’ll have the OGM auto-configure itself to use the embedded driver for tests by including an ogm.properties
file in the test classpath.
driver=org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver
Note that we want to use the impermanent graph database so the URI is omitted from the properties. As with Application.java
, the neo4jServer()
method is not relevant any more and it’s been removed.
Conclusion
Pretty straightforward!
We strongly recommend that you upgrade from Spring Data Neo4j 4.0 to Spring Data Neo4j 4.1, or from Neo4j OGM 1.x to Neo4j OGM 2.0
The documentation for Spring Data Neo4j 4.1 is available at https://docs.spring.io/spring-data/neo4j/docs/4.1.0.M1/reference/html/
If you prefer to use Neo4j OGM directly, the reference guide is published to https://neo4j.com/docs/ogm/java/stable/
The source code for Flavorwocky is available on Github and instructions on how to run it locally are documented in the README.
If you need help, please post a question on StackOverflow and tag it with spring-data-neo4j-4