Skip to content

feat: add java sdk#44

Open
liulx20 wants to merge 63 commits intoalibaba:mainfrom
liulx20:java-sdk
Open

feat: add java sdk#44
liulx20 wants to merge 63 commits intoalibaba:mainfrom
liulx20:java-sdk

Conversation

@liulx20
Copy link
Collaborator

@liulx20 liulx20 commented Mar 12, 2026

This pull request introduces a new Java driver for the NeuG graph database, including the initial implementation, build configuration, and usage documentation. The main changes establish the driver’s interface, provide factory methods for creating driver instances, set up Maven build and dependency management, and document how to use and integrate the driver in other projects.

Java driver implementation:

  • Added the main Driver interface in Driver.java, defining methods for session creation, connectivity verification, resource cleanup, and closed-state checking.
  • Added the GraphDatabase class in GraphDatabase.java as the entry point for creating driver instances, including URI validation and support for custom configuration via the Config class.

Build and dependency configuration:

  • Added a Maven build file pom.xml to manage dependencies (OkHttp, Protocol Buffers, Jackson, SLF4J, JUnit, Mockito), plugins for compilation, testing, code formatting, and Protocol Buffers code generation.

Documentation:

  • Added a comprehensive usage guide in USAGE.md, including installation instructions, dependency details, and example code for connecting, querying, and using configuration and parameters.

Protocol Buffers integration:

  • Updated response.proto with java_package and java_outer_classname options to support Java code generation for the driver.

Greptile Summary

This PR introduces a complete Java driver for the NeuG graph database, covering HTTP transport (Client/OkHttp), query serialization (JSON via Jackson), response parsing (protobuf), and the public API (Driver, Session, ResultSet). CI workflows are updated to build, format-check, and run unit and E2E tests. Several issues flagged in prior review rounds have been resolved (closed-state checks in InternalSession and InternalDriver, next()/previous() sentinel positions, FLOAT_ARRAY in getObject(), first() on an empty result set). Two new logic bugs remain in InternalResultSet:

  • relative() doesn't apply before-first/after-last sentinels — when the computed target is out of bounds, relative() delegates to absolute() which returns false without moving the cursor. Unlike next() (which advances to rowCount) and previous() (which retreats to -1), a failed relative() call leaves the cursor at its current position. A reverse-iteration loop calling relative(-1) from row 0 will never see isBeforeFirst() become true.
  • BYTES_ARRAY unhandled in getObject() and getMetaData() — the proto schema defines BytesArray, and Types.BYTES exists in the enum, but the getObject() switch falls to the default branch and throws UnsupportedOperationException. The getMetaData() switch similarly falls to default and reports Types.OTHER instead of Types.BYTES. This is the same class of issue as the FLOAT_ARRAY gap that was fixed in this round.

Confidence Score: 3/5

  • Safe to merge after fixing the relative() sentinel bug and the missing BYTES_ARRAY case in getObject() and getMetaData().
  • The driver's transport, serialization, and core parsing layers are solid. Several previously-flagged bugs were fixed in this iteration (closed-state checks, next()/previous() sentinels, FLOAT_ARRAY). However, relative() leaves the cursor in an inconsistent state on out-of-bounds navigation (breaking reverse-iteration patterns), and BYTES_ARRAY columns will throw UnsupportedOperationException at runtime — an omission symmetric to the already-fixed FLOAT_ARRAY gap. Both issues will surface in normal usage and should be addressed before merge.
  • tools/java_driver/src/main/java/com/alibaba/neug/driver/internal/InternalResultSet.java needs attention for both the relative() sentinel fix and the BYTES_ARRAY dispatch cases.

Important Files Changed

Filename Overview
tools/java_driver/src/main/java/com/alibaba/neug/driver/internal/InternalResultSet.java Core result-set implementation with two remaining logic bugs: relative() doesn't advance the cursor to before-first/after-last sentinels on out-of-bounds navigation (unlike next()/previous()), and BYTES_ARRAY is unhandled in both getObject() (throws UnsupportedOperationException) and getMetaData() (reports Types.OTHER instead of Types.BYTES). Several previously-flagged issues are now fixed (next()/previous() sentinels, FLOAT_ARRAY in getObject(), first() on empty result set, getRow() after afterLast() still returns rowCount not -1).
tools/java_driver/src/main/java/com/alibaba/neug/driver/internal/InternalSession.java Closed-state check is now correctly in place — run() throws IllegalStateException when the session is closed. Clean implementation.
tools/java_driver/src/main/java/com/alibaba/neug/driver/internal/InternalDriver.java session() now checks if the client is closed and throws IllegalStateException. verifyConnectivity() correctly uses try-with-resources. Clean and correct.
tools/java_driver/src/main/java/com/alibaba/neug/driver/utils/Client.java Closed-state guard present in syncPost(). Missing Content-Type: application/json header on the request body (previously noted). closed field is not volatile but driver doesn't advertise thread-safety.
tools/java_driver/src/main/java/com/alibaba/neug/driver/GraphDatabase.java Clean factory class with correct URI validation (null, empty, and scheme checks). Private constructor prevents instantiation. No issues.
.github/workflows/format-check.yml Uses s4u/setup-maven-action@v1.19.0 to configure Java 17 and Maven 3.9.6 cleanly — no redundant apt install maven step is present. Java format checking via mvn spotless:check added correctly.
tools/java_driver/src/test/java/com/alibaba/neug/driver/JavaDriverE2ETest.java E2E integration test that uses assumeTrue to skip when the server URI env-var is absent. Covers basic query and parameterized query paths correctly.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Client Code] --> B[GraphDatabase.driver uri, config]
    B --> |URI validation| C[InternalDriver]
    C --> D[Client OkHttp]

    A --> E[driver.session]
    E --> |checks client.isClosed| F[InternalSession]

    A --> G[session.run query, params, mode]
    G --> |checks closed flag| H[QuerySerializer.serialize]
    H --> I[Client.syncPost JSON bytes]
    I --> J[HTTP POST /cypher]
    J --> K[NeuG Server]
    K --> L[protobuf bytes]
    L --> M[ResponseParser.parse]
    M --> N[InternalResultSet]

    N --> O{Cursor Navigation}
    O --> |next / previous| P[Advance/Retreat cursor]
    O --> |absolute row| Q[Set cursor directly]
    O --> |relative rows ⚠️| R[Delegates to absolute - no sentinel fix]
    O --> |afterLast / beforeFirst| S[Set to rowCount or -1]

    N --> T{Data Access}
    T --> |getInt / getLong / getString etc.| U[getValues currentIndex]
    T --> |getObject| V{switch on ArrayType}
    V --> |BYTES_ARRAY ⚠️| W[UnsupportedOperationException]
    V --> |other types| X[Return typed value]
Loading

Last reviewed commit: d23081c

Greptile also left 2 inline comments on this PR.

Greptile Summary

This PR adds a complete Java driver for the NeuG graph database, covering HTTP transport (OkHttp), query serialization (JSON via Jackson), response parsing (protobuf), and the public API (Driver, Session, ResultSet). CI workflows are updated to build, format-check, and run unit and E2E tests. Several issues flagged in prior review rounds have been resolved in this iteration: closed-state checks in InternalSession and InternalDriver, next()/previous() sentinel positions, FLOAT_ARRAY in getObject(), and first() on an empty result set.

