Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Neo4j Driver Java Skill

ASecurity

Neo4j Java Driver v6 — driver lifecycle, Maven/Gradle setup, executableQuery,

114 stars
0 votes
0 copies
0 views
Added 10/6/2026
ai-agentsjavakotlinbashreactnodespringawsgcpazuredebugging

Works with

cursorcliapi

Security Analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned 10/6/2026

$npx -y skills add neo4j-contrib/neo4j-skills --skill neo4j-driver-java-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Neo4j Driver Java Skill?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Neo4j Driver Java Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/neo4j-contrib-neo4j-driver-java-skill/badge)](https://www.skillsdirectory.com/skills/neo4j-contrib-neo4j-driver-java-skill)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: neo4j-driver-java-skill
description: Neo4j Java Driver v6 — driver lifecycle, Maven/Gradle setup, executableQuery,
  executeRead/Write managed transactions, explicit transactions, async/reactive patterns,
  error handling, data type mapping, connection pool tuning, causal consistency/bookmarks.
  Use when writing Java or Kotlin code that connects to Neo4j via GraphDatabase.driver,
  executableQuery, SessionConfig, executeRead, executeWrite, or TransactionCallback.
  Does NOT handle Cypher authoring — use neo4j-cypher-skill.
  Does NOT cover driver version upgrades — use neo4j-migration-skill.
  Does NOT cover Spring Data Neo4j (@Node, Neo4jRepository) — use neo4j-spring-data-skill.
version: 1.0.12
allowed-tools: Bash WebFetch
---

## When to Use
- Java/Kotlin code connecting to Neo4j (Aura or self-managed)
- Setting up driver, sessions, transactions in Maven/Gradle projects
- Debugging result handling, error recovery, connection pool issues
- Async (`CompletableFuture`) or reactive (Project Reactor / RxJava) Neo4j access

## When NOT to Use
- **Cypher query authoring/optimization** → `neo4j-cypher-skill`
- **Driver version upgrades** → `neo4j-migration-skill`
- **Spring Data Neo4j** (`@Node`, `@Relationship`, `Neo4jRepository`) → `neo4j-spring-data-skill`

---

## Dependency

### Maven
```xml
<dependency>
    <groupId>org.neo4j.driver</groupId>
    <artifactId>neo4j-java-driver</artifactId>
    <version>6.3.0</version>
</dependency>
```

### Gradle
```groovy
implementation 'org.neo4j.driver:neo4j-java-driver:6.3.0'
```

Check latest: https://central.sonatype.com/artifact/org.neo4j.driver/neo4j-java-driver

6.2.0 [2026-06]: Neo4j `UUID` type + Bolt 6.1 support; `QueryProfile` in result summary.
6.2.1 [2026-08]: fixes `Value#asObject()` on `UUID` values — required if reading UUID properties generically. Neo4j 2026.08 server bundles 6.2.1; 2026.07 bundles 6.2.0.
6.3.0 [2026-09]: Property Encryption preview — client-side envelope encryption of property values (`driver.propertyEncryption()`) → [references/property-encryption.md](references/property-encryption.md).

Server-side `UUID` type and `uuid()` constructors ship in Neo4j 2026.08 — use driver >= 6.2.1 against those servers.

---

## Environment Variables

Standard pattern for connection config — never hardcode credentials:

```java
String uri      = System.getenv().getOrDefault("NEO4J_URI",      "neo4j://localhost:7687");
String user     = System.getenv().getOrDefault("NEO4J_USERNAME",  "neo4j");
String password = System.getenv().getOrDefault("NEO4J_PASSWORD",  "");
String database = System.getenv().getOrDefault("NEO4J_DATABASE",  "neo4j");
```

Spring Boot: inject via `@Value("${spring.neo4j.uri}")` or `application.properties`:
```properties
spring.neo4j.uri=neo4j+s://xxx.databases.neo4j.io
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
```

---

## Driver Lifecycle

One `Driver` per application — thread-safe, expensive to create. Implement `AutoCloseable` or use try-with-resources.

```java
// Long-lived singleton
var driver = GraphDatabase.driver(
    "neo4j+s://xxx.databases.neo4j.io",          // Aura TLS+routing
    AuthTokens.basic(user, password));
driver.verifyConnectivity();                      // fail fast

// Short-lived (tests / CLI)
try (var driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password))) {
    driver.verifyConnectivity();
    // ...
}
```

URI schemes:

| URI | Use |
|---|---|
| `neo4j://localhost` | Unencrypted, cluster routing |
| `neo4j+s://xxx.databases.neo4j.io` | TLS + cluster routing (Aura) |
| `bolt://localhost:7687` | Unencrypted, single instance |
| `bolt+s://localhost:7687` | TLS, single instance |

Auth options: `AuthTokens.basic(u,p)` · `AuthTokens.bearer(token)` · `AuthTokens.kerberos(b64)` · `AuthTokens.none()`

---

## Choosing the Right API

| API | When | Auto-retry | Streaming |
|---|---|:---:|:---:|
| `driver.executableQuery()` | Default for most queries | ✅ | ❌ eager |
| `session.executeRead/Write()` | Large results, callback control | ✅ | ✅ |
| `session.beginTransaction()` | Multi-method, external coordination | ❌ | ✅ |
| `session.run()` | Self-managing queries (`CALL IN TRANSACTIONS`) | ⚠️ one-shot [6.1+] | ✅ |
| `driver.asyncSession()` | Non-blocking `CompletableFuture` | ✅ | ✅ |
| `driver.rxSession()` | Reactor/RxJava backpressure | ✅ | ✅ |

`CALL { … } IN TRANSACTIONS` and `USING PERIODIC COMMIT` self-manage their transaction — use `session.run()` only. `executableQuery` and `executeRead/Write` will fail for these queries.

`session.run()` retry [6.1+]: single immediate retry on idempotent errors only (enabled by default). Disable per driver or per session:

```java
// Driver-level — disable for all sessions
var config = Config.builder().withAutoCommitRetriesDisabled(true).build();

// Session-level — overrides driver
var sessionConfig = SessionConfig.builder()
    .withAutoCommitRetriesMode(AutoCommitRetriesMode.DISABLED)  // DEFAULT = follow driver
    .build();
```

---

## `executableQuery` — Default

```java
// Read — route to replicas
var result = driver.executableQuery("""
        MATCH (p:Person {name: $name})-[:KNOWS]->(friend)
        RETURN friend.name AS name
        """)
    .withParameters(Map.of("name", "Alice"))
    .withConfig(QueryConfig.builder()
        .withDatabase("neo4j")            // always specify — avoids home-db round-trip
        .withRouting(RoutingControl.READ)
        .build())
    .execute();

result.records().forEach(r -> System.out.println(r.get("name").asString()));
long ms = result.summary().resultAvailableAfter(TimeUnit.MILLISECONDS);

// Write
driver.executableQuery("CREATE (p:Person {name: $name, age: $age})")
    .withParameters(Map.of("name", "Bob", "age", 30))
    .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
    .execute();
```

Never string-interpolate Cypher. Always `.withParameters(Map.of(...))`.

---

## Managed Transactions (`executeRead` / `executeWrite`)

Sessions are NOT thread-safe — one per request/thread, always close.

```java
try (var session = driver.session(SessionConfig.builder()
        .withDatabase("neo4j").build())) {

    // Read → replica routing
    var names = session.executeRead(tx -> {
        var result = tx.run(
            "MATCH (p:Person) WHERE p.name STARTS WITH $prefix RETURN p.name AS name",
            Map.of("prefix", "Al"));
        return result.stream().map(r -> r.get("name").asString()).toList(); // collect INSIDE
    });

    // Write → leader routing
    session.executeWriteWithoutResult(tx ->
        tx.run("CREATE (p:Person {name: $name})", Map.of("name", "Carol"))
    );
}
```

### Result must be consumed INSIDE the callback

`Result` is a lazy cursor tied to the open transaction. Transaction closes when callback returns — any read after that throws `ResultConsumedException`.

```java
// ❌ Returns Result — already closed by the time caller uses it
var result = session.executeRead(tx ->
    tx.run("MATCH (p:Person) RETURN p.name AS name"));
result.stream().forEach(...); // throws ResultConsumedException

// ✅ Collect to List inside callback
var names = session.executeRead(tx ->
    tx.run("MATCH (p:Person) RETURN p.name AS name")
      .stream().map(r -> r.get("name").asString()).toList());
```

### Callback rules

- Consume each `Result` before next `tx.run()` — multiple open cursors = undefined behaviour.
- No side effects (HTTP, email, metric increments) — callback may be retried on transient errors.
- Use `MERGE` (idempotent), not `CREATE`, for retry-safe writes.
- `executeRead` → replica; `executeWrite` → leader.

### TransactionConfig — timeouts & metadata

```java
var config = TransactionConfig.builder()
    .withTimeout(Duration.ofSeconds(5))
    .withMetadata(Map.of("app", "myService", "user", userId))  // visible in SHOW TRANSACTIONS
    .build();
session.executeRead(tx -> { /* ... */ }, config);
```

---

## Explicit Transactions

Use when work spans multiple methods or requires external coordination. Not auto-retried.

```java
try (var session = driver.session(SessionConfig.builder().withDatabase("neo4j").build())) {
    var tx = session.beginTransaction();
    try {
        doPartA(tx);
        doPartB(tx);
        tx.commit();
    } catch (Exception e) {
        try { tx.rollback(); } catch (Exception rb) { e.addSuppressed(rb); }
        throw e;
    }
}
```

`tx.rollback()` is a network call — wrap in its own try/catch and use `addSuppressed` so the original exception is not lost.

**Commit uncertainty**: if `tx.commit()` throws `ServiceUnavailableException`, the commit may or may not have succeeded. Design writes as idempotent (`MERGE` + unique constraints) so retrying is safe.

Choose explicit vs managed:
- Auto-retry needed → `executeRead` / `executeWrite`
- Work spans multiple methods → explicit (pass `tx` as parameter)
- Coordinating with external I/O → explicit (commit only after I/O succeeds)

---

## Error Handling

```java
try {
    driver.executableQuery("...").execute();
} catch (ServiceUnavailableException e) {
    // No servers — check connection
} catch (SessionExpiredException e) {
    // Server closed session — open new one
} catch (TransientException e) {
    // Managed txns retry automatically; explicit txns need manual retry
} catch (Neo4jException e) {
    // Cypher/constraint error — e.code() gives GQL status code
}
```

Managed transactions auto-retry `TransientException` — no catch needed.

---

## Data Types & Value Extraction

| Cypher type | Java accessor |
|---|---|
| `Integer` | `value.asLong()` / `value.asInt()` |
| `Float` | `value.asDouble()` |
| `String` | `value.asString()` |
| `Boolean` | `value.asBoolean()` |
| `List` | `value.asList()` |
| `Map` | `value.asMap()` |
| `Node` | `value.asNode()` |
| `Relationship` | `value.asRelationship()` |
| `Date` | `value.asLocalDate()` |
| `DateTime` | `value.asZonedDateTime()` |
| `UUID` | `value.asUUID()` → `java.util.UUID` [6.2+, Neo4j 2026.08+] |

```java
var record = result.records().get(0);
String name = record.get("name").asString();
long age    = record.get("age").asLong();

var node = record.get("p").asNode();
String label = node.labels().iterator().next();
Map<String,Object> props = node.asMap();
```

### Null safety — two distinct cases

| Situation | `record.get(key)` | `.asString()` |
|---|---|---|
| Key present, value non-null | the value | returns string |
| Key present, value is graph null | `Value` where `.isNull()` = true | **throws** `Uncoercible` |
| Key absent (typo / not projected) | `Value.NULL` sentinel | **throws** `NoSuchElementException` |

```java
// Graph null — use default overload (safe only if key is always projected):
String city = record.get("city").asString("Unknown");

// Absent key — check containsKey first:
if (record.containsKey("city") && !record.get("city").isNull()) {
    String city = record.get("city").asString();
}
```

---

## Object Mapping

Map query results to Java records/classes directly — eliminates manual accessor calls.

```java
// Domain record — field names match RETURN aliases (case-sensitive)
public record Person(String name, long age) {}

// Map single record
var person = driver.executableQuery("MATCH (p:Person {name: $name}) RETURN p.name AS name, p.age AS age")
    .withParameters(Map.of("name", "Alice"))
    .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
    .execute()
    .records()
    .stream()
    .map(r -> r.get("name").asString())   // or: r.as(Person.class) — see note
    .findFirst()
    .orElseThrow();

// Using .as(Person.class) — maps RETURN keys to record fields by name
var person2 = driver.executableQuery("""
        MATCH (p:Person {name: $name})
        RETURN p.name AS name, p.age AS age
        """)
    .withParameters(Map.of("name", "Tom Hanks"))
    .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
    .execute()
    .records()
    .stream()
    .map(record -> record.get("p").as(Person.class))
    .findFirst()
    .orElseThrow(() -> new RuntimeException("Person not found"));
```

Nested mapping — return a map projection and include `COLLECT {}` for lists:

```java
public record Movie(String title, List<Person> actors) {}

var movieCypher = """
    MATCH (movie:Movie)
    LIMIT 1
    RETURN movie {
        .title,
        actors: COLLECT {
            MATCH (actor:Person)-[:ACTED_IN]->(movie)
            RETURN actor
        }
    }
    """;

var movie = driver.executableQuery(movieCypher)
    .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
    .execute()
    .records()
    .stream()
    .map(r -> r.get("movie").as(Movie.class))
    .findFirst()
    .orElseThrow();
```

Only mapped properties defined in the record are populated — extra properties returned by Cypher are ignored.

---

## Performance Patterns

**Always specify database** — omitting triggers home-db round-trip on every call.

**Route reads to replicas** — `RoutingControl.READ` in `QueryConfig` or use `executeRead`.

**Batch writes with `UNWIND`** — pass `List<Map<String,Object>>` (plain maps only; custom objects fail):

```java
List<Map<String, Object>> rows = people.stream()
    .map(p -> Map.<String, Object>of("name", p.name(), "age", p.age()))
    .toList();

driver.executableQuery("UNWIND $items AS item MERGE (p:Person {name: item.name}) SET p.age = item.age")
    .withParameters(Map.of("items", rows))
    .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
    .execute();
```

Allowed leaf types in parameter maps: `String`, `Long`/`Integer`/`Short`/`Byte`, `Double`/`Float`, `Boolean`, `List<?>`, `Map<String,?>`, `null`. Custom objects and `LocalDate` must be converted first.

**Group writes in one transaction** — one `executeWrite` with a loop, not one `executeWrite` per iteration.

**Connection pool** — default 100 connections. Tune if exhausted:
```java
Config.builder()
    .withMaxConnectionPoolSize(50)
    .withConnectionAcquisitionTimeout(30, TimeUnit.SECONDS)
    .build()
```

---

## Common Errors

| Mistake | Fix |
|---|---|
| String-interpolate Cypher params | `.withParameters(Map.of(...))` always |
| Omit database name | Set in `QueryConfig` / `SessionConfig` every time |
| New `Driver` per request | Create once at startup; share everywhere |
| Share `Session` across threads | One session per request/thread |
| Return `Result` from tx callback | Collect to `List`/`Map` inside callback |
| Leave `Result` open before next `tx.run()` | Consume before next call |
| Side effects in managed tx callback | Move outside — callback may retry |
| Pass custom objects to UNWIND params | Convert to `List<Map<String,Object>>` |
| `asString()` on graph null | `.asString("default")` or check `.isNull()` |
| `asString()` on absent key | `containsKey()` before optional access |
| Naked `tx.rollback()` in catch | Wrap in try/catch; use `addSuppressed` |
| Assume `commit()` failure = no commit | Commit uncertainty — design writes idempotent |
| Block inside async callback (`.join()`) | Chain with `thenCompose` |
| Skip session close in async error path | `exceptionallyCompose` to close then re-throw |
| One transaction per write in loop | Batch with `UNWIND` or group in one callback |
| `executeWrite` for a read | Use `executeRead` — routes to replica |

---

## References

Load on demand:
- [references/async-reactive.md](references/async-reactive.md) — full async `CompletableFuture` patterns, reactive `RxSession` with `Flux.usingWhen`, deadlock avoidance
- [references/property-encryption.md](references/property-encryption.md) — Property Encryption preview [6.3.0+]: envelope profile, key encapsulation services (local, AWS KMS, Azure Key Vault, GCP KMS), key manager, encrypt/decrypt with AAD
- [references/advanced-config.md](references/advanced-config.md) — full `Config.builder()` options, TLS, notification filtering, session-level auth, user impersonation, cross-session bookmarks, spatial types (Values.point/WGS-84/Cartesian)

Docs:
- Java Driver manual: https://neo4j.com/docs/java-manual/current/
- API reference: https://neo4j.com/docs/api/java-driver/current/

---

## Checklist
- [ ] One `Driver` instance created at startup; closed on shutdown
- [ ] `verifyConnectivity()` called after driver creation
- [ ] Database name specified in every `QueryConfig` / `SessionConfig`
- [ ] Parameters used (never string-interpolated Cypher)
- [ ] `Result` consumed inside managed transaction callback
- [ ] No side effects inside `executeRead/Write` callbacks
- [ ] Sessions closed via try-with-resources
- [ ] Async sessions closed in both success and error paths (`exceptionallyCompose`)
- [ ] `ServiceUnavailableException` on commit handled as commit-uncertain
- [ ] `UNWIND` params are `List<Map<String,Object>>` (no custom objects)
- [ ] `containsKey()` checked before accessing optional result columns

Attribution

neo4j-contribneo4j-contrib
View sourceSee grades on GitHubMore from neo4j-contrib →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →