-
-
Save michael-simons/d3137f64ac0b13713fae8e7e1a69367e to your computer and use it in GitHub Desktop.
package ac.simons.neo4j.examples; | |
import java.io.IOException; | |
import java.nio.file.Files; | |
import java.util.List; | |
import java.util.Map; | |
import org.neo4j.configuration.connectors.BoltConnector; | |
import org.neo4j.configuration.helpers.SocketAddress; | |
import org.neo4j.dbms.api.DatabaseManagementServiceBuilder; | |
import org.neo4j.driver.AuthTokens; | |
import org.neo4j.driver.GraphDatabase; | |
import org.neo4j.driver.TransactionContext; | |
public class GraphApplication { | |
public static void main(String... a) throws IOException { | |
// This is the db itself, should be long-lived | |
var graphDb = new DatabaseManagementServiceBuilder(Files.createTempDirectory("neo4j")) | |
.setConfig(BoltConnector.enabled, true) | |
.setConfig(BoltConnector.listen_address, new SocketAddress("localhost", 7687)) | |
.build(); | |
// You could also use the graph database api and skip using bolt. | |
// The advantage of using build also in an embedded scenario: You can switch to a server with ease. | |
// Same goes for the driver with the connection pool | |
// The session itself is short-lived | |
try ( | |
var driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.none()); | |
var session = driver.session() | |
) { | |
session.executeWrite(t -> t.run("CREATE (p:Person {name: 'Arnold Schwarzenegger'}) - [:ACTED_IN] -> (:Movie {title: 'The Terminator'})").consume().counters().nodesCreated()); | |
var movies = session.executeRead(GraphApplication::findMovieAndTheirActors); | |
movies.forEach(System.out::println); | |
} | |
graphDb.shutdown(); | |
} | |
record Person(String name) { | |
} | |
record Movie(String title, List<Person>actedIn) { | |
} | |
static List<Movie> findMovieAndTheirActors(TransactionContext tx) { | |
var query = """ | |
MATCH (m:Movie) <- [:ACTED_IN] - (p:Person) | |
WHERE m.title =~ $movieTitle | |
RETURN m.title AS title, collect(p.name) AS actors | |
"""; | |
return tx.run(query, Map.of("movieTitle", ".*The.*")).list(r -> { | |
var actors = r.get("actors").asList(v -> new Person(v.asString())); | |
return new Movie(r.get("title").asString(), actors); | |
}); | |
} | |
} |
<?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> | |
<groupId>ac.simons.neo4j</groupId> | |
<artifactId>neo4jtwitch</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<properties> | |
<maven.compiler.release>21</maven.compiler.release> | |
<neo4j.version>5.15.0</neo4j.version> | |
<neo4j-java-driver.version>5.15.0</neo4j-java-driver.version> | |
</properties> | |
<dependencies> | |
<!-- Embbeded instance --> | |
<dependency> | |
<groupId>org.neo4j</groupId> | |
<artifactId>neo4j</artifactId> | |
<version>${neo4j.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.neo4j</groupId> | |
<artifactId>neo4j-bolt</artifactId> | |
<version>${neo4j.version}</version> | |
</dependency> | |
<!-- Driver (for connection) --> | |
<dependency> | |
<groupId>org.neo4j.driver</groupId> | |
<artifactId>neo4j-java-driver</artifactId> | |
<version>${neo4j-java-driver.version}</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<version>3.11.0</version> | |
</plugin> | |
<plugin> | |
<groupId>org.codehaus.mojo</groupId> | |
<artifactId>appassembler-maven-plugin</artifactId> | |
<version>2.1.0</version> | |
<configuration> | |
<assembleDirectory>${project.build.directory}/assembly</assembleDirectory> | |
<repositoryLayout>flat</repositoryLayout> | |
<repositoryName>lib</repositoryName> | |
<programs> | |
<program> | |
<mainClass>ac.simons.neo4j.examples.GraphApplication</mainClass> | |
<id>app</id> | |
</program> | |
</programs> | |
</configuration> | |
<executions> | |
<execution> | |
<id>make-distribution</id> | |
<goals> | |
<goal>assemble</goal> | |
</goals> | |
<phase>package</phase> | |
</execution> | |
</executions> | |
</plugin> | |
</plugins> | |
</build> | |
</project> |
Neo4j Browser is not part of the embedded distribution.
Neo4j embedded inside Spring Boot is not likely to work with recent versions of Neo4j.
To use Neo4j from Spring Boot, use the bolt connector and an externally running Neo4j.
Database of this app cannot be accessed with Neo4j Browser hosted at https://browser.neo4j.io/ either?
I know if db file structure will be created not in TempDirectory as it is but in /target/
directory, it will stay populated after app shutdown and you can run neo4j docker instance which will use this directory, making it possible to observe this data with neo4j browser.
Neo4j embedded inside Spring Boot is not likely to work with recent versions of Neo4j.
It works for me with latest neo4j and Spring Boot as long as HttpConnector is disabled. At least now I know it shouldn't have worked at all, thank you. I wonder how I should've known that Neo4j Embedded isn't compatible with Spring Boot. These compatibility issues between Spring Boot and Neo4j Embedded will be addressed or Neo4j team isn't interested on this matter?
A couple of suggestions:
- I think there is a typo. "The advantage of using build" should probably be "The advantage of using bolt".
- You should probably schedule deletion of the temp directory via
graphDb.deleteOnExit()
.
It helped me, thank you.
Adding
.setConfig(HttpConnector.enabled, true)
and adding this method and calling it instead ofgraphDb.shutdown();
allows you to access Http endpoint:
or with powershell:
which results in this output:
But why visiting locahost:7474 in browser redirects to
/browser
and shows a blank page? Can this running db be accessed with neo4j browser? And how to expose Http endpoint from Spring[Boot] webapp? It crashes withjavax.servlet not found
if HttpConnector is enabled.