Spring Boot
Maven project setup
Create a Spring boot application to use the example provided below. To do this, define the necessary dependencies and the project layout in Maven or Gradle. This example focuses on the Maven-based solution.
Your pom.xml
file should match the following:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.neo4j.examples</groupId>
<artifactId>spring-boot-read-write-transactions</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Neo4j Spring Boot Example</name>
<description>Example showing how to use Spring Boot and do write and read transactions</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Code example
package org.neo4j.examples;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Record;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.SessionConfig;
import org.neo4j.driver.TransactionWork;
import org.neo4j.driver.exceptions.Neo4jException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
@SpringBootApplication
public class Example {
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
}
@Component
class ExampleCommandLineRunner implements CommandLineRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(ExampleCommandLineRunner.class.getName());
private final Driver driver;
private final ConfigurableApplicationContext applicationContext;
// Autowire the Driver bean by constructor injection
public ExampleCommandLineRunner(Driver driver, ConfigurableApplicationContext applicationContext) {
this.driver = driver;
this.applicationContext = applicationContext;
}
@Override
public void run(String... args) throws Exception {
try (Session session = driver.session(SessionConfig.forDatabase("neo4j"))) {
// Using transaction functions allows the driver to handle retries and transient errors for you
// The first examples indicates a write transaction that must go through the leader of a cluster
Record peopleCreated = session.writeTransaction(createRelationshipToPeople("Alice", "David"));
System.out.println("Create successful: " + peopleCreated.get("p1") + ", " + peopleCreated.get("p2"));
// The second examples indicates a read transaction, that can be answered by a follower
session
.readTransaction(readPersonByName("Alice"))
.forEach(System.out::println);
}
// Shutdown the application context to simulate application end.
// This closes all managed beans as well. The driver is one of those and its resources will be released.
applicationContext.close();
}
private static TransactionWork<Record> createRelationshipToPeople(String person1, String person2) {
return tx -> {
// To learn more about the Cypher syntax, see https://neo4j.com/docs/cypher-manual/current/
// The Reference Card is also a good resource for keywords https://neo4j.com/docs/cypher-refcard/current/
String createRelationshipToPeopleQuery = "MERGE (p1:Person { name: $person1_name }) \n" +
"MERGE (p2:Person { name: $person2_name })\n" +
"MERGE (p1)-[:KNOWS]->(p2)\n" +
"RETURN p1, p2";
Map<String, Object> params = new HashMap<>();
params.put("person1_name", person1);
params.put("person2_name", person2);
try {
Result result = tx.run(createRelationshipToPeopleQuery, params);
// You should not return the result itself outside of the scope of the transaction.
// The result will be closed when the transaction closes and it won't be usable afterwards.
// As we know that the query can only return one row, we can use the single method of the Result and
// return the record.
return result.single();
// You should capture any errors along with the query and data for traceability
} catch (Neo4jException ex) {
LOGGER.error(createRelationshipToPeopleQuery + " raised an exception", ex);
throw ex;
}
};
}
private static TransactionWork<List<String>> readPersonByName(String name) {
return tx -> {
String readPersonByNameQuery = "MATCH (p:Person)\n" +
" WHERE p.name = $person_name\n" +
" RETURN p.name AS name";
Map<String, Object> params = Collections.singletonMap("person_name", name);
try {
Result result = tx.run(readPersonByNameQuery, params);
return result.list(row -> row.get("name").asString());
} catch (Neo4jException ex) {
LOGGER.error(readPersonByNameQuery + " raised an exception", ex);
throw ex;
}
};
}
}
Running the example
Follow the steps below to run the example code:
-
Copy and paste the code above into a file named
Example.java
within a package/folder likeorg.neo4j.examples
in themain/java/src
folder. -
Enter the information for the AuraDB instance you want to connect to by adding the following to the
application.properties
file:spring.neo4j.uri=neo4j+s://<Bolt url for Neo4j Aura instance> spring.neo4j.authentication.username=<Username for Neo4j Aura instance> spring.neo4j.authentication.password=<Password for Neo4j Aura instance>
and replace:
-
<Bolt url for Neo4j Aura instance>
with the URI. -
<Username for Neo4j Aura instance>
with the username. -
<Password for Neo4j Aura instance>
with the password.
-
-
Use the following command to run the example code:
./mvnw spring-boot:run
Example walkthrough
This example creates an ExampleCommandLineRunner
, an implementation of Spring’s CommandLineRunner
.
This bean’s run method executes after the Spring context is successfully created.
There are two methods called from the implemented run method:
-
createRelationshipToPeople
creates two 'Person' nodes, Alice and David, and a 'KNOWS' relationship between them using a write transaction. -
readPersonByName
finds Alice using a read transaction.
Developing with Neo4j Aura requires the use of Transaction Functions. Transaction Functions enable automatic recovery from transient network errors and enable load balancing. |
Make sure to log queries and data sent from your application as it is useful when you encounter errors and can help with debugging.
Was this page helpful?