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

valentyn pushed a commit to branch TINKERPOP-3163
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 64b90139d923dceacdfa951bef75c5d098b2f3dd
Author: Valentyn Kahamlyk <[email protected]>
AuthorDate: Mon Jun 23 10:54:12 2025 -0700

    fixed CallStep serialization
---
 CHANGELOG.asciidoc                                 |  1 +
 .../process/traversal/step/map/CallStep.java       | 21 ++++++------
 .../process/traversal/step/map/CallStepTest.java   | 40 ++++++++++++++++++++++
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index eaf17bd912..f526c9e09f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -45,6 +45,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Changed `PythonTranslator` to generate snake case step naming instead of 
camel case.
 * Changed `gremlin-go` Client `ReadBufferSize` and `WriteBufferSize` defaults 
to 1048576 (1MB) to align with DriverRemoteConnection.
 * Fixed bug in `IndexStep` which prevented Java serialization due to 
non-serializable lambda usage by creating serializable function classes.
+* Fixed bug in `CallStep` which prevented Java serialization due to 
non-serializable `ServiceCallContext` and `Service` usage.
 * Fixed bug in `Operator` which was caused only a single method parameter to 
be Collection type checked instead of all parameters.
 * Support hot reloading of SSL certificates.
 * Added the `PopContaining` interface designed to get label and `Pop` 
combinations held in a `PopInstruction` object.
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
index 2435be373c..758c318869 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
@@ -59,10 +59,10 @@ public final class CallStep<S, E> extends AbstractStep<S, 
E> implements Traversa
     private final boolean isStart;
     private boolean first = true;
 
-    private ServiceCallContext ctx;
-    private String serviceName;
-    private Service<S, E> service;
-    private Map staticParams;
+    private transient ServiceCallContext ctx;
+    private final String serviceName;
+    private transient Service<S, E> service;
+    private final Map staticParams;
     private Traversal.Admin<S,Map> mapTraversal;
     private Parameters parameters;
 
@@ -90,7 +90,6 @@ public final class CallStep<S, E> extends AbstractStep<S, E> 
implements Traversa
         this.staticParams = staticParams == null ? new LinkedHashMap() : 
staticParams;
         this.mapTraversal = mapTraversal == null ? null : 
integrateChild(mapTraversal);
         this.parameters = new Parameters();
-        this.ctx = new ServiceCallContext(traversal, this);
     }
 
     protected Service<S, E> service() {
@@ -98,6 +97,10 @@ public final class CallStep<S, E> extends AbstractStep<S, E> 
implements Traversa
         return service != null ? service : (service = 
getServiceRegistry().get(serviceName, isStart, staticParams));
     }
 
+    private ServiceCallContext ctx() {
+        return ctx != null ? ctx : (ctx = new ServiceCallContext(traversal, 
this));
+    }
+
     public String getServiceName() {
         return serviceName;
     }
@@ -244,17 +247,17 @@ public final class CallStep<S, E> extends AbstractStep<S, 
E> implements Traversa
 
     protected CloseableIterator start() {
         final Map params = getMergedParams();
-        return service().execute(this.ctx, params);
+        return service().execute(this.ctx(), params);
     }
 
     protected CloseableIterator flatMap(final Traverser.Admin<S> traverser) {
         final Map params = getMergedParams(traverser);
-        return service().execute(this.ctx, traverser, params);
+        return service().execute(this.ctx(), traverser, params);
     }
 
     protected CloseableIterator flatMap(final TraverserSet<S> traverserSet) {
         final Map params = getMergedParams(traverserSet);
-        return service().execute(this.ctx, traverserSet, params);
+        return service().execute(this.ctx(), traverserSet, params);
     }
 
     protected ServiceRegistry getServiceRegistry() {
@@ -288,7 +291,6 @@ public final class CallStep<S, E> extends AbstractStep<S, 
E> implements Traversa
         if (mapTraversal != null)
             this.integrateChild(mapTraversal);
         parameters.getTraversals().forEach(this::integrateChild);
-        ctx = new ServiceCallContext(parentTraversal, this);
     }
 
     @Override
@@ -328,7 +330,6 @@ public final class CallStep<S, E> extends AbstractStep<S, 
E> implements Traversa
         final CallStep<S, E> clone = (CallStep<S, E>) super.clone();
         clone.mapTraversal = mapTraversal != null ? mapTraversal.clone() : 
null;
         clone.parameters = parameters.clone();
-        clone.ctx = new ServiceCallContext(traversal, clone);
         clone.iterator = EmptyCloseableIterator.instance();
         clone.head = null;
         return clone;
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStepTest.java
new file mode 100644
index 0000000000..a981cb61aa
--- /dev/null
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStepTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class CallStepTest {
+
+    @Test
+    public void testSerializationRoundTrip() {
+        final byte[] serialized = 
SerializationUtils.serialize(__.call("--list"));
+        final DefaultTraversal<Object, Object> deserialized = 
SerializationUtils.deserialize(serialized);
+
+        assertEquals(1, deserialized.getSteps().size());
+        assertTrue(deserialized.getSteps().get(0) instanceof CallStep);
+        assertEquals("--list", ((CallStep) 
deserialized.getSteps().get(0)).getServiceName());
+    }
+}

Reply via email to