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()); + } +}
