This is an automated email from the ASF dual-hosted git repository.

Cole-Greer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/master by this push:
     new 982ee6e65d Support Java 21/25 and Spark 4.1, raise minimum to Java 17 
(#3489)
982ee6e65d is described below

commit 982ee6e65df9d6e5e699d784261286791181e0c2
Author: Oleksandr Porunov <[email protected]>
AuthorDate: Thu Jul 9 05:52:51 2026 +0100

    Support Java 21/25 and Spark 4.1, raise minimum to Java 17 (#3489)
    
    Modernizes TinkerPop 4.0 to build and run on Java 21 and Java 25 and 
upgrades
    the Spark OLAP integration to Spark 4.1. Because Spark 4 requires Java 17 
as a
    minimum, the project-wide minimum Java version is raised from 11 to 17. 
Every
    LTS release from the new minimum upward (17, 21, 25) is covered by CI.
    
    Java 21/25 support:
    - Groovy 4.0.25 -> 4.0.32 (bundled ASM parses Java 25 bytecode)
    - StringFactory: detect the Java 21+ lambda class name format ($$Lambda/)
    - LambdaRestrictionStrategy: match "lambda" case-insensitively
    - ImportGremlinPluginTest: account for Math.TAU added in Java 19
    - gremlin-groovy: declare annotationProcessorPaths explicitly (JDK 23+ no
      longer runs classpath-discovered processors) and widen the javadoc
      groovy-stubs profile to all supported JDKs
    - gremlin-console: apply the neo4j-gremlin --add-opens flags for JDK 17+
    
    Dependency upgrades:
    - Hadoop 3.4.2 -> 3.4.3 (uses the Subject.current()/callAs() replacement 
APIs)
    - Spark 3.5.4 -> 4.1.2, which is Scala 2.13 only, the first Spark line to
      support Java 25, and the second to support Java 21 (SPARK-43831 landed in
      4.0): spark-core_2.12 -> _2.13, Scala 2.13 source migration
      (JavaConversions -> CollectionConverters, WrappedArray -> immutable
      ArraySeq), and aligned Netty, jackson (via jackson-bom) and other 
transitive
      versions that Spark 4 requires
    - Netty 4.1.125 -> 4.2.7 (required by Spark 4)
    
    Java 17 baseline (breaking):
    - enforcer requireJavaVersion [11,18) -> [17,26); compiler release 11 -> 17
      (and gremlin-groovy/gremlin-annotations release 8 -> 17)
    - build-test.yml: all jobs run on Java 17, plus new Java 21 and Java 25 
jobs;
      the Java 11 job is removed and coverage runs on the Java 17 job
    - Dockerfiles updated to Java 17; developer, reference, and upgrade docs 
list
      Java 17 as the minimum with Java 21 and 25 supported
    
    Integration-test fixes for the Java 17 baseline (deep reflection into 
java.base
    is denied by default on Java 17, and TLS 1.3 is the default):
    - gremlin-server.sh: append the jdk17 --add-opens/--add-exports set to
      JAVA_OPTIONS so the standalone/Docker server can perform the deep 
reflection
      Kryo/Gryo needs
    - GremlinServerSslIntegrateTest: accept the alerts Java 17's TLS 1.3 raises 
for
      a missing/untrusted client certificate
    - gremlin-socket-server and gremlin-console test Docker images use Java 17
    
    Assisted-by: claude-opus-4.8
---
 .github/workflows/build-test.yml                   | 80 +++++++++++++---------
 CHANGELOG.asciidoc                                 |  3 +
 docker/Dockerfile                                  |  4 +-
 .../dev/developer/development-environment.asciidoc |  9 +--
 docs/src/reference/gremlin-variants.asciidoc       |  1 +
 docs/src/upgrade/release-4.x.x.asciidoc            | 14 ++++
 gremlin-annotations/pom.xml                        |  6 +-
 gremlin-console/Dockerfile                         |  2 +-
 gremlin-console/pom.xml                            |  4 +-
 gremlin-console/src/main/bin/gremlin.sh            |  5 +-
 gremlin-console/src/test/python/docker/Dockerfile  |  2 +-
 .../verification/LambdaRestrictionStrategy.java    |  2 +-
 .../gremlin/structure/util/StringFactory.java      |  3 +-
 .../gremlin/jsr223/ImportGremlinPluginTest.java    | 11 ++-
 gremlin-groovy/pom.xml                             | 46 +++++++++++--
 gremlin-server/Dockerfile                          |  2 +-
 gremlin-server/src/main/bin/gremlin-server.sh      | 19 +++++
 .../server/GremlinServerSslIntegrateTest.java      | 18 +++--
 gremlin-tools/gremlin-socket-server/Dockerfile     |  2 +-
 pom.xml                                            | 24 +++----
 spark-gremlin/pom.xml                              | 49 ++++++++++---
 .../tinkerpop/gremlin/spark/structure/Spark.java   |  4 +-
 .../spark/structure/io/gryo/GryoRegistrator.java   |  4 +-
 .../spark/structure/io/gryo/GryoSerializer.java    |  4 +-
 .../structure/io/gryo/WrappedArraySerializer.java  | 21 +++---
 .../gremlin/spark/structure/SparkTest.java         |  6 +-
 26 files changed, 242 insertions(+), 103 deletions(-)

diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 0f8f7aecad..30ffc51ac3 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -20,10 +20,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven
         run: mvn clean install -DskipTests -Dci --batch-mode 
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
@@ -40,25 +40,39 @@ jobs:
           java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven
-        run: mvn clean install -pl $EXCLUDE_MODULES -Dci --batch-mode 
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
-  java-jdk11:
-    name: mvn clean install - jdk11
+        run: mvn clean install -pl $EXCLUDE_MODULES -Dci --batch-mode 
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
 -Dcoverage
+      - name: Upload to Codecov
+        uses: codecov/codecov-action@v7
+        with:
+         directory: ./gremlin-tools/gremlin-coverage/target/site
+  java-jdk21:
+    name: mvn clean install - jdk21
     timeout-minutes: 45
     needs: smoke
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 21
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '21'
           distribution: 'temurin'
       - name: Build with Maven
-        run: mvn clean install -pl $EXCLUDE_MODULES -Dci --batch-mode 
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
 -Dcoverage
-      - name: Upload to Codecov
-        uses: codecov/codecov-action@v7
+        run: mvn clean install -pl $EXCLUDE_MODULES -Dci --batch-mode 
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
+  java-jdk25:
+    name: mvn clean install - jdk25
+    timeout-minutes: 45
+    needs: smoke
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v7
+      - name: Set up JDK 25
+        uses: actions/setup-java@v5
         with:
-         directory: ./gremlin-tools/gremlin-coverage/target/site
+          java-version: '25'
+          distribution: 'temurin'
+      - name: Build with Maven
+        run: mvn clean install -pl $EXCLUDE_MODULES -Dci --batch-mode 
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
   gremlin-server-default:
     name: gremlin-server default
     timeout-minutes: 45
@@ -66,10 +80,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven
         run: |
@@ -82,10 +96,10 @@ jobs:
       runs-on: ubuntu-latest
       steps:
         - uses: actions/checkout@v7
-        - name: Set up JDK 11
+        - name: Set up JDK 17
           uses: actions/setup-java@v5
           with:
-            java-version: '11'
+            java-version: '17'
             distribution: 'temurin'
         - name: Generate Gremlin Server Base
           working-directory: .
@@ -118,10 +132,10 @@ jobs:
 #    runs-on: ubuntu-latest
 #    steps:
 #      - uses: actions/checkout@v7
-#      - name: Set up JDK 11
+#      - name: Set up JDK 17
 #        uses: actions/setup-java@v5
 #        with:
-#          java-version: '11'
+#          java-version: '17'
 #          distribution: 'temurin'
 #      - name: Build with Maven
 #        run: |
@@ -134,10 +148,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven
         run: |
@@ -153,10 +167,10 @@ jobs:
         os: [ubuntu-latest, windows-latest]
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven Windows
         if: runner.os == 'Windows'
@@ -177,10 +191,10 @@ jobs:
         os: [ubuntu-latest, windows-latest]
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven Windows
         if: runner.os == 'Windows'
@@ -198,10 +212,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven
         run: |
@@ -215,10 +229,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Build with Maven
         run: |
@@ -235,10 +249,10 @@ jobs:
         node-version: [ '22', '24', '26' ]
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Get Cached Server Base Image
         uses: actions/cache@v6
@@ -269,10 +283,10 @@ jobs:
       PYTHON_VERSION: ${{ matrix.python-version }}
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK 11
+      - name: Set up JDK 17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Set up Python ${{ matrix.python-version }}
         uses: actions/setup-python@v6
@@ -291,10 +305,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v7
-      - name: Set up JDK11
+      - name: Set up JDK17
         uses: actions/setup-java@v5
         with:
-          java-version: '11'
+          java-version: '17'
           distribution: 'temurin'
       - name: Set up .NET 8.0.x
         uses: actions/setup-dotnet@v5
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 9632d16aee..8bb8aacf59 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,9 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 [[release-4-0-0]]
 === TinkerPop 4.0.0 (Release Date: NOT OFFICIALLY RELEASED YET)
 
+* Raised the minimum Java version to 17 for building and running *(breaking)*.
+* Enabled building and running with Java 21 and Java 25.
+* Bumped Groovy to 4.0.32, Hadoop to 3.4.3, Spark to 4.1.2 (Scala 2.13), and 
Netty to 4.2.7 to support Java 25.
 * Standardized connection options across all GLVs (Java, Python, .NET, Go, 
JavaScript) per the TinkerPop 4.x GLV proposal; see the upgrade docs for the 
full per-driver table. *(breaking)*
 ** Aligned option names across drivers: `maxConnections` (128), 
`connectTimeoutMillis` (5000), `readTimeoutMillis` (off), `idleTimeoutMillis` 
(180000), `keepAliveTimeMillis` (30000), `compression` (on/`deflate`), 
`batchSize` (64), `bulkResults` (false), `maxResponseHeaderBytes`, `proxy`, and 
`ssl`. Timeouts use a millisecond-suffixed canonical name with an idiomatic 
duration companion (Java `Duration`, Go `time.Duration`, .NET `TimeSpan`, 
Python seconds); JavaScript uses milliseconds only.
 ** Java: renamed 
`maxConnectionPoolSize`/`connectionSetupTimeoutMillis`/`idleConnectionTimeoutMillis`/`resultIterationBatchSize`
 and `RequestOptions.addG`->`traversalSource`; removed 
`maxResponseContentLength` (responses now stream); added `readTimeoutMillis`, 
`keepAliveTimeMillis`, `maxResponseHeaderBytes`, `proxy`, `url(String)`, 
`ssl(SslContext)`. *(breaking)*
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 66a375384b..921c80ee68 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -29,7 +29,7 @@ RUN apt-get install apt-transport-https gnupg ca-certificates
 RUN sh -c 'echo "deb https://download.mono-project.com/repo/ubuntu 
stable-focal main" | tee /etc/apt/sources.list.d/mono-official-stable.list'
 RUN apt-get update
 
-RUN apt-get install -y openjdk-11-jdk gawk git maven openssh-server subversion 
zip
+RUN apt-get install -y openjdk-17-jdk gawk git maven openssh-server subversion 
zip
 RUN apt-get install -y --force-yes dotnet-sdk-8.0 mono-devel
 
 ENV DEBIAN_FRONTEND=noninteractive
@@ -43,7 +43,7 @@ RUN python3 -m pip install --upgrade pip
 RUN pip install virtualenv
 RUN pip install virtualenvwrapper --no-deps
 
-RUN rm -rf /var/lib/apt/lists/* /var/cache/openjdk-11-jdk
+RUN rm -rf /var/lib/apt/lists/* /var/cache/openjdk-17-jdk
 
 RUN sed -i 's@PermitRootLogin without-password@PermitRootLogin yes@' 
/etc/ssh/sshd_config
 RUN sed -i 's@session\s*required\s*pam_loginuid.so@session optional 
pam_loginuuid.so@g' /etc/pam.d/sshd
diff --git a/docs/src/dev/developer/development-environment.asciidoc 
b/docs/src/dev/developer/development-environment.asciidoc
index e0a9559218..c7748ac728 100644
--- a/docs/src/dev/developer/development-environment.asciidoc
+++ b/docs/src/dev/developer/development-environment.asciidoc
@@ -28,8 +28,9 @@ image:conspiracy.png[]
 [[system-configuration]]
 == System Configuration
 
-At a minimum, development of TinkerPop requires 
link:https://openjdk.java.net/projects/jdk/11/[Java 11] or
-link:https://openjdk.org/projects/jdk/17/[Java 17]. Note, however, that there 
are some issues with deep reflection
+At a minimum, development of TinkerPop requires 
link:https://openjdk.org/projects/jdk/17/[Java 17]; builds and tests
+also run on link:https://openjdk.org/projects/jdk/21/[Java 21] and 
link:https://openjdk.org/projects/jdk/25/[Java 25].
+Note, however, that there are some issues with deep reflection
 so there are `--add-opens` JVM options included in the pom files to enable 
this to work. Maven (requiring a minimum of
 link:https://maven.apache.org/download.cgi[Maven 3.5.3+]) is used as the 
common build system, which even
 controls the builds of non-JVM 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[GLVs]
@@ -47,7 +48,7 @@ system. You will need to install both 
link:https://docs.docker.com/engine/instal
 link:https://docs.docker.com/compose/install/[Docker Compose], which are 
included in
 link:https://docs.docker.com/desktop/[Docker Desktop].
 
-IMPORTANT: Use Java 11 for documentation generation with `bin/process-docs.sh` 
and for other build features outside
+IMPORTANT: Use Java 17 for documentation generation with `bin/process-docs.sh` 
and for other build features outside
 of the basic `mvn clean install` sort of function.
 
 IMPORTANT: For those who intend to offer a contribution, building with a 
minimal configuration may not be sufficient
@@ -124,7 +125,7 @@ The core of the documentation generation process is an 
link:https://asciidoctor.
 Gremlin Console subprocess, and renders the console output as tabbed HTML. The 
orchestration script
 `bin/process-docs.sh` wraps this and acts as the entrypoint: it validates the 
Gremlin Console and Gremlin Server
 distributions, installs the required plugins into the console, starts a 
Gremlin Server (for the `:remote` examples) and
-a Gephi mock, then invokes Maven to run the extension. Javadocs should be 
built using Java 11.
+a Gephi mock, then invokes Maven to run the extension. Javadocs should be 
built using Java 17.
 
 Before generating documentation, build the build all of the dependencies that 
the process consumes:
 
diff --git a/docs/src/reference/gremlin-variants.asciidoc 
b/docs/src/reference/gremlin-variants.asciidoc
index 4e90afdcf6..22e21adabc 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -902,6 +902,7 @@ The following table outlines recommended runtime versions 
by the release in whic
 |3.6.0 | Java 8, 11
 |3.7.0 | Java 8, 11, 17
 |3.8.0 | Java 11, 17
+|4.0.0 | Java 17, 21, 25
 |===
 
 [[gremlin-java-connecting]]
diff --git a/docs/src/upgrade/release-4.x.x.asciidoc 
b/docs/src/upgrade/release-4.x.x.asciidoc
index 1118cf3fc9..96ded966ba 100644
--- a/docs/src/upgrade/release-4.x.x.asciidoc
+++ b/docs/src/upgrade/release-4.x.x.asciidoc
@@ -106,6 +106,20 @@ These change runtime behavior on upgrade even if you do 
not change your configur
 
 See: 
link:https://lists.apache.org/thread/yqtr2wnb1kq2pqqq4002cz511q5o0bkg[[DISCUSS] 
Standardizing GLV connection options in TinkerPop 4].
 
+==== Java 17 Required; Java 21 and 25 Supported
+
+TinkerPop 4.0 raises the minimum Java version from 11 to 17 for both building 
and running, and adds support for running
+on Java 21 and Java 25, so that every LTS release from the new minimum upward 
is covered by TinkerPop's automated
+tests. *(breaking)* Supporting Java 25 required upgrading Groovy to 4.0.32 
(whose bundled ASM can parse Java 25
+bytecode) and Hadoop to 3.4.3 (which moved off the `Subject.getSubject()` API 
that was removed along with the Security
+Manager). Spark was upgraded to 4.1.x, built on Scala 2.13 — the first Spark 
line that supports Java 25. Because Spark 4
+requires Java 17 as its minimum, and `spark-gremlin` is part of the build, the 
project-wide minimum is now Java 17.
+Netty was upgraded to 4.2.x as required by Spark 4.
+
+As with the earlier JDK 17 support, some libraries still rely on deep 
reflection (most notably the Kryo serialization
+library used with OLAP), so it may be necessary to `--add-opens` or 
`--add-exports` certain modules at runtime. The set
+of options used by TinkerPop's own tests is unchanged.
+
 ==== Declarative Pattern Matching
 
 Gremlin has always offered both imperative and declarative styles to writing 
graph queries. While the imperative style
diff --git a/gremlin-annotations/pom.xml b/gremlin-annotations/pom.xml
index 8a1a83299a..15214dbd24 100644
--- a/gremlin-annotations/pom.xml
+++ b/gremlin-annotations/pom.xml
@@ -95,9 +95,9 @@ limitations under the License.
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <release>8</release>
-                    <source>8</source>
-                    <target>8</target>
+                    <release>17</release>
+                    <source>17</source>
+                    <target>17</target>
                     <compilerArgs>
                         <arg>-parameters</arg>
                         <arg>-proc:none</arg>
diff --git a/gremlin-console/Dockerfile b/gremlin-console/Dockerfile
index 44c995ae66..5752709997 100644
--- a/gremlin-console/Dockerfile
+++ b/gremlin-console/Dockerfile
@@ -23,7 +23,7 @@ ARG GREMLIN_CONSOLE_DIR
 
 RUN apk add --no-cache --update \
     bash \
-    openjdk11-jdk
+    openjdk17-jdk
 
 COPY src/main/docker/docker-entrypoint.sh /
 COPY ${GREMLIN_CONSOLE_DIR} /opt/gremlin-console
diff --git a/gremlin-console/pom.xml b/gremlin-console/pom.xml
index c167c08f79..0c96d16aa7 100644
--- a/gremlin-console/pom.xml
+++ b/gremlin-console/pom.xml
@@ -384,12 +384,12 @@ limitations under the License.
                                     <target>
                                         <exec executable="docker" 
failonerror="true">
                                             <!-- This build command relies on 
Docker's caching mechanism to reduce the amount of times it is run. -->
-                                            <arg line="build -t 
gremlin-console-test:py3.10jre11 ./src/test/python/docker"/>
+                                            <arg line="build -t 
gremlin-console-test:py3.10jre17 ./src/test/python/docker"/>
                                         </exec>
                                         <exec executable="docker" 
failonerror="true">
                                             <arg line="run --rm --mount 
type=bind,src=${project.basedir}/src/test/python,dst=/console_app
                                             --mount 
type=bind,src=${project.basedir}/target/apache-tinkerpop-gremlin-console-${project.version}-standalone,dst=/console_app/gremlin-console
-                                            gremlin-console-test:py3.10jre11"/>
+                                            gremlin-console-test:py3.10jre17"/>
                                         </exec>
                                     </target>
                                 </configuration>
diff --git a/gremlin-console/src/main/bin/gremlin.sh 
b/gremlin-console/src/main/bin/gremlin.sh
index 2cd33cbc04..8a245f80ef 100755
--- a/gremlin-console/src/main/bin/gremlin.sh
+++ b/gremlin-console/src/main/bin/gremlin.sh
@@ -108,9 +108,10 @@ if [ -n "$SCRIPT_DEBUG" ]; then
     set -x
 fi
 
-# Detect JDK version and add specific flags for JDK 17
+# Detect the JDK major version and add specific flags for JDK 17 and newer
 JAVA_VERSION=$($JAVA -version 2>&1 | awk -F '"' '/version/ {print $2}')
-if [[ "$JAVA_VERSION" == 17* ]]; then
+JAVA_MAJOR_VERSION=$(echo "$JAVA_VERSION" | awk -F. '{if ($1 == 1) print $2; 
else print $1}')
+if [[ "$JAVA_MAJOR_VERSION" -ge 17 ]]; then
     JVM_OPTS+=( "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" )
     JVM_OPTS+=( 
"--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED" )
 fi
diff --git a/gremlin-console/src/test/python/docker/Dockerfile 
b/gremlin-console/src/test/python/docker/Dockerfile
index e20de5991b..f4dec1f694 100644
--- a/gremlin-console/src/test/python/docker/Dockerfile
+++ b/gremlin-console/src/test/python/docker/Dockerfile
@@ -20,7 +20,7 @@ FROM python:3.10-bullseye
 
 LABEL maintainer="[email protected]"
 
-RUN apt-get update && apt-get install -y --no-install-recommends 
openjdk-11-jre && apt-get install dos2unix
+RUN apt-get update && apt-get install -y --no-install-recommends 
openjdk-17-jre && apt-get install dos2unix
 
 WORKDIR /console_app
 CMD dos2unix ./gremlin-console/bin/gremlin.sh && python3 setup.py build && 
python3 setup.py test; \
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/LambdaRestrictionStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/LambdaRestrictionStrategy.java
index d26141e632..5dc0c25f4c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/LambdaRestrictionStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/LambdaRestrictionStrategy.java
@@ -51,7 +51,7 @@ public final class LambdaRestrictionStrategy extends 
AbstractTraversalStrategy<T
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
         for (final Step<?, ?> step : traversal.getSteps()) {
-            if ((step instanceof LambdaHolder || step instanceof 
ComparatorHolder) && step.toString().contains("lambda"))
+            if ((step instanceof LambdaHolder || step instanceof 
ComparatorHolder) && step.toString().toLowerCase().contains("lambda"))
                 throw new VerificationException("The provided traversal 
contains a lambda step: " + step, traversal);
         }
     }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
index 74ba38437e..f84d83357b 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
@@ -237,7 +237,8 @@ public final class StringFactory {
     }
 
     private static boolean hasLambda(final String objectString) {
-        return objectString.contains("$Lambda$") || // JAVA 
(org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphPlayTest$$Lambda$1/1711574013@61a52fb)
+        return objectString.contains("$Lambda$") || // JAVA <21 
(org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphPlayTest$$Lambda$1/1711574013@61a52fb)
+                objectString.contains("$$Lambda/") || // JAVA 21+ 
(org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphPlayTest$$Lambda/0x00007fc001151000@61a52fb)
                 objectString.contains("$_run_closure") || // GROOVY 
(groovysh_evaluate$_run_closure1@db44aa2)
                 objectString.contains("<lambda>");  // PYTHON (<function 
<lambda> at 0x10dfaec80>)
     }
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinPluginTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinPluginTest.java
index 0a1868da74..c628f48578 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinPluginTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinPluginTest.java
@@ -148,8 +148,15 @@ public class ImportGremlinPluginTest {
                 
.fieldsImports(Collections.singletonList(Math.class.getCanonicalName() + 
"#*")).create();
 
         final DefaultImportCustomizer customizer = (DefaultImportCustomizer) 
module.getCustomizers().get()[0];
-        assertThat(customizer.getFieldImports(), is(new HashSet<>(
-                Arrays.asList(Math.class.getField("PI"), 
Math.class.getField("E")))));
+        // Math.TAU was added in Java 19
+        final HashSet<Field> expectedFields = new HashSet<>(Arrays.asList(
+                Math.class.getField("PI"), Math.class.getField("E")));
+        try {
+            expectedFields.add(Math.class.getField("TAU"));
+        } catch (NoSuchFieldException ignored) {
+            // TAU not available in Java < 19
+        }
+        assertThat(customizer.getFieldImports(), is(expectedFields));
     }
 
     @Test
diff --git a/gremlin-groovy/pom.xml b/gremlin-groovy/pom.xml
index 5b7af40287..aaafa65750 100644
--- a/gremlin-groovy/pom.xml
+++ b/gremlin-groovy/pom.xml
@@ -142,12 +142,44 @@ limitations under the License.
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <release>8</release>
-                    <source>8</source>
-                    <target>8</target>
+                    <release>17</release>
+                    <source>17</source>
+                    <target>17</target>
                     <compilerArgs>
                         <arg>-parameters</arg>
                     </compilerArgs>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.apache.tinkerpop</groupId>
+                            <artifactId>gremlin-annotations</artifactId>
+                            <version>${project.version}</version>
+                        </path>
+                        <path>
+                            <groupId>org.apache.tinkerpop</groupId>
+                            <artifactId>gremlin-core</artifactId>
+                            <version>${project.version}</version>
+                        </path>
+                        <path>
+                            <groupId>org.apache.tinkerpop</groupId>
+                            <artifactId>gremlin-shaded</artifactId>
+                            <version>${project.version}</version>
+                        </path>
+                        <path>
+                            <groupId>org.apache.tinkerpop</groupId>
+                            <artifactId>gremlin-language</artifactId>
+                            <version>${project.version}</version>
+                        </path>
+                        <path>
+                            <groupId>com.squareup</groupId>
+                            <artifactId>javapoet</artifactId>
+                            <version>${javapoet.version}</version>
+                        </path>
+                        <path>
+                            <groupId>org.antlr</groupId>
+                            <artifactId>antlr4-runtime</artifactId>
+                            <version>${antlr4.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
                 </configuration>
             </plugin>
         </plugins>
@@ -155,9 +187,9 @@ limitations under the License.
 
     <profiles>
         <profile>
-            <id>jdk11</id>
+            <id>jdk11-and-newer</id>
             <activation>
-                <jdk>[11,18)</jdk>
+                <jdk>[11,)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -167,8 +199,8 @@ limitations under the License.
                         <configuration>
                             <!--
                             need to override source path as we don't seem to 
get the groovy-stubs automatically. this worked
-                            under java 8 but errors under java 11 due to 
missing files on the path. i guess java 8 was more
-                            forgiving.
+                            under java 8 but errors under java 11 and newer 
due to missing files on the path. i guess java 8
+                            was more forgiving.
                             -->
                             
<sourcepath>${pom.basedir}/src/main/java:${project.build.directory}/generated-sources/annotations:${project.build.directory}/generated-sources/groovy-stubs/main</sourcepath>
                         </configuration>
diff --git a/gremlin-server/Dockerfile b/gremlin-server/Dockerfile
index 63a494d63b..7eb7a58003 100644
--- a/gremlin-server/Dockerfile
+++ b/gremlin-server/Dockerfile
@@ -24,7 +24,7 @@ ARG GREMLIN_SERVER_DIR
 RUN apk add --no-cache --update \
     bash \
     perl \
-    openjdk11-jdk
+    openjdk17-jdk
 
 COPY src/main/docker/docker-entrypoint.sh /
 COPY ${GREMLIN_SERVER_DIR} /opt/gremlin-server
diff --git a/gremlin-server/src/main/bin/gremlin-server.sh 
b/gremlin-server/src/main/bin/gremlin-server.sh
index 430a18c398..438daf1ca6 100755
--- a/gremlin-server/src/main/bin/gremlin-server.sh
+++ b/gremlin-server/src/main/bin/gremlin-server.sh
@@ -94,6 +94,25 @@ if [[ "$JAVA_OPTIONS" = "" ]] ; then
     JAVA_OPTIONS="-Xms512m -Xmx4096m"
 fi
 
+# These options are required for libraries that still rely on deep reflection 
(notably Kryo, used by Gryo) to work on
+# Java 17 and newer, where such access into java.base is denied by default. 
They mirror the jdk17JvmArgs used by the
+# build (see the root pom.xml) and are always appended so they apply even when 
JAVA_OPTIONS is overridden.
+JAVA_OPTIONS="$JAVA_OPTIONS \
+-XX:+IgnoreUnrecognizedVMOptions \
+--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
+--add-exports=java.base/sun.security.x509=ALL-UNNAMED \
+--add-exports=java.base/sun.security.action=ALL-UNNAMED \
+--add-opens=java.base/java.io=ALL-UNNAMED \
+--add-opens=java.base/java.nio=ALL-UNNAMED \
+--add-opens=java.base/sun.nio.cs=ALL-UNNAMED \
+--add-opens=java.base/java.lang=ALL-UNNAMED \
+--add-opens=java.base/java.lang.invoke=ALL-UNNAMED \
+--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
+--add-opens=java.base/java.util=ALL-UNNAMED \
+--add-opens=java.base/java.util.concurrent=ALL-UNNAMED \
+--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED \
+--add-opens=java.base/java.net=ALL-UNNAMED"
+
 # Build Java CLASSPATH
 CP="$GREMLIN_HOME/conf/"
 CP="$CP":$( find "$GREMLIN_HOME/lib" -name "*.jar" -print | tr '\n' ':' ).
diff --git 
a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java
 
b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java
index a8ae0b860f..2e73cca38e 100644
--- 
a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java
+++ 
b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java
@@ -261,7 +261,9 @@ public class GremlinServerSslIntegrateTest extends 
AbstractGremlinServerIntegrat
             client.submit("g.inject('test')").one();
             fail("Should throw exception because ssl client auth is enabled on 
the server but client does not have a cert");
         } catch (Exception x) {
-            assertSslException(x, "bad_certificate");
+            // Under TLS 1.3 (default on Java 17+) a client-certificate 
rejection may reach the client as the specific
+            // alert or, depending on handshake timing, as a generic 
engine-closed error.
+            assertSslException(x, "bad_certificate", "certificate_required", 
"SSLEngine closed already");
         } finally {
             cluster.close();
         }
@@ -277,7 +279,9 @@ public class GremlinServerSslIntegrateTest extends 
AbstractGremlinServerIntegrat
             client.submit("g.inject('test')").one();
             fail("Should throw exception because ssl client auth is enabled on 
the server but does not trust client's cert");
         } catch (Exception x) {
-            assertSslException(x, "bad_certificate");
+            // Under TLS 1.3 (default on Java 17+) a client-certificate 
rejection may reach the client as the specific
+            // alert or, depending on handshake timing, as a generic 
engine-closed error.
+            assertSslException(x, "bad_certificate", "certificate_required", 
"SSLEngine closed already");
         } finally {
             cluster.close();
         }
@@ -343,10 +347,16 @@ public class GremlinServerSslIntegrateTest extends 
AbstractGremlinServerIntegrat
         }
     }
 
-    private static void assertSslException(Exception x, String 
expectedSubstring) {
+    private static void assertSslException(final Exception x, final String... 
acceptableSubstrings) {
         logger.warn("Exception caught: {}", x.getMessage(), x);
         final Throwable root = ExceptionHelper.getRootCause(x);
         assertThat(root, instanceOf(SSLException.class));
-        assertThat(root.getMessage(), containsString(expectedSubstring));
+        final String message = root.getMessage();
+        // The exact TLS alert can vary by JDK/TLS version (for example a 
missing client certificate is reported as
+        // "bad_certificate" under TLS 1.2 but "certificate_required" under 
the TLS 1.3 that is default on Java 17+),
+        // so accept any of the provided substrings.
+        final boolean matched = message != null && 
Arrays.stream(acceptableSubstrings).anyMatch(message::contains);
+        assertThat("Expected SSL exception message <" + message + "> to 
contain one of " +
+                Arrays.toString(acceptableSubstrings), matched, is(true));
     }
 }
diff --git a/gremlin-tools/gremlin-socket-server/Dockerfile 
b/gremlin-tools/gremlin-socket-server/Dockerfile
index 3010f33cd6..f40c91a66d 100644
--- a/gremlin-tools/gremlin-socket-server/Dockerfile
+++ b/gremlin-tools/gremlin-socket-server/Dockerfile
@@ -24,7 +24,7 @@ ARG SOCKET_SERVER_VERSION
 
 RUN apk add --no-cache --update \
     bash \
-    openjdk11-jdk
+    openjdk17-jdk
 
 COPY ${SOCKET_SERVER_DIR}/gremlin-socket-server-${SOCKET_SERVER_VERSION}.jar 
/opt/gremlin-socket-server/gremlin-socket-server.jar
 COPY ${SOCKET_SERVER_DIR}/libs/ /opt/gremlin-socket-server/libs/
diff --git a/pom.xml b/pom.xml
index 9f4b908127..8f426fc504 100644
--- a/pom.xml
+++ b/pom.xml
@@ -159,7 +159,7 @@ limitations under the License.
         <commons.text.version>1.15.0</commons.text.version>
         <cucumber.version>7.21.1</cucumber.version>
         <exp4j.version>0.4.8</exp4j.version>
-        <groovy.version>4.0.25</groovy.version>
+        <groovy.version>4.0.32</groovy.version>
         <!--
           don't really use guava directly, but there are a lot of jar 
conflicts around it,
           so centralizing that dependency version here
@@ -170,7 +170,7 @@ limitations under the License.
           it supports the jakarta.inject namespace which tinkerpop doesn't 
fuss with
         -->
         <guice.version>6.0.0</guice.version>
-        <hadoop.version>3.4.2</hadoop.version>
+        <hadoop.version>3.4.3</hadoop.version>
         <hamcrest.version>3.0</hamcrest.version>
         <java.tuples.version>1.2</java.tuples.version>
         <javadoc-plugin.version>3.3.1</javadoc-plugin.version>
@@ -180,10 +180,10 @@ limitations under the License.
         <logback.version>1.3.15</logback.version>
         <metrics.version>3.0.2</metrics.version>
         <mockito.version>5.19.0</mockito.version>
-        <netty.version>4.1.125.Final</netty.version>
+        <netty.version>4.2.7.Final</netty.version>
         <slf4j.version>2.0.16</slf4j.version>
         <snakeyaml.version>2.0</snakeyaml.version>
-        <spark.version>3.5.4</spark.version>
+        <spark.version>4.1.2</spark.version>
         <awssdk.version>2.29.3</awssdk.version>
         <!-- Version aligned with Netty's optional bcpkix dependency used for 
SelfSignedCertificate -->
         <bouncycastle.version>1.69</bouncycastle.version>
@@ -259,7 +259,7 @@ limitations under the License.
                             <rules>
                                 <DependencyConvergence/>
                                 <requireJavaVersion>
-                                    <version>[11,18)</version>
+                                    <version>[17,26)</version>
                                 </requireJavaVersion>
                                 <requireMavenVersion>
                                     <version>[3.5.3,)</version>
@@ -624,9 +624,9 @@ limitations under the License.
                     <artifactId>maven-compiler-plugin</artifactId>
                     <version>3.14.0</version>
                     <configuration>
-                        <release>11</release>
-                        <source>11</source>
-                        <target>11</target>
+                        <release>17</release>
+                        <source>17</source>
+                        <target>17</target>
                         <compilerArgs>
                             <arg>-parameters</arg>
                         </compilerArgs>
@@ -733,7 +733,7 @@ limitations under the License.
                     <artifactId>maven-javadoc-plugin</artifactId>
                     <version>${javadoc-plugin.version}</version>
                     <configuration>
-                        <source>11</source>
+                        <source>17</source>
                     </configuration>
                 </plugin>
                 <plugin>
@@ -741,7 +741,7 @@ limitations under the License.
                     <artifactId>gmavenplus-plugin</artifactId>
                     <version>4.1.1</version>
                     <configuration>
-                        <targetBytecode>11</targetBytecode>
+                        <targetBytecode>17</targetBytecode>
                     </configuration>
                 </plugin>
                 <plugin>
@@ -2203,7 +2203,7 @@ limitations under the License.
                                 -Dlog4j.configuration=${log4j-test.properties}
                                 
-Dslf4j.provider=ch.qos.logback.classic.spi.LogbackServiceProvider
                                 -Dbuild.dir=${project.build.directory} 
-Dis.testing=true ${suresafeArgs}
-                                -Djava.net.preferIPv4Stack=true
+                                -Djava.net.preferIPv4Stack=true ${jdk17JvmArgs}
                             </argLine>
                         </configuration>
                     </plugin>
@@ -2215,7 +2215,7 @@ limitations under the License.
                                 -Dlog4j.configuration=${log4j-test.properties} 
-Dhost=localhost -Dport=8182
                                 
-Dslf4j.provider=ch.qos.logback.classic.spi.LogbackServiceProvider
                                 -Dbuild.dir=${project.build.directory} 
-Dis.testing=true ${suresafeArgs}
-                                -Djava.net.preferIPv4Stack=true
+                                -Djava.net.preferIPv4Stack=true ${jdk17JvmArgs}
                             </argLine>
                         </configuration>
                     </plugin>
diff --git a/spark-gremlin/pom.xml b/spark-gremlin/pom.xml
index ce0eff687e..0b2917997d 100644
--- a/spark-gremlin/pom.xml
+++ b/spark-gremlin/pom.xml
@@ -25,6 +25,42 @@ limitations under the License.
     </parent>
     <artifactId>spark-gremlin</artifactId>
     <name>Apache TinkerPop :: Spark Gremlin</name>
+    <dependencyManagement>
+        <dependencies>
+            <!-- Align every jackson artifact with the version Spark 4.x is 
built against; its bundled
+                 jackson-module-scala requires a matching jackson-databind. 
The BOM also resolves the version skew
+                 between jackson-databind/core and jackson-annotations. -->
+            <dependency>
+                <groupId>com.fasterxml.jackson</groupId>
+                <artifactId>jackson-bom</artifactId>
+                <version>2.21.2</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <!-- Spark 4.1.x and Hadoop pull in conflicting versions of these 
transitive dependencies; pin each to a
+                 single version so that dependency convergence is satisfied -->
+            <dependency>
+                <groupId>com.thoughtworks.paranamer</groupId>
+                <artifactId>paranamer</artifactId>
+                <version>2.8.3</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.servlet</groupId>
+                <artifactId>javax.servlet-api</artifactId>
+                <version>4.0.1</version>
+            </dependency>
+            <dependency>
+                <groupId>org.bouncycastle</groupId>
+                <artifactId>bcprov-jdk18on</artifactId>
+                <version>1.82</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.xml.bind</groupId>
+                <artifactId>jaxb-api</artifactId>
+                <version>2.2.12</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>org.apache.tinkerpop</groupId>
@@ -105,7 +141,7 @@ limitations under the License.
         <!-- SPARK -->
         <dependency>
             <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_2.12</artifactId>
+            <artifactId>spark-core_2.13</artifactId>
             <version>${spark.version}</version>
             <exclusions>
                 <!-- prefer hadoop protobuf -->
@@ -195,7 +231,7 @@ limitations under the License.
         <dependency>
             <groupId>io.dropwizard.metrics</groupId>
             <artifactId>metrics-core</artifactId>
-            <version>4.2.19</version>
+            <version>4.2.37</version>
         </dependency>
         <dependency>
             <groupId>org.apache.curator</groupId>
@@ -244,23 +280,20 @@ limitations under the License.
         <dependency>
             <groupId>org.scala-lang</groupId>
             <artifactId>scala-library</artifactId>
-            <version>2.12.15</version>
+            <version>2.13.17</version>
         </dependency>
-        <!-- use jackson 2.13.5 to fit better with spark 2.3.3 where Scala 
module 2.13.4 requires Jackson Databind version >= 2.13.0 and < 2.14.0 -->
+        <!-- jackson versions are managed by the jackson-bom import above so 
that they match Spark 4.x -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
-            <version>2.15.4</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
-            <version>2.15.4</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
-            <version>2.15.4</version>
         </dependency>
         <!-- TEST -->
         <dependency>
@@ -366,7 +399,7 @@ limitations under the License.
                     <archive>
                         <manifestEntries>
                             <Gremlin-Plugin-Dependencies>
-                                
org.apache.hadoop:hadoop-client:${hadoop.version};org.apache.hadoop:hadoop-yarn-server-web-proxy:${hadoop.version};org.apache.spark:spark-yarn_2.12:${spark.version}
+                                
org.apache.hadoop:hadoop-client:${hadoop.version};org.apache.hadoop:hadoop-yarn-server-web-proxy:${hadoop.version};org.apache.spark:spark-yarn_2.13:${spark.version}
                             </Gremlin-Plugin-Dependencies>
                         </manifestEntries>
                     </archive>
diff --git 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/Spark.java
 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/Spark.java
index 694b25e382..afb3ff62a0 100644
--- 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/Spark.java
+++ 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/Spark.java
@@ -23,7 +23,7 @@ import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.SparkConf;
 import org.apache.spark.SparkContext;
 import org.apache.spark.rdd.RDD;
-import scala.collection.JavaConversions;
+import scala.jdk.javaapi.CollectionConverters;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -108,7 +108,7 @@ public class Spark {
             recreateStopped();
 
         final Set<String> keepNames = new HashSet<>();
-        for (final RDD<?> rdd : 
JavaConversions.asJavaIterable(CONTEXT.persistentRdds().values())) {
+        for (final RDD<?> rdd : 
CollectionConverters.asJava(CONTEXT.persistentRdds().values())) {
             if (null != rdd.name()) {
                 keepNames.add(rdd.name());
                 NAME_TO_RDD.put(rdd.name(), rdd);
diff --git 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoRegistrator.java
 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoRegistrator.java
index 4cf871d0e9..705d883a73 100644
--- 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoRegistrator.java
+++ 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoRegistrator.java
@@ -51,7 +51,7 @@ import org.apache.tinkerpop.gremlin.util.SystemUtil;
 import org.javatuples.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import scala.collection.mutable.WrappedArray;
+import scala.collection.immutable.ArraySeq;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -206,7 +206,7 @@ public class GryoRegistrator implements KryoRegistrator {
         } catch (final ClassNotFoundException e) {
             throw new IllegalStateException(e.getMessage(), e);
         }
-        m.put(WrappedArray.ofRef.class, null);
+        m.put(ArraySeq.ofRef.class, null);
         m.put(MessagePayload.class, null);
         m.put(ViewIncomingPayload.class, null);
         m.put(ViewOutgoingPayload.class, null);
diff --git 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializer.java
 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializer.java
index 58fa16bcac..35f631703d 100644
--- 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializer.java
+++ 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializer.java
@@ -51,7 +51,7 @@ import 
org.apache.tinkerpop.shaded.kryo.serializers.ExternalizableSerializer;
 import org.apache.tinkerpop.shaded.kryo.serializers.JavaSerializer;
 import scala.Tuple2;
 import scala.Tuple3;
-import scala.collection.mutable.WrappedArray;
+import scala.collection.immutable.ArraySeq;
 import scala.runtime.BoxedUnit;
 
 import java.io.Serializable;
@@ -147,7 +147,7 @@ public final class GryoSerializer extends Serializer 
implements Serializable {
                 super.register(GryoIo.class, Class.forName("scala.None$"), new 
JavaSerializer());
                 super.register(GryoIo.class, Class.forName("scala.Some$"), new 
JavaSerializer());
                 super.register(GryoIo.class, Class.forName("scala.Some"), new 
JavaSerializer());
-                super.register(GryoIo.class, WrappedArray.ofRef.class, new 
WrappedArraySerializer());
+                super.register(GryoIo.class, ArraySeq.ofRef.class, new 
WrappedArraySerializer());
                 super.register(GryoIo.class, MessagePayload.class, null);
                 super.register(GryoIo.class, ViewIncomingPayload.class, null);
                 super.register(GryoIo.class, ViewOutgoingPayload.class, null);
diff --git 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/WrappedArraySerializer.java
 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/WrappedArraySerializer.java
index 1de17f1a90..8d6be792f2 100644
--- 
a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/WrappedArraySerializer.java
+++ 
b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/WrappedArraySerializer.java
@@ -23,29 +23,32 @@ import org.apache.tinkerpop.shaded.kryo.Kryo;
 import org.apache.tinkerpop.shaded.kryo.Serializer;
 import org.apache.tinkerpop.shaded.kryo.io.Input;
 import org.apache.tinkerpop.shaded.kryo.io.Output;
-import scala.collection.JavaConversions;
-import scala.collection.mutable.WrappedArray;
+import scala.collection.immutable.ArraySeq;
 
 /**
+ * Serializer for Scala's immutable {@link ArraySeq}. In Scala 2.13 (the Scala 
version Spark is built against) wrapping
+ * a reference array produces an {@code immutable.ArraySeq.ofRef}, which 
replaced the {@code WrappedArray} used under
+ * Scala 2.12.
+ *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class WrappedArraySerializer<T> extends 
Serializer<WrappedArray<T>> {
+public final class WrappedArraySerializer<T> extends Serializer<ArraySeq<T>> {
 
     @Override
-    public void write(final Kryo kryo, final Output output, final 
WrappedArray<T> iterable) {
+    public void write(final Kryo kryo, final Output output, final ArraySeq<T> 
iterable) {
         output.writeVarInt(iterable.size(), true);
-        JavaConversions.asJavaCollection(iterable).forEach(t -> {
-            kryo.writeClassAndObject(output, t);
-        });
+        for (int i = 0; i < iterable.size(); i++) {
+            kryo.writeClassAndObject(output, iterable.apply(i));
+        }
     }
 
     @Override
-    public WrappedArray<T> read(final Kryo kryo, final Input input, final 
Class<WrappedArray<T>> aClass) {
+    public ArraySeq<T> read(final Kryo kryo, final Input input, final 
Class<ArraySeq<T>> aClass) {
         final int size = input.readVarInt(true);
         final Object[] array = new Object[size];
         for (int i = 0; i < size; i++) {
             array[i] = kryo.readClassAndObject(input);
         }
-        return new WrappedArray.ofRef<>((T[]) array);
+        return new ArraySeq.ofRef<>((T[]) array);
     }
 }
diff --git 
a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
 
b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
index d77f359ccc..59e87ee473 100644
--- 
a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
+++ 
b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
@@ -38,7 +38,7 @@ import 
org.apache.tinkerpop.gremlin.spark.structure.io.gryo.GryoSerializer;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
 import org.junit.Test;
-import scala.collection.JavaConversions;
+import scala.jdk.javaapi.CollectionConverters;
 
 import java.io.File;
 
@@ -112,7 +112,7 @@ public class SparkTest extends AbstractSparkTest {
     }
 
     private static boolean hasPersistedRDD(final String name) {
-        for (final RDD<?> rdd : 
JavaConversions.asJavaIterable(Spark.getContext().persistentRdds().values())) {
+        for (final RDD<?> rdd : 
CollectionConverters.asJava(Spark.getContext().persistentRdds().values())) {
             if (null != rdd.name() && rdd.name().equals(name))
                 return true;
         }
@@ -121,7 +121,7 @@ public class SparkTest extends AbstractSparkTest {
 
     private static int getPersistedRDDSize() {
         int counter = 0;
-        for (final RDD<?> rdd : 
JavaConversions.asJavaIterable(Spark.getContext().persistentRdds().values())) {
+        for (final RDD<?> rdd : 
CollectionConverters.asJava(Spark.getContext().persistentRdds().values())) {
             if (null != rdd.name())
                 counter++;
         }

Reply via email to