Key observations in this round:

  • Types.BYTES is now orphanedBytesArray was removed from response.proto in this PR (both the message and the bytes_array = 9 field in Array), but Types.BYTES remains in Types.java. It is now a dead enum constant with no proto type to back it, and callers can never receive it from getMetaData().
  • ccache key over-expandedtools/java_driver/** was added to the C++ ccache hash in neug-test.yml. Java sources have no effect on C++ artifacts; including them in the key means Java-only PRs will always miss the primary ccache entry and fall back to incremental recompilation unnecessarily.
  • testRelative validates unfixed behavior — the test is written to pass against the current (broken) relative() cursor semantics; it would fail if the relative() sentinel bug were fixed in a future PR, making the test an implicit obstacle to that fix.

Confidence Score: 4/5

  • Safe to merge after addressing the Types.BYTES dead enum constant and the ccache key over-expansion; the two pre-existing open issues (relative() sentinels, getRow() after afterLast()) are carryovers from prior rounds and do not block this iteration.
  • The transport, serialization, and core parsing layers are solid and all previously-flagged critical bugs have been fixed in this round. The two remaining open issues (relative() sentinel and getRow() after afterLast()) are carryovers from prior review rounds. New issues introduced in this iteration are minor: a dead Types.BYTES enum constant left behind after BytesArray was removed from the proto, and an unnecessarily broad ccache key in CI. Neither blocks correctness in production.
  • tools/java_driver/src/main/java/com/alibaba/neug/driver/utils/Types.java (dead BYTES constant) and .github/workflows/neug-test.yml (ccache key over-expansion).

Important Files Changed

Filename Overview
tools/java_driver/src/main/java/com/alibaba/neug/driver/internal/InternalResultSet.java Core result-set implementation. Previously-flagged issues resolved in this round: next()/previous() sentinels, FLOAT_ARRAY in getObject(), and first() on empty result set. Two pre-existing issues from prior review rounds remain open: relative() does not advance the cursor to before-first/after-last on out-of-bounds navigation, and getRow() returns rowCount instead of -1 after afterLast().
tools/java_driver/src/main/java/com/alibaba/neug/driver/utils/Types.java Types.BYTES is now a dead enum constant: the PR removes BytesArray from response.proto but leaves this entry in place. Minor inconsistency introduced by this PR.
tools/java_driver/src/main/java/com/alibaba/neug/driver/utils/Client.java Closed-state guard is present in syncPost(). closed field is not volatile and close() is not synchronized, so concurrent use could see stale state — but the driver does not advertise thread-safety. Missing Content-Type: application/json header remains (flagged in prior round).
.github/workflows/neug-test.yml Java driver test step added correctly; tools/java_driver/** is unnecessarily included in the ccache hash key, causing C++ cache misses on Java-only changes.
tools/java_driver/src/test/java/com/alibaba/neug/driver/InternalResultSetTest.java Good coverage of navigation, typed accessors, null handling, and unsigned integer overflow. testRelative is written against the current (unfixed) relative() sentinel behavior — the test would fail if the relative() bug were corrected.
proto/response.proto java_package and java_outer_classname options added for Java code generation. BytesArray message and bytes_array = 9 field removed from the Array oneof — intentional, but leaves Types.BYTES orphaned in Types.java.

Sequence Diagram

sequenceDiagram
    participant App as Client Code
    participant GDB as GraphDatabase
    participant DRV as InternalDriver
    participant CLI as Client (OkHttp)
    participant SES as InternalSession
    participant SRV as NeuG Server
    participant RS as InternalResultSet

    App->>GDB: driver(uri, config)
    GDB->>GDB: validate URI (null/empty/scheme)
    GDB->>DRV: new InternalDriver(uri, config)
    DRV->>CLI: new Client(uri, config)
    GDB-->>App: Driver

    App->>DRV: session()
    DRV->>DRV: check client.isClosed()
    DRV->>SES: new InternalSession(client)
    DRV-->>App: Session

    App->>SES: run(query, params, mode)
    SES->>SES: check closed flag
    SES->>SES: QuerySerializer.serialize(query, params, mode)
    SES->>CLI: syncPost(jsonBytes)
    CLI->>CLI: check closed flag
    CLI->>SRV: HTTP POST /cypher (JSON body)
    SRV-->>CLI: protobuf bytes
    CLI-->>SES: responseBytes
    SES->>RS: ResponseParser.parse(responseBytes)
    Note over RS: cursor starts at -1 (before-first)
    SES-->>App: ResultSet

    App->>RS: next() / absolute() / relative()
    RS-->>App: boolean (row available)
    App->>RS: getInt() / getString() / getObject()
    RS-->>App: typed value
    App->>RS: wasNull()
    RS-->>App: boolean

    App->>SES: close()
    App->>DRV: close()
    DRV->>CLI: close() → evictAll + shutdown executor
Loading

Last reviewed commit: "remove bytearray"

Greptile also left 1 inline comment on this PR.

liulx20 and others added 5 commits March 12, 2026 16:49
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@liulx20
Copy link
Collaborator Author

liulx20 commented Mar 12, 2026

@greptile-apps anything else?

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 12, 2026

The main critical issues have been covered — the two static field bugs are blocking and must be fixed before merge.

A few additional notes:

1. No tests included — The PR adds JUnit/Mockito dependencies in pom.xml, but doesn't appear to include any test classes. For a new driver implementation, you'd want at least basic integration tests.

2. Resource cleanup — In Client.syncPost, the Response object should be closed (use try-with-resources) to properly return connections to the pool:

try (Response response = httpClient.newCall(request).execute()) {
    ResponseBody body = response.body();
    // ... null check and read bytes
}

3. Thread safety — Beyond the static field bugs, once those are fixed to instance fields, the driver should be thread-safe (OkHttp's client is thread-safe), but this hasn't been documented or tested.

Bottom line: Fix the two critical static field bugs first — they break multi-driver usage entirely. The other issues are important but secondary.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an initial Java SDK/driver for the NeuG graph database, including a public API surface, internal HTTP/protobuf plumbing, Maven build configuration, and accompanying tests/docs.

Changes:

  • Introduces core driver APIs (Driver, Session, ResultSet) and factory entry point (GraphDatabase) backed by internal implementations.
  • Adds utility components for request/response handling over HTTP (OkHttp) with JSON serialization and protobuf response parsing.
  • Adds a standalone Maven module (tools/java_driver) with unit tests and a usage guide.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tools/java_driver/src/test/java/org/alibaba/neug/driver/QuerySerializerTest.java Adds unit tests covering query JSON serialization permutations.
tools/java_driver/src/test/java/org/alibaba/neug/driver/JsonUtilTest.java Adds tests to validate singleton ObjectMapper access.
tools/java_driver/src/test/java/org/alibaba/neug/driver/InternalResultSetTest.java Adds tests for protobuf-to-Java type mapping, cursoring, and null bitmap handling.
tools/java_driver/src/test/java/org/alibaba/neug/driver/GraphDatabaseTest.java Adds basic factory creation tests and multi-driver instantiation check.
tools/java_driver/src/test/java/org/alibaba/neug/driver/ConfigTest.java Adds tests for default/custom config builder behavior.
tools/java_driver/src/test/java/org/alibaba/neug/driver/ClientTest.java Adds tests around Client lifecycle and basic connectivity failure behavior.
tools/java_driver/src/test/java/org/alibaba/neug/driver/AccessModeTest.java Adds enum sanity tests for AccessMode.
tools/java_driver/src/main/java/org/alibaba/neug/driver/utils/ResponseParser.java Adds protobuf response parsing helper returning ResultSet.
tools/java_driver/src/main/java/org/alibaba/neug/driver/utils/QuerySerializer.java Adds JSON request serializer for query/params/access mode.
tools/java_driver/src/main/java/org/alibaba/neug/driver/utils/JsonUtil.java Adds shared Jackson ObjectMapper singleton holder.
tools/java_driver/src/main/java/org/alibaba/neug/driver/utils/Config.java Adds driver configuration object + builder for timeouts/pool sizing.
tools/java_driver/src/main/java/org/alibaba/neug/driver/utils/Client.java Adds OkHttp-based synchronous POST client to /cypher.
tools/java_driver/src/main/java/org/alibaba/neug/driver/utils/AccessMode.java Adds access mode enum used in requests.
tools/java_driver/src/main/java/org/alibaba/neug/driver/internal/InternalSession.java Implements Session by serializing, posting, and parsing results.
tools/java_driver/src/main/java/org/alibaba/neug/driver/internal/InternalResultSet.java Implements ResultSet cursoring and typed getters over protobuf arrays.
tools/java_driver/src/main/java/org/alibaba/neug/driver/internal/InternalDriver.java Implements Driver to create sessions and manage the underlying client.
tools/java_driver/src/main/java/org/alibaba/neug/driver/Session.java Defines the Session API for executing queries.
tools/java_driver/src/main/java/org/alibaba/neug/driver/ResultSet.java Defines the ResultSet cursor and typed access API.
tools/java_driver/src/main/java/org/alibaba/neug/driver/GraphDatabase.java Adds factory methods for driver creation with URI/config validation.
tools/java_driver/src/main/java/org/alibaba/neug/driver/Driver.java Defines the top-level Driver interface and lifecycle methods.
tools/java_driver/pom.xml Adds Maven module build, dependencies, protobuf generation, formatting, and test setup.
tools/java_driver/USAGE.md Documents installation and example usage of the new Java driver.
proto/response.proto Adds Java protobuf generation options (java_package, java_outer_classname).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@liulx20
Copy link
Collaborator Author

liulx20 commented Mar 17, 2026

@greptile

liulx20 and others added 4 commits March 17, 2026 16:43
…al/InternalDriver.java

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@liulx20
Copy link
Collaborator Author

liulx20 commented Mar 17, 2026

@greptile

liulx20 and others added 2 commits March 17, 2026 19:09
…al/InternalResultSet.java

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…al/InternalResultSet.java

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@liulx20
Copy link
Collaborator Author

liulx20 commented Mar 17, 2026

@greptile

@liulx20
Copy link
Collaborator Author

liulx20 commented Mar 17, 2026

@greptile

@liulx20
Copy link
Collaborator Author

liulx20 commented Mar 18, 2026

@greptile

@liulx20 liulx20 requested a review from longbinlai March 19, 2026 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants