diff --git a/.gitignore b/.gitignore
index 7725bf202e..b731787052 100644
--- a/.gitignore
+++ b/.gitignore
@@ -120,4 +120,7 @@ libraries-2/src/test/resources/crawler4j/**
devDb*.db
#jaxb
-*.xjb
\ No newline at end of file
+*.xjb
+
+#neo4j
+persistence-modules/neo4j/data/**
\ No newline at end of file
diff --git a/persistence-modules/neo4j/README.md b/persistence-modules/neo4j/README.md
new file mode 100644
index 0000000000..354d9605db
--- /dev/null
+++ b/persistence-modules/neo4j/README.md
@@ -0,0 +1,15 @@
+## Spring Data Neo4j
+
+### Relevant Articles:
+- [A Guide to Neo4J with Java](https://www.baeldung.com/java-neo4j)
+
+### Build the Project with Tests Running
+```
+mvn clean install
+```
+
+### Run Tests Directly
+```
+mvn test
+```
+
diff --git a/persistence-modules/neo4j/pom.xml b/persistence-modules/neo4j/pom.xml
new file mode 100644
index 0000000000..91a488637a
--- /dev/null
+++ b/persistence-modules/neo4j/pom.xml
@@ -0,0 +1,117 @@
+
+
+ 4.0.0
+ neo4j
+ 1.0
+ neo4j
+
+
+ com.baeldung
+ persistence-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.neo4j
+ neo4j
+ ${neo4j.version}
+
+
+ org.neo4j
+ neo4j-ogm-core
+ ${neo4j-ogm-core.version}
+
+
+ org.neo4j
+ neo4j-ogm-embedded-driver
+ ${neo4j-ogm-embedded.version}
+
+
+ org.neo4j
+ neo4j-ogm-bolt-driver
+ ${neo4j-ogm-bolt-driver.version}
+
+
+ org.neo4j.driver
+ neo4j-java-driver
+ ${neo4j-java-driver.version}
+
+
+ org.neo4j
+ neo4j-jdbc-driver
+ ${neo4j-jdbc.version}
+ runtime
+
+
+ com.voodoodyne.jackson.jsog
+ jackson-jsog
+ ${jackson-jsog.version}
+ compile
+
+
+ org.neo4j
+ neo4j-kernel
+ ${neo4j.version}
+ test-jar
+
+
+ org.neo4j.app
+ neo4j-server
+ ${neo4j.version}
+ test-jar
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.neo4j
+ neo4j-ogm-test
+ ${neo4j-ogm.version}
+ test
+
+
+ org.neo4j.test
+ neo4j-harness
+ ${neo4j.version}
+ test
+
+
+ org.testcontainers
+ neo4j
+ ${testcontainers.version}
+ test
+
+
+ org.jetbrains
+ annotations
+
+
+ org.apache.commons
+ commons-compress
+
+
+ javax.xml.bind
+ jaxb-api
+
+
+
+
+
+
+ 5.6.0
+ 5.8.0
+ 1.1.2
+ 3.1.22
+ 4.0.5
+ 3.2.39
+ 4.0.9
+ 4.0.5
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Car.java b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Car.java
new file mode 100644
index 0000000000..d396cc94e7
--- /dev/null
+++ b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Car.java
@@ -0,0 +1,50 @@
+package com.baeldung.neo4j.domain;
+
+import static org.neo4j.ogm.annotation.Relationship.Direction.INCOMING;
+
+import org.neo4j.ogm.annotation.GeneratedValue;
+import org.neo4j.ogm.annotation.Id;
+import org.neo4j.ogm.annotation.NodeEntity;
+import org.neo4j.ogm.annotation.Relationship;
+
+@NodeEntity
+public class Car {
+ @Id @GeneratedValue
+ private Long id;
+
+ private String make;
+
+ @Relationship(direction = INCOMING)
+ private Company company;
+
+ public Car(String make, String model) {
+ this.make = make;
+ this.model = model;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getMake() {
+ return make;
+ }
+
+ public void setMake(String make) {
+ this.make = make;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ private String model;
+}
diff --git a/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Company.java b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Company.java
new file mode 100644
index 0000000000..7749db9d74
--- /dev/null
+++ b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Company.java
@@ -0,0 +1,42 @@
+package com.baeldung.neo4j.domain;
+
+import org.neo4j.ogm.annotation.NodeEntity;
+import org.neo4j.ogm.annotation.Relationship;
+
+@NodeEntity
+public class Company {
+ private Long id;
+
+ private String name;
+
+ @Relationship(type="owns")
+ private Car car;
+
+ public Company(String name) {
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Car getCar() {
+ return car;
+ }
+
+ public void setCar(Car car) {
+ this.car = car;
+ }
+}
diff --git a/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Movie.java b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Movie.java
new file mode 100644
index 0000000000..c6a0a9a529
--- /dev/null
+++ b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Movie.java
@@ -0,0 +1,66 @@
+package com.baeldung.neo4j.domain;
+
+import static org.neo4j.ogm.annotation.Relationship.Direction.INCOMING;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
+
+import org.neo4j.ogm.annotation.GeneratedValue;
+import org.neo4j.ogm.annotation.Id;
+import org.neo4j.ogm.annotation.NodeEntity;
+import org.neo4j.ogm.annotation.Relationship;
+
+import java.util.Collection;
+import java.util.List;
+
+@JsonIdentityInfo(generator = JSOGGenerator.class)
+
+@NodeEntity
+public class Movie {
+ @Id @GeneratedValue
+ Long id;
+
+ private String title;
+
+ private int released;
+ private String tagline;
+
+ @Relationship(type = "ACTED_IN", direction = INCOMING)
+ private List roles;
+
+ public Movie() {
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public int getReleased() {
+ return released;
+ }
+
+ public String getTagline() {
+ return tagline;
+ }
+
+ public Collection getRoles() {
+ return roles;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setReleased(int released) {
+ this.released = released;
+ }
+
+ public void setTagline(String tagline) {
+ this.tagline = tagline;
+ }
+
+ public void setRoles(List roles) {
+ this.roles = roles;
+ }
+
+}
diff --git a/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Person.java b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Person.java
new file mode 100644
index 0000000000..a9491ee876
--- /dev/null
+++ b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Person.java
@@ -0,0 +1,52 @@
+package com.baeldung.neo4j.domain;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
+
+import org.neo4j.ogm.annotation.GeneratedValue;
+import org.neo4j.ogm.annotation.Id;
+import org.neo4j.ogm.annotation.NodeEntity;
+import org.neo4j.ogm.annotation.Relationship;
+
+import java.util.List;
+
+@JsonIdentityInfo(generator = JSOGGenerator.class)
+@NodeEntity
+public class Person {
+ @Id @GeneratedValue
+ Long id;
+
+ private String name;
+ private int born;
+
+ @Relationship(type = "ACTED_IN")
+ private List movies;
+
+ public Person() {
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getBorn() {
+ return born;
+ }
+
+ public List getMovies() {
+ return movies;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setBorn(int born) {
+ this.born = born;
+ }
+
+ public void setMovies(List movies) {
+ this.movies = movies;
+ }
+
+}
diff --git a/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Role.java b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Role.java
new file mode 100644
index 0000000000..0c91e67f0c
--- /dev/null
+++ b/persistence-modules/neo4j/src/main/java/com/baeldung/neo4j/domain/Role.java
@@ -0,0 +1,50 @@
+package com.baeldung.neo4j.domain;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
+import org.neo4j.ogm.annotation.EndNode;
+import org.neo4j.ogm.annotation.GeneratedValue;
+import org.neo4j.ogm.annotation.Id;
+import org.neo4j.ogm.annotation.RelationshipEntity;
+import org.neo4j.ogm.annotation.StartNode;
+
+import java.util.Collection;
+
+@JsonIdentityInfo(generator = JSOGGenerator.class)
+@RelationshipEntity(type = "ACTED_IN")
+public class Role {
+ @Id @GeneratedValue
+ Long id;
+ private Collection roles;
+ @StartNode
+ private Person person;
+ @EndNode
+ private Movie movie;
+
+ public Role() {
+ }
+
+ public Collection getRoles() {
+ return roles;
+ }
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public Movie getMovie() {
+ return movie;
+ }
+
+ public void setRoles(Collection roles) {
+ this.roles = roles;
+ }
+
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+
+ public void setMovie(Movie movie) {
+ this.movie = movie;
+ }
+}
diff --git a/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerLiveTest.java b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerLiveTest.java
new file mode 100644
index 0000000000..2232c68e8e
--- /dev/null
+++ b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerLiveTest.java
@@ -0,0 +1,79 @@
+package com.baeldung.neo4j;
+
+import static com.baeldung.neo4j.TestContainersTestBase.DEFAULT_PASSWORD;
+import static com.baeldung.neo4j.TestContainersTestBase.getNewBoltConnection;
+import static com.baeldung.neo4j.TestContainersTestBase.neo4jServer;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.neo4j.driver.Driver;
+import org.neo4j.driver.Result;
+import org.neo4j.driver.Session;
+
+
+/**
+ * To run this test you will need to have an instance of the docker running on your machine (Docker desktop - for Windows and Docker instance for linux)
+ * After your docker instance is up run this test
+ */
+class Neo4JServerLiveTest {
+
+ private static Session session;
+ private static Driver driver;
+
+ @BeforeAll
+ public static void setup() {
+ driver = getNewBoltConnection();
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ driver.close();
+ }
+
+ @Test
+ void standAloneDriver() {
+ session = driver.session();
+ session.run("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
+ "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
+ "RETURN baeldung, tesla");
+
+ Result result = session.run("MATCH (company:Company)-[:owns]-> (car:Car)" +
+ "WHERE car.make='tesla' and car.model='modelX'" +
+ "RETURN company.name");
+
+ assertTrue(result.hasNext());
+ assertEquals("Baeldung", result.next().get("company.name").asString());
+
+ session.close();
+ }
+
+ @Test
+ void standAloneJdbc() throws Exception {
+ String uri = "jdbc:neo4j:" + neo4jServer.getBoltUrl() + "/?user=neo4j,password=" + DEFAULT_PASSWORD + ",scheme=basic";
+ Connection con = DriverManager.getConnection(uri);
+
+ // Querying
+ try (Statement stmt = con.createStatement()) {
+ stmt.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
+ "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
+ "RETURN baeldung, tesla");
+
+ ResultSet rs = stmt.executeQuery("MATCH (company:Company)-[:owns]-> (car:Car)" +
+ "WHERE car.make='tesla' and car.model='modelX'" +
+ "RETURN company.name");
+
+ while (rs.next()) {
+ assertEquals("Baeldung", rs.getString("company.name"));
+ }
+ }
+ con.close();
+ }
+}
diff --git a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java
similarity index 63%
rename from persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java
rename to persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java
index 1ff01b93a1..8591dd3a8d 100644
--- a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java
+++ b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java
@@ -1,7 +1,10 @@
package com.baeldung.neo4j;
+import static org.neo4j.configuration.GraphDatabaseSettings.DEFAULT_DATABASE_NAME;
+
import java.io.File;
+import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -10,101 +13,111 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.neo4j.configuration.GraphDatabaseSettings;
+import org.neo4j.dbms.api.DatabaseManagementService;
+import org.neo4j.dbms.api.DatabaseManagementServiceBuilder;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Result;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
+import org.neo4j.graphdb.Transaction;
+/**
+ * To run this test you will need to have an instance of the docker running on your machine (Docker desktop - for Windows and Docker instance for linux)
+ * After your docker instance is up run this test
+ */
public class Neo4jLiveTest {
private static GraphDatabaseService graphDb;
+ private static Transaction transaction;
+ private static DatabaseManagementService managementService;
@Before
public void setUp() {
- GraphDatabaseFactory graphDbFactory = new GraphDatabaseFactory();
- graphDb = graphDbFactory.newEmbeddedDatabase(new File("data/cars"));
+ managementService = new DatabaseManagementServiceBuilder(new File("data/cars").toPath())
+ .setConfig( GraphDatabaseSettings.transaction_timeout, Duration.ofSeconds( 60 ) )
+ .setConfig( GraphDatabaseSettings.preallocate_logical_logs, false ).build();
+ graphDb = managementService.database( DEFAULT_DATABASE_NAME );
}
@After
public void tearDown() {
- graphDb.shutdown();
+ managementService.shutdown();
}
@Test
public void testPersonCar() {
- graphDb.beginTx();
- Node car = graphDb.createNode(Label.label("Car"));
+ transaction = graphDb.beginTx();
+ Node car = transaction.createNode(Label.label("Car"));
car.setProperty("make", "tesla");
car.setProperty("model", "model3");
- Node owner = graphDb.createNode(Label.label("Person"));
+ Node owner = transaction.createNode(Label.label("Person"));
owner.setProperty("firstName", "baeldung");
owner.setProperty("lastName", "baeldung");
owner.createRelationshipTo(car, RelationshipType.withName("owner"));
- Result result = graphDb.execute("MATCH (c:Car) <-[owner]- (p:Person) " +
+ Result result = transaction.execute("MATCH (c:Car) <-[owner]- (p:Person) " +
"WHERE c.make = 'tesla'" +
"RETURN p.firstName, p.lastName");
Map firstResult = result.next();
+
Assert.assertEquals("baeldung", firstResult.get("p.firstName"));
}
@Test
public void testCreateNode() {
-
- graphDb.beginTx();
-
- Result result = graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"})" +
+ transaction = graphDb.beginTx();
+ Result result = transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"})" +
"RETURN baeldung");
Map firstResult = result.next();
Node firstNode = (Node) firstResult.get("baeldung");
+
Assert.assertEquals(firstNode.getProperty("name"), "Baeldung");
}
@Test
public void testCreateNodeAndLink() {
- graphDb.beginTx();
-
- Result result = graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
+ transaction = graphDb.beginTx();
+ Result result = transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
"-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
"RETURN baeldung, tesla");
Map firstResult = result.next();
+
Assert.assertTrue(firstResult.containsKey("baeldung"));
Assert.assertTrue(firstResult.containsKey("tesla"));
}
@Test
public void testFindAndReturn() {
- graphDb.beginTx();
-
- graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
+ transaction = graphDb.beginTx();
+ transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
"-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
"RETURN baeldung, tesla");
- Result result = graphDb.execute("MATCH (company:Company)-[:owns]-> (car:Car)" +
+ Result result = transaction.execute("MATCH (company:Company)-[:owns]-> (car:Car)" +
"WHERE car.make='tesla' and car.model='modelX'" +
"RETURN company.name");
Map firstResult = result.next();
+
Assert.assertEquals(firstResult.get("company.name"), "Baeldung");
}
@Test
public void testUpdate() {
- graphDb.beginTx();
-
- graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
+ transaction = graphDb.beginTx();
+ transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
"-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
"RETURN baeldung, tesla");
- Result result = graphDb.execute("MATCH (car:Car)" +
+ Result result = transaction.execute("MATCH (car:Car)" +
"WHERE car.make='tesla'" +
" SET car.milage=120" +
" SET car :Car:Electro" +
@@ -127,17 +140,16 @@ public class Neo4jLiveTest {
@Test
public void testDelete() {
- graphDb.beginTx();
-
- graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
+ transaction = graphDb.beginTx();
+ transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
"-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
"RETURN baeldung, tesla");
- graphDb.execute("MATCH (company:Company)" +
+ transaction.execute("MATCH (company:Company)" +
" WHERE company.name='Baeldung'" +
" DELETE company");
- Result result = graphDb.execute("MATCH (company:Company)" +
+ Result result = transaction.execute("MATCH (company:Company)" +
" WHERE company.name='Baeldung'" +
" RETURN company");
@@ -146,14 +158,13 @@ public class Neo4jLiveTest {
@Test
public void testBindings() {
- graphDb.beginTx();
-
+ transaction = graphDb.beginTx();
Map params = new HashMap<>();
params.put("name", "baeldung");
params.put("make", "tesla");
params.put("model", "modelS");
- Result result = graphDb.execute("CREATE (baeldung:Company {name:$name}) " +
+ Result result = transaction.execute("CREATE (baeldung:Company {name:$name}) " +
"-[:owns]-> (tesla:Car {make: $make, model: $model})" +
"RETURN baeldung, tesla", params);
diff --git a/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java
new file mode 100644
index 0000000000..aa9dd84ed6
--- /dev/null
+++ b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.neo4j;
+
+import static com.baeldung.neo4j.TestContainersTestBase.getDriver;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.neo4j.ogm.model.Result;
+import org.neo4j.ogm.session.Session;
+import org.neo4j.ogm.session.SessionFactory;
+
+import com.baeldung.neo4j.domain.Car;
+import com.baeldung.neo4j.domain.Company;
+
+/**
+ * To run this test you will need to have an instance of the docker running on your machine (Docker desktop - for Windows and Docker instance for linux)
+ * After your docker instance is up run this test
+ */
+public class Neo4jOgmLiveTest {
+
+ private static SessionFactory sessionFactory;
+ private static Session session;
+
+ @BeforeAll
+ public static void oneTimeSetUp() {
+ sessionFactory = new SessionFactory(getDriver(), "com.baeldung.neo4j.domain");
+ session = sessionFactory.openSession();
+ session.purgeDatabase();
+ }
+
+ @Test
+ void testOgm() {
+ Car tesla = new Car("tesla", "modelS");
+ Company baeldung = new Company("baeldung");
+
+ baeldung.setCar(tesla);
+
+ session.save(baeldung);
+
+ assertEquals(1, session.countEntitiesOfType(Company.class));
+
+ Map params = new HashMap<>();
+ params.put("make", "tesla");
+ Result result = session.query("MATCH (car:Car) <-[:owns]- (company:Company)" +
+ " WHERE car.make=$make" +
+ " RETURN company", params);
+
+ Map firstResult = result.iterator().next();
+
+ assertEquals(1, firstResult.size());
+
+ Company actual = (Company) firstResult.get("company");
+ assertEquals(actual.getName(), baeldung.getName());
+ }
+}
diff --git a/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/TestContainersTestBase.java b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/TestContainersTestBase.java
new file mode 100644
index 0000000000..eed2237454
--- /dev/null
+++ b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/TestContainersTestBase.java
@@ -0,0 +1,132 @@
+package com.baeldung.neo4j;
+
+import static org.neo4j.ogm.drivers.bolt.driver.BoltDriver.CONFIG_PARAMETER_BOLT_LOGGING;
+
+import java.util.Locale;
+import java.util.Optional;
+
+import org.neo4j.driver.AccessMode;
+import org.neo4j.driver.AuthTokens;
+import org.neo4j.driver.GraphDatabase;
+import org.neo4j.driver.Logging;
+import org.neo4j.driver.Session;
+import org.neo4j.driver.SessionConfig;
+import org.neo4j.ogm.config.Configuration;
+import org.neo4j.ogm.driver.Driver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.Neo4jContainer;
+import org.testcontainers.utility.TestcontainersConfiguration;
+
+/**
+ * Reference: https://github.com/neo4j/neo4j-ogm/blob/master/neo4j-ogm-tests/neo4j-ogm-integration-tests/src/test/java/org/neo4j/ogm/testutil/TestContainersTestBase.java
+ */
+public class TestContainersTestBase {
+
+ public static final Logger LOGGER = LoggerFactory.getLogger(TestContainersTestBase.class);
+
+ public static final Driver driver;
+
+ public static final String version;
+
+ public static final String DEFAULT_IMAGE = "neo4j:5";
+
+ public static final String SYS_PROPERTY_ACCEPT_AND_USE_COMMERCIAL_EDITION = "NEO4J_OGM_NEO4J_ACCEPT_AND_USE_COMMERCIAL_EDITION";
+
+ public static final String SYS_PROPERTY_IMAGE_NAME = "NEO4J_OGM_NEO4J_IMAGE_NAME";
+
+ public static final String SYS_PROPERTY_NEO4J_URL = "NEO4J_OGM_NEO4J_URL";
+
+ public static final String SYS_PROPERTY_NEO4J_PASSWORD = "NEO4J_OGM_NEO4J_PASSWORD";
+
+ public static final String DEFAULT_PASSWORD = "12345";
+
+ public static Neo4jContainer neo4jServer;
+
+ public static Configuration.Builder baseConfigurationBuilder;
+
+ public static final String NEO4J_URL = Optional.ofNullable(System.getenv(SYS_PROPERTY_NEO4J_URL)).orElse("");
+
+ public static final String NEO4J_PASSWORD = Optional.ofNullable(System.getenv(SYS_PROPERTY_NEO4J_PASSWORD)).orElse("").trim();
+
+ static {
+
+ boolean acceptAndUseCommercialEdition = hasAcceptedAndWantsToUseCommercialEdition();
+
+ if (!(NEO4J_URL.isEmpty() || NEO4J_PASSWORD.isEmpty())) {
+ LOGGER.info("Using Neo4j instance at {}.", NEO4J_URL);
+ driver = new org.neo4j.ogm.drivers.bolt.driver.BoltDriver();
+ baseConfigurationBuilder = new Configuration.Builder()
+ .uri(NEO4J_URL)
+ .verifyConnection(true)
+ .withCustomProperty(CONFIG_PARAMETER_BOLT_LOGGING, Logging.slf4j())
+ .credentials("neo4j", NEO4J_PASSWORD);
+ driver.configure(baseConfigurationBuilder.build());
+ version = extractVersionFromBolt();
+ } else {
+ LOGGER.info("Using Neo4j test container.");
+ String imageName = Optional.ofNullable(System.getenv(SYS_PROPERTY_IMAGE_NAME))
+ .orElse(DEFAULT_IMAGE + (acceptAndUseCommercialEdition ? "-enterprise" : ""));
+
+ version = extractVersionFromDockerImage(imageName);
+
+ boolean containerReuseSupported = TestcontainersConfiguration
+ .getInstance().environmentSupportsReuse();
+ neo4jServer = new Neo4jContainer<>(imageName)
+ .withReuse(containerReuseSupported);
+
+ if (acceptAndUseCommercialEdition) {
+ neo4jServer.withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes");
+ }
+ neo4jServer.withAdminPassword(DEFAULT_PASSWORD).start();
+
+ driver = new org.neo4j.ogm.drivers.bolt.driver.BoltDriver();
+
+ baseConfigurationBuilder = new Configuration.Builder()
+ .uri(neo4jServer.getBoltUrl())
+ .credentials("neo4j", DEFAULT_PASSWORD)
+ .verifyConnection(true)
+ .withCustomProperty(CONFIG_PARAMETER_BOLT_LOGGING, Logging.slf4j());
+
+ driver.configure(baseConfigurationBuilder.build());
+
+ Runtime.getRuntime().addShutdownHook(new Thread(neo4jServer::stop));
+ }
+ }
+
+ public static org.neo4j.driver.Driver getNewBoltConnection() {
+
+ if (neo4jServer != null) {
+ return GraphDatabase.driver(neo4jServer.getBoltUrl(), AuthTokens.basic("neo4j", DEFAULT_PASSWORD));
+ } else {
+ return GraphDatabase.driver(NEO4J_URL, AuthTokens.basic("neo4j", NEO4J_PASSWORD));
+ }
+ }
+
+ public static boolean hasAcceptedAndWantsToUseCommercialEdition() {
+ return Optional.ofNullable(
+ System.getenv(TestContainersTestBase.SYS_PROPERTY_ACCEPT_AND_USE_COMMERCIAL_EDITION))
+ .orElse("no").toLowerCase(Locale.ENGLISH).equals("yes");
+ }
+
+ public static Driver getDriver() {
+ return driver;
+ }
+
+ private static String extractVersionFromDockerImage(String imageName) {
+ return imageName.replace("neo4j:", "").replace("neo4j/neo4j-experimental:", "").replace("-enterprise", "");
+ }
+
+ private static String extractVersionFromBolt() {
+
+ org.neo4j.driver.Driver driver = getDriver().unwrap(org.neo4j.driver.Driver.class);
+
+ String version;
+ SessionConfig sessionConfig = SessionConfig.builder().withDefaultAccessMode(AccessMode.READ).build();
+ try (Session session = driver.session(sessionConfig)) {
+ version = (String) session.run("CALL dbms.components() YIELD versions").single().get("versions").asList().get(0);
+ }
+ return version.toLowerCase(Locale.ENGLISH);
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 9361e26d7d..39172d7f42 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -93,7 +93,6 @@
spring-data-mongodb-2
spring-data-mongodb-reactive
-
spring-data-redis
@@ -113,6 +112,7 @@
spring-data-rest
java-mongodb
questdb
+ neo4j
diff --git a/persistence-modules/spring-data-neo4j/pom.xml b/persistence-modules/spring-data-neo4j/pom.xml
index 8c5030779b..33f2966db3 100644
--- a/persistence-modules/spring-data-neo4j/pom.xml
+++ b/persistence-modules/spring-data-neo4j/pom.xml
@@ -14,26 +14,11 @@
-
- org.neo4j
- neo4j
- ${neo4j.version}
-
-
- org.neo4j
- neo4j-ogm-core
- ${neo4j-ogm.version}
-
org.neo4j
neo4j-ogm-embedded-driver
${neo4j-ogm.version}
-
- org.neo4j.driver
- neo4j-java-driver
- ${neo4j-java-driver.version}
-
org.springframework.data
spring-data-neo4j
@@ -51,24 +36,6 @@
${spring-boot.version}
test
-
- org.neo4j
- neo4j-kernel
- ${neo4j.version}
- test-jar
-
-
- org.neo4j.app
- neo4j-server
- ${neo4j.version}
- test-jar
-
-
- commons-logging
- commons-logging
-
-
-
org.neo4j
neo4j-ogm-test
@@ -89,7 +56,6 @@
- 1.6.2
3.4.6
5.0.1.RELEASE
1.1
diff --git a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerLiveTest.java b/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerLiveTest.java
deleted file mode 100644
index bf187ccb2d..0000000000
--- a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerLiveTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.baeldung.neo4j;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.Statement;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.neo4j.driver.v1.AuthTokens;
-import org.neo4j.driver.v1.Driver;
-import org.neo4j.driver.v1.GraphDatabase;
-import org.neo4j.driver.v1.Session;
-import org.neo4j.driver.v1.StatementResult;
-
-@Ignore
-public class Neo4JServerLiveTest {
-
- @Test
- public void standAloneDriver() {
- Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "12345"));
- Session session = driver.session();
-
- session.run("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
- "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
- "RETURN baeldung, tesla");
-
- StatementResult result = session.run("MATCH (company:Company)-[:owns]-> (car:Car)" +
- "WHERE car.make='tesla' and car.model='modelX'" +
- "RETURN company.name");
-
- Assert.assertTrue(result.hasNext());
- Assert.assertEquals(result.next().get("company.name").asString(), "Baeldung");
-
- session.close();
- driver.close();
- }
-
- @Test
- public void standAloneJdbc() throws Exception {
- Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://localhost/?user=neo4j,password=12345,scheme=basic");
-
- // Querying
- try (Statement stmt = con.createStatement()) {
- stmt.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
- "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
- "RETURN baeldung, tesla");
-
- ResultSet rs = stmt.executeQuery("MATCH (company:Company)-[:owns]-> (car:Car)" +
- "WHERE car.make='tesla' and car.model='modelX'" +
- "RETURN company.name");
-
- while (rs.next()) {
- Assert.assertEquals(rs.getString("company.name"), "Baeldung");
- }
- }
- con.close();
- }
-}
diff --git a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java b/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java
deleted file mode 100644
index 96e5e76402..0000000000
--- a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.baeldung.neo4j;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.neo4j.ogm.config.Configuration;
-import org.neo4j.ogm.model.Result;
-import org.neo4j.ogm.session.Session;
-import org.neo4j.ogm.session.SessionFactory;
-
-import com.baeldung.spring.data.neo4j.domain.Car;
-import com.baeldung.spring.data.neo4j.domain.Company;
-
-public class Neo4jOgmLiveTest {
-
- @Test
- public void testOgm() {
- Configuration conf = new Configuration.Builder().build();
-
- SessionFactory factory = new SessionFactory(conf, "com.baeldung.spring.data.neo4j.domain");
- Session session = factory.openSession();
-
- Car tesla = new Car("tesla", "modelS");
- Company baeldung = new Company("baeldung");
-
- baeldung.setCar(tesla);
-
- session.save(baeldung);
-
- Assert.assertEquals(1, session.countEntitiesOfType(Company.class));
-
- Map params = new HashMap<>();
- params.put("make", "tesla");
- Result result = session.query("MATCH (car:Car) <-[:owns]- (company:Company)" +
- " WHERE car.make=$make" +
- " RETURN company", params);
-
- Map firstResult = result.iterator().next();
-
- Assert.assertEquals(firstResult.size(), 1);
-
- Company actual = (Company) firstResult.get("company");
- Assert.assertEquals(actual.getName(), baeldung.getName());
- }
-}
diff --git a/pom.xml b/pom.xml
index e5311ec25f..b8bc85d634 100644
--- a/pom.xml
+++ b/pom.xml
@@ -369,6 +369,7 @@
persistence-modules/hibernate-ogm
persistence-modules/java-cassandra
persistence-modules/spring-data-cassandra-reactive
+ persistence-modules/spring-data-neo4j
@@ -545,6 +546,7 @@
persistence-modules/hibernate-ogm
persistence-modules/java-cassandra
persistence-modules/spring-data-cassandra-reactive
+ persistence-modules/spring-data-neo4j