Merge branch '3.4-dev'
diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000..178eb48
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,11 @@
+github:
+  description: "Apache TinkerPop - a graph computing framework"
+  homepage: https://tinkerpop.apache.org/
+  labels:
+    - tinkerpop
+    - gremlin
+    - graph
+    - graphdb
+    - graph-database
+    - gremlin-server
+    - apache
\ No newline at end of file
diff --git a/.dependabot/config.yml b/.dependabot/config.yml
new file mode 100644
index 0000000..0871a00
--- /dev/null
+++ b/.dependabot/config.yml
@@ -0,0 +1,10 @@
+version: 1
+update_configs:
+  - package_manager: "java:maven"
+    directory: "/"
+    update_schedule: "monthly"
+    allowed_updates:
+      - match:
+          update_type: "security"
+      - match:
+          dependency_name: "org.apache.tinkerpop:die-dependabot"
diff --git a/.gitignore b/.gitignore
index 1db44b9..b2ce127 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
 .classpath
 .project
 .settings
+.factorypath
 _bsp/
 doc/out
 docs/*.asciidoc
diff --git a/.travis.yml b/.travis.yml
index 19050c3..2954c74 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,9 +2,9 @@
 os:
   - linux
 jdk:
-  - openjdk8
+  - openjdk11
 sudo: required
-dist: xenial
+dist: bionic
 services:
   - docker
 cache:
@@ -36,12 +36,13 @@
   - sudo apt install python3.6
   - sudo rm /usr/bin/python3
   - sudo ln -s python3.6 /usr/bin/python3
+  - sudo apt install gcc python3.6-dev libkrb5-dev
 
 jobs:
   include:
     - stage: "tests"
       script: "mvn clean install -Dci --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn"
-      name: "mvn clean install"
+      name: "mvn clean install - jdk11"
     - script: "touch gremlin-dotnet/src/.glv && touch gremlin-dotnet/test/.glv && mvn clean install -q -DskipTests -Dci && mvn verify -pl :gremlin-dotnet,:gremlin-dotnet-tests -P gremlin-dotnet"
       name: ".net"
     - script: "touch gremlin-python/.glv && mvn clean install -q -DskipTests -Dci && mvn verify -pl gremlin-python"
@@ -49,8 +50,13 @@
     - script: "mvn clean install -q -DskipTests -Dci && mvn verify -pl :gremlin-javascript"
       name: "javascript"
     - script:
-      - "mvn clean install -q -DskipTests -Dci"
-      - "mvn verify -pl :gremlin-server -DskipTests -DskipIntegrationTests=false -DincludeNeo4j"
+        - "mvn -version"
+        - "mvn clean install -Dci --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn"
+      jdk: openjdk8
+      name: "mvn clean install - jdk8"
+    - script:
+        - "mvn clean install -q -DskipTests -Dci"
+        - "mvn verify -pl :gremlin-server -DskipTests -DskipIntegrationTests=false -DincludeNeo4j"
       name: "gremlin server"
     - script:
         - "mvn clean install -q -DskipTests -Dci"
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index a1d822d..03a5268 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -16,6 +16,73 @@
 ////
 = TinkerPop3 CHANGELOG
 
+== TinkerPop 3.5.0 (The Sleeping Gremlin: No. 18 Entr'acte symphonique)
+
+image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/gremlin-sleeping-beauty.png[width=185]
+
+[[release-3-5-0]]
+=== TinkerPop 3.5.0 (Release Date: NOT OFFICIALLY RELEASED YET)
+
+This release also includes changes from <<release-3-4-3, 3.4.3>>.
+
+* Allowed the possibility for the propagation of `null` as a `Traverser` in Gremlin.
+* Fixed a bug where spark-gremlin was not re-attaching properties when using `dedup()`.
+* Ensured better consistency of the use of `null` as arguments to mutation steps.
+* Allowed `property(T.label,Object)` to be used if no value was supplied to `addV(String)`.
+* Allowed additional arguments to `Client.submit()` in Javascript driver to enable setting of parameters like `scriptEvaluationTimeout`.
+* Supported deserialization of `dict` as a key in a `dict` for Python.
+* Added a `Graph.Feature` for `supportsNullPropertyValues`.
+* Modified `TokenTraversal` to support `Property` thus `by(key)` and `by(value)` can now apply to `Edge` and meta-properties.
+* Added `SeedStrategy` to allow deterministic behavior for `coin()`, `sample()` and `Order.shuffle`.
+* Added `Grouping` step interface.
+* Added `TraversalParent.replaceTraversal()` which can replace a direct child traversal.
+* Added `ByModulatorOptimizationStrategy` which replaces certain standard traversals w/ optimized traversals (e.g. `TokenTraversal`).
+* Refactored `MapStep` to move its logic to `ScalarMapStep` so that the old behavior could be preserved while allow other implementations to have more flexibility.
+* Modified TinkerGraph to support `null` property values and can be configured to disable that feature.
+* Modified `null` handling in mutations to be consistent for a new `Vertex` as well as update to an existing one.
+* Enforced use of anonymous child traversals.
+* Removed support for Python 2.x in gremlinpython.
+* Upgraded to Apache Commons Configuration2.
+* Renamed `StoreStep` to `AggregateLocalStep`.
+* Renamed `AggregateStep` to `AggregateGlobalStep`.
+* Renamed `SERVER_ERROR_SCRIPT_EVALUATION` to `SERVER_ERROR_EVALUATION` given that this response code applies to remote traversals as well as scripts.
+* Refactored `TraversalStrategies` to implement `Iterable`.
+* Refactored `Traversal` semantics to always expect `EmptyStep` as a parent if it is meant to be the root `Traversal`.
+* Configured GraphBinary as the default binary serialization format for the Java Driver.
+* Configured GraphSON 3.0 as the default text serialization format when no serializer can be determined.
+* Configured GraphSON 3.0 as the default setting for the `GraphSONMapper`.
+* Bumped to Neo4j 3.4.11.
+* Bumped to Spark 3.0.0.
+* Bumped to Groovy 3.0.3.
+* Bumped to Jackson 2.11.x.
+* Supported build for Java 11.
+* Added a parameterized `TypeTranslator` for use with `GroovyTranslator` that should produce more cache hits.
+* Added support for `TextP` in Neo4j using its string search functions.
+* Added a kerberos KDC to the docker container for testing GLV's.
+* Added kerberos authentication to Gremlin-Python.
+* Added audit logging to bytecode-based traversals.
+* Changed `TraversalStrategy` application methodology to apply each strategy in turn to each level of the traversal hierarchy starting from root down to children.
+* Prevented more than one `Client` from connecting to the same Gremlin Server session.
+* Removed internal functionality for the session close message in Gremlin Server - the message is accepted but ignored if sent.
+* Removed `Property.Exceptions.propertyValueCanNotBeNull` exception type as `null` now has meaning in Gremlin.
+* Removed the "experimental" support for multi/meta-properties in Neo4j.
+* Removed Gryo serialization configurations from Gremlin Server sample configurations and default configurations.
+* Removed previously deprecated `Cluster.maxWaitForSessionClose` configuration option.
+* Removed previously deprecated `TraversalStrategies.applyStrategies()`.
+* Removed previously deprecated `scriptEvaluationTimeout`.
+* Removed previously deprecated `NioChannelizer` and related classes.
+* Removed previously deprecated remote traversal side-effects and related infrastructure.
+* Removed previously deprecated `Serializers.DEFAULT_RESULT_SERIALIZER` and `Serializers.DEFAULT_REQUEST_SERIALIZER`.
+* Removed previously deprecated `decr` and `incr` from `Order`.
+* Removed previously deprecated `TraversalSource.withRemote()`.
+* Removed previously deprecated `ResponseHandlerContext` infrastructure.
+* Removed previously deprecated `VertexProgram` related infrastructure.
+* Removed previously deprecated SSL settings: `keyCertChainFile`, `keyFile`, `keyPassword` and `trustCertChainFile` and related infrastructure.
+* Removed previously deprecated `PropertyMapStep` constructor and `isIncludeTokens`.
+* Removed previously deprecated `StarGraph.builder()` and `StarGraph.Builder.create()`.
+* Removed previously deprecated `AbstractOpProcessor.generateMetaData(ChannelHandlerContext, RequestMessage, ResponseStatusCode, Iterator)`
+* Removed previously deprecated `BulkDumperVertexProgram` and `BulkLoaderVertexProgram`.
+
 == TinkerPop 3.4.0 (Avant-Gremlin Construction #3 for Theremin and Flowers)
 
 image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/avant-gremlin.png[width=185]
@@ -833,6 +900,8 @@
 * Bumped `httpclient` to 4.5.7.
 * Bumped `slf4j` to 1.7.25.
 * Bumped `commons-codec` to 1.12.
+* Bumped to Groovy 2.5.6.
+* Bumped to Hadoop 2.7.7.
 * Fixed partial response failures when using authentication in `gremlin-python`.
 * Fixed concurrency issues in `TraverserSet.toString()` and `ObjectWritable.toString()`.
 * Fixed a bug in `InlineFilterStrategy` that mixed up and's and or's when folding merging conditions together.
diff --git a/README.asciidoc b/README.asciidoc
index 4f8e659..3f2367d 100644
--- a/README.asciidoc
+++ b/README.asciidoc
@@ -29,7 +29,7 @@
 
 === Building and Testing
 
-TinkerPop uses link:https://maven.apache.org/[Maven] and requires `Java 1.8.0_40+` for proper building and proper operations. To build, execute unit tests and package Gremlin Console/Server run:
+TinkerPop uses link:https://maven.apache.org/[Maven] and requires `Java 11` for proper building and proper operations. To build, execute unit tests and package Gremlin Console/Server run:
 
 [source,bash]
 mvn clean install
diff --git a/bin/gephi-mock.py b/bin/gephi-mock.py
index 85501e6..1018677 100755
--- a/bin/gephi-mock.py
+++ b/bin/gephi-mock.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 #
 # Licensed to the Apache Software Foundation (ASF) under one
@@ -19,7 +19,7 @@
 # under the License.
 #
 
-from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+from http.server import BaseHTTPRequestHandler, HTTPServer
 
 
 class GephiHandler(BaseHTTPRequestHandler):
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d997be6..e5bae33 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -25,7 +25,7 @@
 RUN sh -c 'curl -s https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb -o packages-microsoft-prod.deb'
 RUN sh -c 'dpkg -i packages-microsoft-prod.deb'
 RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
-RUN apt-get install apt-transport-https ca-certificates
+RUN apt-get install apt-transport-https gnupg ca-certificates
 RUN sh -c 'echo "deb https://download.mono-project.com/repo/ubuntu stable-xenial main" | tee /etc/apt/sources.list.d/mono-official-stable.list'
 RUN apt-get update
 
@@ -38,7 +38,9 @@
 # custom build and install 3.5.3 and upgrade pip along the way. this could be resolved by using bionic
 # but trying to keep all of our release branches on the same docker image and the older versions sorta
 # suit 3.3.x and 3.4.x
-RUN apt-get install -y --force-yes python python-dev python-pip build-essential checkinstall zlib1g-dev libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt-get install -y python python-dev python-pip build-essential checkinstall zlib1g-dev libreadline-gplv2-dev \
+    libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libkrb5-dev krb5-user
 RUN cd /opt && wget https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tgz && tar -xvf Python-3.5.3.tgz
 RUN cd /opt/Python-3.5.3 && ./configure && make && make install
 RUN ln -sf /usr/bin/python3.5.3 /usr/bin/python3
diff --git a/docker/gremlin-server.sh b/docker/gremlin-server.sh
index ee8d111..9d91da7 100755
--- a/docker/gremlin-server.sh
+++ b/docker/gremlin-server.sh
@@ -25,6 +25,7 @@
 
 DIR=`dirname $0`
 PROJECT_HOME=${DIR}/../
+ABS_PROJECT_HOME=$(dirname $(realpath $0))/..
 
 TIMESTAMP=$(date +%s)
 BUILD_TAG="gremlin-server-test-${TIMESTAMP}"
@@ -57,7 +58,8 @@
 sed -e "s/GREMLIN_SERVER_VERSION\$/${GREMLIN_SERVER_VERSION}/" docker/gremlin-server/Dockerfile.template > Dockerfile
 
 docker build -t tinkerpop:${BUILD_TAG} .
-docker run ${TINKERPOP_TEST_DOCKER_OPTS} ${REMOVE_CONTAINER} -ti -p 45940:45940 -p 45941:45941 -v "${HOME}"/.groovy:/root/.groovy -v "${HOME}"/.m2:/root/.m2 tinkerpop:${BUILD_TAG} ${@}
+docker run ${TINKERPOP_TEST_DOCKER_OPTS} ${REMOVE_CONTAINER} -p 45940:45940 -p 45941:45941 -p 45942:45942 -p 4588:4588 -h gremlin-server-test -v "${HOME}"/.groovy:/root/.groovy \
+    -v "${HOME}"/.m2:/root/.m2 -v ${ABS_PROJECT_HOME}/gremlin-test/target:/opt/gremlin-test -ti tinkerpop:${BUILD_TAG} ${@}
 
 status=$?
 popd > /dev/null
diff --git a/docker/gremlin-server/Dockerfile.template b/docker/gremlin-server/Dockerfile.template
index de4eb45..cbb0611 100644
--- a/docker/gremlin-server/Dockerfile.template
+++ b/docker/gremlin-server/Dockerfile.template
@@ -25,7 +25,7 @@
 RUN chmod 755 /opt/docker-entrypoint.sh
 ENV GREMLIN_SERVER_VERSION=GREMLIN_SERVER_VERSION
 
-EXPOSE 45940-45941
+EXPOSE 45940-45942 4588
 
 ENTRYPOINT ["/opt/docker-entrypoint.sh"]
 CMD []
diff --git a/docker/gremlin-server/docker-entrypoint.sh b/docker/gremlin-server/docker-entrypoint.sh
index ae75116..7031cec 100644
--- a/docker/gremlin-server/docker-entrypoint.sh
+++ b/docker/gremlin-server/docker-entrypoint.sh
@@ -19,18 +19,71 @@
 #
 
 TINKERPOP_HOME=/opt/gremlin-server
-
 cp /opt/test/scripts/* ${TINKERPOP_HOME}/scripts
 
 IP=$(hostname -i)
-echo "#######################"
+
+echo "#############################################################################"
 echo IP is $IP
-echo "#######################"
+echo
+echo Available Gremlin Server instances:
+echo "ws://${IP}:45940/gremlin with anonymous access"
+echo "ws://${IP}:45941/gremlin with basic authentication (stephen/password)"
+echo "ws://${IP}:45942/gremlin with kerberos authentication (stephen/password)"
+echo
+echo "See docker/gremlin-server/docker-entrypoints.sh for transcripts per GLV."
+echo "#############################################################################"
 
 cp *.yaml ${TINKERPOP_HOME}/conf/
 
 java -version
 
-/opt/gremlin-server/bin/gremlin-server.sh install org.apache.tinkerpop gremlin-python ${GREMLIN_SERVER_VERSION}
 /opt/gremlin-server/bin/gremlin-server.sh conf/gremlin-server-integration.yaml &
-exec /opt/gremlin-server/bin/gremlin-server.sh conf/gremlin-server-integration-secure.yaml
+
+/opt/gremlin-server/bin/gremlin-server.sh conf/gremlin-server-integration-secure.yaml &
+
+java -cp /opt/gremlin-test/gremlin-test-${GREMLIN_SERVER_VERSION}-jar-with-dependencies.jar \
+     -Dlog4j.configuration="file:/opt/gremlin-server/conf/log4j-server.properties" \
+     org.apache.tinkerpop.gremlin.server.KdcFixture /opt/gremlin-server &
+
+export JAVA_OPTIONS="-Xms512m -Xmx4096m -Djava.security.krb5.conf=/opt/gremlin-server/target/kdc/krb5.conf"
+exec /opt/gremlin-server/bin/gremlin-server.sh conf/gremlin-server-integration-krb5.yaml
+
+
+#######################################################################
+# Transcripts for connecting to gremlin-server-test using various GLV's
+#######################################################################
+#
+# cd ${APACHE_TINKERPOP}                              # first terminal: location of cloned gitrepo
+# docker/gremlin-server.sh
+
+# cd ${APACHE_TINKERPOP}                              # second terminal
+# export KRB5_CONFIG=`pwd`/docker/gremlin-server/krb5.conf
+# echo 'password' | kinit stephen
+# klist
+
+# Gremlin-Groovy
+# --------------
+# KRB5_OPTION="-Djava.security.krb5.conf=`pwd`/docker/gremlin-server/krb5.conf"
+# JAAS_OPTION="-Djava.security.auth.login.config=`pwd`/docker/gremlin-server/gremlin-console-jaas.conf"
+# export JAVA_OPTIONS="${KRB5_OPTION} ${JAAS_OPTION}"
+# cd gremlin-console/target/apache-tinkerpop-gremlin-console-3.x.y-SNAPSHOT-standalone
+# If necessary (versions 3.4.2-3.4.6): in bin/gremlin.sh replace JVM_OPTS+=( "${JAVA_OPTIONS}" ) by JVM_OPTS+=( ${JAVA_OPTIONS} )
+# bin/gremlin.sh
+# gremlin> cluster = Cluster.build("172.17.0.2").port(45940).create()
+# gremlin> cluster = Cluster.build("172.17.0.2").port(45941).credentials("stephen", "password").create()
+# gremlin> cluster = Cluster.build("172.17.0.2").port(45942).addContactPoint("gremlin-server-test").protocol("test-service").jaasEntry("GremlinConsole").create()
+# gremlin> g = traversal().withRemote(DriverRemoteConnection.using(cluster, "gmodern"))
+# gremlin> g.V()
+
+# Gremlin-Python
+# --------------
+# cd gremlin-python/target/python3
+# source env/bin/activate
+# python
+# >>> from gremlin_python.process.anonymous_traversal import traversal
+# >>> from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
+# >>> g = traversal().withRemote(DriverRemoteConnection('ws://172.17.0.2:45940/gremlin','gmodern'))
+# >>> g = traversal().withRemote(DriverRemoteConnection('ws://172.17.0.2:45941/gremlin','gmodern', username='stephen', password='password'))
+# >>> g = traversal().withRemote(DriverRemoteConnection('ws://172.17.0.2:45942/gremlin','gmodern', kerberized_service='test-service@gremlin-server-test'))
+# >>> g.V().toList()
diff --git a/docker/gremlin-server/gremlin-console-jaas.conf b/docker/gremlin-server/gremlin-console-jaas.conf
new file mode 100644
index 0000000..13b92bb
--- /dev/null
+++ b/docker/gremlin-server/gremlin-console-jaas.conf
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+GremlinConsole {
+  com.sun.security.auth.module.Krb5LoginModule required
+  doNotPrompt=true
+  useTicketCache=true;
+};
diff --git a/docker/gremlin-server/gremlin-server-integration-krb5.yaml b/docker/gremlin-server/gremlin-server-integration-krb5.yaml
new file mode 100644
index 0000000..16bad46
--- /dev/null
+++ b/docker/gremlin-server/gremlin-server-integration-krb5.yaml
@@ -0,0 +1,66 @@
+# 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.
+
+host: 0.0.0.0
+port: 45942
+evaluationTimeout: 30000
+graphs: {
+  graph: conf/tinkergraph-empty.properties,
+  classic: conf/tinkergraph-empty.properties,
+  modern: conf/tinkergraph-empty.properties,
+  crew: conf/tinkergraph-empty.properties,
+  grateful: conf/tinkergraph-empty.properties,
+  sink: conf/tinkergraph-empty.properties}
+scriptEngines: {
+  gremlin-groovy: {
+    plugins: { org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin: {expectedCompilationTime: 30000},
+               org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
+               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-all.groovy]}}}}
+serializers:
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
+processors:
+  - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
+  - { className: org.apache.tinkerpop.gremlin.server.op.standard.StandardOpProcessor, config: {}}
+metrics: {
+  slf4jReporter: {enabled: true, interval: 180000}}
+strictTransactionManagement: false
+idleConnectionTimeout: 0
+keepAliveInterval: 0
+maxInitialLineLength: 4096
+maxHeaderSize: 8192
+maxChunkSize: 8192
+maxContentLength: 1000000
+maxAccumulationBufferComponents: 1024
+resultIterationBatchSize: 64
+writeBufferLowWaterMark: 32768
+writeBufferHighWaterMark: 65536
+authentication: {
+  authenticator: org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator,
+  config: {
+    principal: test-service/gremlin-server-test@TEST.COM,
+    keytab: /opt/gremlin-server/target/kdc/test-service.keytab}}
diff --git a/docker/gremlin-server/gremlin-server-integration-secure.yaml b/docker/gremlin-server/gremlin-server-integration-secure.yaml
index c489e07..1cd3156 100644
--- a/docker/gremlin-server/gremlin-server-integration-secure.yaml
+++ b/docker/gremlin-server/gremlin-server-integration-secure.yaml
@@ -17,7 +17,7 @@
 
 host: 0.0.0.0
 port: 45941
-scriptEvaluationTimeout: 30000
+evaluationTimeout: 30000
 graphs: {
   graph: conf/tinkergraph-empty.properties,
   classic: conf/tinkergraph-empty.properties,
@@ -31,10 +31,7 @@
                org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
                org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin: {expectedCompilationTime: 30000},
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
-               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-all.groovy]}}},
-  gremlin-jython: {},
-  gremlin-python: {}
-}
+               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-all.groovy]}}}}
 serializers:
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
diff --git a/docker/gremlin-server/gremlin-server-integration.yaml b/docker/gremlin-server/gremlin-server-integration.yaml
index 7c5445a..13c2d6c 100644
--- a/docker/gremlin-server/gremlin-server-integration.yaml
+++ b/docker/gremlin-server/gremlin-server-integration.yaml
@@ -17,7 +17,7 @@
 
 host: 0.0.0.0
 port: 45940
-scriptEvaluationTimeout: 30000
+evaluationTimeout: 30000
 graphs: {
   graph: conf/tinkergraph-empty.properties,
   classic: conf/tinkergraph-empty.properties,
@@ -31,10 +31,7 @@
                org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
                org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin: {expectedCompilationTime: 30000},
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
-               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-all.groovy]}}},
-  gremlin-jython: {},
-  gremlin-python: {}
-}
+               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-all.groovy]}}}}
 serializers:
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0], custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
diff --git a/docker/gremlin-server/krb5.conf b/docker/gremlin-server/krb5.conf
new file mode 100644
index 0000000..3f9c322
--- /dev/null
+++ b/docker/gremlin-server/krb5.conf
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+[libdefaults]
+    kdc_realm = TEST.COM
+    default_realm = TEST.COM
+    udp_preference_limit = 4096
+    kdc_tcp_port = 4588
+    kdc_udp_port = 4588
+
+[realms]
+    TEST.COM = {
+        kdc = 172.17.0.2:4588
+    }
diff --git a/docker/scripts/build.sh b/docker/scripts/build.sh
index bf0df0d..7222a73 100755
--- a/docker/scripts/build.sh
+++ b/docker/scripts/build.sh
@@ -76,7 +76,7 @@
   cp settings.xml ~/.m2/
 fi
 
-export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
 
 mvn clean install process-resources --batch-mode ${TINKERPOP_BUILD_OPTIONS} || exit 1
 [ -z "${BUILD_JAVA_DOCS}" ] || mvn process-resources -Djavadoc || exit 1
diff --git a/docs/preprocessor/awk/init-code-blocks.awk b/docs/preprocessor/awk/init-code-blocks.awk
index 466cb90..c9eb528 100644
--- a/docs/preprocessor/awk/init-code-blocks.awk
+++ b/docs/preprocessor/awk/init-code-blocks.awk
@@ -50,48 +50,6 @@
     print "f = new File('/tmp/tinkergraph.kryo')"
     print "if (f.exists()) f.deleteDir()"
     print ":set max-iteration 100"
-    if (lang == "python") {
-      print "import static javax.script.ScriptContext.*"
-      print "import org.apache.tinkerpop.gremlin.python.jsr223.JythonTranslator"
-      print "jython = new org.apache.tinkerpop.gremlin.python.jsr223.GremlinJythonScriptEngine()"
-      print "jython.eval('import os')"
-      print "jython.eval('os.chdir(\"" TP_HOME "\")')"
-      print "jython.eval('import sys')"
-      print "jython.eval('sys.path.append(\"" PYTHONPATH "\")')"
-      print "jython.eval('sys.path.append(\"" TP_HOME "/gremlin-python/target/python2/env/lib/python2.7/site-packages\")')"
-      print "jython.eval('from gremlin_python import statics')"
-      print "jython.eval('from gremlin_python.process.traversal import *')"
-      print "jython.eval('from gremlin_python.process.strategies import *')"
-      print "jython.eval('from gremlin_python.structure.graph import Graph')"
-      print "jython.eval('from gremlin_python.structure.io.graphsonV3d0 import GraphSONWriter')"
-      print "jython.eval('from gremlin_python.structure.io.graphsonV3d0 import GraphSONReader')"
-      # print "jython.eval('from gremlin_python.structure.io.graphson import serializers')"
-      # print "jython.eval('from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection')"
-      print "jython.eval('statics.load_statics(globals())')"
-      print "jythonBindings = jython.createBindings()"
-      print "jythonBindings.put('g', jython.eval('Graph().traversal()'))"
-      print "jythonBindings.put('h', g)"
-      print "jython.getContext().setBindings(jythonBindings, GLOBAL_SCOPE)"
-      print "groovy = new org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine()"
-      print "groovyBindings = groovy.createBindings()"
-      print "groovyBindings.put('g', g)"
-      print "groovyBindings.put('TinkerGraphComputer', TinkerGraphComputer)"
-      print "groovy.getContext().setBindings(groovyBindings, GLOBAL_SCOPE)"
-      print "def processTraversal(t, jython, groovy) {"
-      print "  jython.getContext().getBindings(GLOBAL_SCOPE).put('j', jython.eval(t.replace('.toList()','')))"
-      print "  if(jython.eval('isinstance(j, Traversal)')) {"
-      print "    mapper = GraphSONMapper.build().version(GraphSONVersion.V2_0).create().createMapper()"
-      print "    bytecode = mapper.readValue(jython.eval('GraphSONWriter().writeObject(j)').toString(), Bytecode.class)"
-      print "    language = BytecodeHelper.getLambdaLanguage(bytecode).orElse('gremlin-groovy')"
-      print "    result = language.equals('gremlin-groovy') ? groovy.eval(org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslator.of(\"g\").translate(bytecode) + '.toList()').toString() : jython.eval(JythonTranslator.of(\"h\").translate(bytecode) + '.toList()').toString()"
-      print "    jython.getContext().getBindings(GLOBAL_SCOPE).put('json', mapper.writeValueAsString(result))"
-      print "    return jython.eval('GraphSONReader().readObject(json)').toString()"
-      print "  } else {"
-      print "    j = jython.getContext().getBindings(GLOBAL_SCOPE).get('j')"
-      print "    return null == j ? 'null' : j.toString()"
-      print "  }"
-      print "}"
-    }
   }
   print "'-IGNORE'"
 }
@@ -99,9 +57,6 @@
 !/^pb\([0-9]*\); '\[gremlin-/ {
   if (delimiter == 2 && !($0 ~ /^pb\([0-9]*\); '----'/)) {
     switch (lang) {
-      case "python":
-        print "processTraversal(\"\"\"" gensub("Bindings\\.of\\('id',([0-9]+)\\)", "\\1", "g") "\"\"\", jython, groovy)"
-        break
       default:
         print
         break
diff --git a/docs/preprocessor/awk/language-variants.awk b/docs/preprocessor/awk/language-variants.awk
index d6645d1..e849444 100644
--- a/docs/preprocessor/awk/language-variants.awk
+++ b/docs/preprocessor/awk/language-variants.awk
@@ -36,13 +36,6 @@
 
 { if (inCodeBlock) {
     switch (lang) {
-      case "python":
-        gsub(/^gremlin>/, ">>>")
-        gsub(/^==>/, "")
-        $0 = gensub(/processTraversal\("""(.*)"""\, jython, groovy)/, "\\1", 1)
-        $0 = gensub("g\\.V\\(([^\\)]+)", "g.V(Bindings\\.of('id',\\1)", "g")
-        print gensub("g\\.V\\(Bindings.of\\('id',(Bindings.of\\([^\\)]+\\))\\)\\)", "g.V(\\1)", "g")
-        break
       default:
         print
         break
diff --git a/docs/preprocessor/awk/prepare.awk b/docs/preprocessor/awk/prepare.awk
index 415a6b5..52a14cc 100644
--- a/docs/preprocessor/awk/prepare.awk
+++ b/docs/preprocessor/awk/prepare.awk
@@ -72,9 +72,6 @@
   split(b, l, ",")
   lang = l[1]
   switch (lang) {
-    case "python":
-      c = "#"
-      break
     default:
       c = "//"
       break
diff --git a/docs/preprocessor/awk/tabify.awk b/docs/preprocessor/awk/tabify.awk
index fc07331..fa22ed5 100644
--- a/docs/preprocessor/awk/tabify.awk
+++ b/docs/preprocessor/awk/tabify.awk
@@ -111,9 +111,6 @@
       }
       tabs[i] = lang
       switch (lang) {
-        case "python":
-          c = "#"
-          break
         default:
           c = "//"
           break
diff --git a/docs/preprocessor/install-plugins.sh b/docs/preprocessor/install-plugins.sh
index 5855e92..ba88213 100755
--- a/docs/preprocessor/install-plugins.sh
+++ b/docs/preprocessor/install-plugins.sh
@@ -52,9 +52,6 @@
   ((i++))
 done
 
-echo "installPlugin(new Artifact(\"org.apache.tinkerpop\", \"gremlin-python\", \"${TP_VERSION}\"))" >> ${INSTALL_FILE}
-echo "gremlin-python" >> ${TMP_DIR}/plugins.dir
-
 echo "System.exit(0)" >> ${INSTALL_FILE}
 echo -ne " * tinkerpop-sugar ... "
 
diff --git a/docs/preprocessor/preprocess-file.sh b/docs/preprocessor/preprocess-file.sh
index dbef22f..9ae43c2 100755
--- a/docs/preprocessor/preprocess-file.sh
+++ b/docs/preprocessor/preprocess-file.sh
@@ -133,7 +133,7 @@
   sed 's/\t/    /g' ${input} |
   awk -f ${AWK_SCRIPTS}/tabify.awk |
   awk -f ${AWK_SCRIPTS}/prepare.awk |
-  awk -f ${AWK_SCRIPTS}/init-code-blocks.awk -v TP_HOME="${TP_HOME}" -v PYTHONPATH="${TP_HOME}/gremlin-python/target/classes/Lib" |
+  awk -f ${AWK_SCRIPTS}/init-code-blocks.awk -v TP_HOME="${TP_HOME}" |
   awk -f ${AWK_SCRIPTS}/progressbar.awk -v tpl=${AWK_SCRIPTS}/progressbar.groovy.template |
   HADOOP_GREMLIN_LIBS="${CONSOLE_HOME}/ext/tinkergraph-gremlin/lib" bin/gremlin.sh | ${TP_HOME}/docs/preprocessor/control-characters.sh |
   ${lb} awk -f ${AWK_SCRIPTS}/ignore.awk   |
diff --git a/docs/site/home/downloads.html b/docs/site/home/downloads.html
index f89661b..8ff97f0 100644
--- a/docs/site/home/downloads.html
+++ b/docs/site/home/downloads.html
@@ -18,47 +18,47 @@
  <div class="row">
     <h3>Download Apache TinkerPop&trade;</h3>
     <p><img src="img/gremlin-download.png"  style="float:right;width:150px;padding:10px;"/>Apache TinkerPop provides three packaged downloads per release version. The
-       <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin Console</a> and <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-server">Gremlin Server</a>
+       <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin Console</a> and <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-server">Gremlin Server</a>
        downloads are binary distributions, which contain pre-packaged versions of these important TinkerPop applications that are designed to work out-of-the-box
        when unpackaged. The source distribution is a snapshot of the source code and files used in the building of those  binary distributions.</p>
     <h4>Current Releases</h4>
     <table class="table">
         <tr>
             <td>
-                <strong>3.4.2</strong> (latest, stable)
+                <strong>3.4.8</strong> (latest, stable)
             </td>
             <td>
-                28-May-2019
+                3-Aug-2020
             </td>
             <td>
-                <a href="https://github.com/apache/tinkerpop/blob/3.4.2/CHANGELOG.asciidoc#release-3-4-2">release notes</a> |
-                <a href="http://tinkerpop.apache.org/docs/3.4.2/upgrade/#_tinkerpop_3_4_2">upgrade</a> |
-                <a href="http://tinkerpop.apache.org/docs/3.4.2/">documentation</a> |
-                <a href="#" data-toggle="modal" data-target="#contributors-3_4_2">contributors</a>
+                <a href="https://github.com/apache/tinkerpop/blob/3.4.8/CHANGELOG.asciidoc#release-3-4-8">release notes</a> |
+                <a href="https://tinkerpop.apache.org/docs/3.4.8/upgrade/#_tinkerpop_3_4_8">upgrade</a> |
+                <a href="https://tinkerpop.apache.org/docs/3.4.8/">documentation</a> |
+                <a href="#" data-toggle="modal" data-target="#contributors-3_4_8">contributors</a>
             </td>
             <td align="right">
-                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.2/apache-tinkerpop-gremlin-console-3.4.2-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
-                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.2/apache-tinkerpop-gremlin-server-3.4.2-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
-                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.2/apache-tinkerpop-3.4.2-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
+                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.8/apache-tinkerpop-gremlin-console-3.4.8-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
+                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.8/apache-tinkerpop-gremlin-server-3.4.8-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
+                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.8/apache-tinkerpop-3.4.8-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
             </td>
         </tr>
         <tr>
             <td>
-                <strong>3.3.7</strong> (maintenance)
+                <strong>3.3.11</strong> (maintenance)
             </td>
             <td>
-                28-May-2019
+                1-Jun-2020
             </td>
             <td>
-                <a href="https://github.com/apache/tinkerpop/blob/3.3.7/CHANGELOG.asciidoc#release-3-3-7">release notes</a> |
-                <a href="http://tinkerpop.apache.org/docs/3.3.7/upgrade/#_tinkerpop_3_3_7">upgrade</a> |
-                <a href="http://tinkerpop.apache.org/docs/3.3.7/">documentation</a> |
-                <a href="#" data-toggle="modal" data-target="#contributors-3_3_7">contributors</a>
+                <a href="https://github.com/apache/tinkerpop/blob/3.3.11/CHANGELOG.asciidoc#release-3-3-11">release notes</a> |
+                <a href="https://tinkerpop.apache.org/docs/3.3.11/upgrade/#_tinkerpop_3_3_11">upgrade</a> |
+                <a href="https://tinkerpop.apache.org/docs/3.3.11/">documentation</a> |
+                <a href="#" data-toggle="modal" data-target="#contributors-3_3_11">contributors</a>
             </td>
             <td align="right">
-                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.3.7/apache-tinkerpop-gremlin-console-3.3.7-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
-                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.3.7/apache-tinkerpop-gremlin-server-3.3.7-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
-                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.3.7/apache-tinkerpop-3.3.7-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
+                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.3.11/apache-tinkerpop-gremlin-console-3.3.11-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
+                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.3.11/apache-tinkerpop-gremlin-server-3.3.11-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
+                <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.3.11/apache-tinkerpop-3.3.11-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
             </td>
         </tr>
     </table>
@@ -67,8 +67,18 @@
     <div class="form-group row">
         <div class="col-xs-3">
     <select id="dropdownArchives" class="form-control">
-        <option selected="selected">3.4.1 (18-Mar-2019)</option>
+        <option selected="selected">3.4.7 (1-Jun-2020)</option>
+        <option>3.4.6 (20-Feb-2020)</option>
+        <option>3.4.5 (3-Feb-2020)</option>
+        <option>3.4.4 (14-Oct-2019)</option>
+        <option>3.4.3 (5-Aug-2019)</option>
+        <option>3.4.2 (28-May-2019)</option>
+        <option>3.4.1 (18-Mar-2019)</option>
         <option>3.4.0 (2-Jan-2019)</option>
+        <option>3.3.10 (3-Feb-2020)</option>
+        <option>3.3.9 (14-Oct-2019)</option>
+        <option>3.3.8 (5-Aug-2019)</option>
+        <option>3.3.7 (28-May-2019)</option>
         <option>3.3.6 (18-Mar-2019)</option>
         <option>3.3.5 (2-Jan-2019)</option>
         <option>3.3.4 (15-Oct-2018)</option>
@@ -111,21 +121,21 @@
              </td>
              <td id="archiveReleaseDate"></td>
              <td>
-                 <a id="archiveReleaseNotes" href="https://github.com/apache/tinkerpop/blob/3.4.1/CHANGELOG.asciidoc#release-3-4-1">release notes</a> |
-                 <span id="archiveUpgrade"><a href="http://tinkerpop.apache.org/docs/3.4.1/upgrade/#_tinkerpop_3_4_1">upgrade</a> |</span>
-                 <a id="archiveDocs" href="http://tinkerpop.apache.org/docs/3.4.1/">documentation</a> |
-                 <a id="archiveContributors" href="#" data-toggle="modal" data-target="#contributors-3_4_1">contributors</a>
+                 <a id="archiveReleaseNotes" href="https://github.com/apache/tinkerpop/blob/3.4.2/CHANGELOG.asciidoc#release-3-4-2">release notes</a> |
+                 <span id="archiveUpgrade"><a href="https://tinkerpop.apache.org/docs/3.4.2/upgrade/#_tinkerpop_3_4_2">upgrade</a> |</span>
+                 <a id="archiveDocs" href="https://tinkerpop.apache.org/docs/3.4.2/">documentation</a> |
+                 <a id="archiveContributors" href="#" data-toggle="modal" data-target="#contributors-3_4_2">contributors</a>
              </td>
              <td align="right">
-                 <a id="archiveDownloadConsole" href="https://archive.apache.org/dist/tinkerpop/3.4.1/apache-tinkerpop-gremlin-console-3.4.1-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
-                 <a id="archiveDownloadServer" href="https://archive.apache.org/dist/tinkerpop/3.4.1/apache-tinkerpop-gremlin-server-3.4.1-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
-                 <a id="archiveDownloadSource" href="https://archive.apache.org/dist/tinkerpop/3.4.1/apache-tinkerpop-3.4.1-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
+                 <a id="archiveDownloadConsole" href="https://archive.apache.org/dist/tinkerpop/3.4.2/apache-tinkerpop-gremlin-console-3.4.2-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
+                 <a id="archiveDownloadServer" href="https://archive.apache.org/dist/tinkerpop/3.4.2/apache-tinkerpop-gremlin-server-3.4.2-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
+                 <a id="archiveDownloadSource" href="https://archive.apache.org/dist/tinkerpop/3.4.2/apache-tinkerpop-3.4.2-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
              </td>
          </tr>
      </table>
     <p><strong>Note</strong> that upgrade documentation was only introduced at 3.1.1-incubating which is why there are no "upgrade" links in versions prior to that one.
     <p>As a convenience, TinkerPop also deploys packaged artifacts to the following locations:</p>
-    <p><a href="https://hub.docker.com/u/tinkerpop/">Docker</a> | <a href="http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.apache.tinkerpop%22">Maven Central</a> | <a href="https://pypi.python.org/pypi/gremlinpython/">PyPI</a> | <a href="https://www.npmjs.com/package/gremlin">npm</a> | <a href="https://www.nuget.org/packages/Gremlin.Net/">NuGet</a></p>
+    <p><a href="https://hub.docker.com/u/tinkerpop/">Docker</a> | <a href="https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.apache.tinkerpop%22">Maven Central</a> | <a href="https://pypi.python.org/pypi/gremlinpython/">PyPI</a> | <a href="https://www.npmjs.com/package/gremlin">npm</a> | <a href="https://www.nuget.org/packages/Gremlin.Net/">NuGet</a></p>
 
      <p><strong>Note</strong> this page lists official Apache releases only. TinkerPop occasionally produces unofficial binary release candidates (denoted by the suffix "-RC") which are NOT promoted or announced as actual release versions. <i>Such releases are for early development and evaluation purposes only.</i></p>
 
@@ -162,6 +172,176 @@
  </div>
 
     <!-- Contributor Modals -->
+    <!-- 3.4.8 -->
+    <div class="modal fade" id="contributors-3_4_8" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.4.8</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.4.7..3.4.8
+    21  Stephen Mallette
+     4  Mark Broadmore
+     3  Florian Hockmann
+     3  Jermy Li
+     1  Cholerae Hu
+     1  Divij Vaidya
+     1  Gustavo Cavalieri Fernandes</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.4.7 -->
+    <div class="modal fade" id="contributors-3_4_7" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.4.7</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.4.6..3.4.7
+   106  Stephen Mallette
+    18  Liu Jianping
+    17  Florian Hockmann
+     4  Robert Dale
+     3  Jorge Bay Gondra
+     2  Daniel C. Weber
+     2  dzmitry.lahoda
+     1  Connor T. Skennerton
+     1  Eduard Tudenhoefner
+     1  Juha Haapsaari
+     1  Justin Chu
+     1  Nicolas Trangosi
+     1  olim7t</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.4.6 -->
+    <div class="modal fade" id="contributors-3_4_6" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.4.6</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.4.5..3.4.6
+    10  Stephen Mallette
+     1  Nicolas Trangosi</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.4.5 -->
+    <div class="modal fade" id="contributors-3_4_5" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.4.5</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.4.4..3.4.5
+   107  Stephen Mallette
+    17  Jorge Bay Gondra
+     9  Rusi Popov
+     8  Robert Dale
+     4  Jermy Li
+     3  thevalzo
+     2  Daniel Kuppitz
+     2  Norio Akagi
+     1  Cholerae Hu
+     1  root
+     1  wangshaogan
+     1  臻至</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.4.4 -->
+    <div class="modal fade" id="contributors-3_4_4" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.4.4</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.4.3..3.4.4
+   157  Stephen Mallette
+     5  thirstycrow
+     3  Daniel Kuppitz
+     3  Jorge Bay Gondra
+     2  Justin Chu
+     2  Robert Dale
+     2  gion
+     2  sandszhou.zj
+     1  Ammarove
+     1  Dan LaRocque
+     1  Martin Kulhavy
+     1  sel-fish</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.4.3 -->
+    <div class="modal fade" id="contributors-3_4_3" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.4.3</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.4.2..3.4.3
+   207  Stephen Mallette
+    13  Robert Dale
+    11  Divij Vaidya
+    11  jon-scho
+     8  Daniel Kuppitz
+     4  bryn
+     3  Eduard Tudenhoefner
+     2  sandszhou.zj
+     1  Dan LaRocque
+     1  xiyu.wxy</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <!-- 3.4.2 -->
     <div class="modal fade" id="contributors-3_4_2" tabindex="-1" role="dialog">
         <div class="modal-dialog" role="document">
@@ -172,7 +352,21 @@
                 </div>
                 <div class="modal-body">
                     <p>Release Manager: Stephen Mallette</p>
-                    <pre><code>$ git shortlog -sn 3.4.1..3.4.2</code></pre>
+                    <pre><code>$ git shortlog -sn 3.4.1..3.4.2
+   119  Stephen Mallette
+    20  Robert Dale
+     5  Eduard Tudenhoefner
+     4  Divij Vaidya
+     4  Jorge Bay Gondra
+     3  Daniel Kuppitz
+     3  Kevin Gallardo
+     2  Dwitry
+     1  Brett Peavler
+     1  Dan LaRocque
+     1  Daniel C. Weber
+     1  Florian Hockmann
+     1  Hieu Nguyen
+     1  sel-fish</code></pre>
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
@@ -259,6 +453,117 @@
         </div>
     </div>
 
+    <!-- 3.3.11 -->
+    <div class="modal fade" id="contributors-3_3_11" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.3.11</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.3.10..3.3.11
+    46  Stephen Mallette
+    13  Liu Jianping
+     7  Florian Hockmann
+     2  Daniel C. Weber
+     2  Jorge Bay Gondra
+     1  Justin Chu
+     1  Robert Dale
+     1  olim7t</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.3.10 -->
+    <div class="modal fade" id="contributors-3_3_10" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.3.10</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.3.9..3.3.10
+    44  Stephen Mallette
+     9  Rusi Popov
+     8  Jorge Bay Gondra
+     4  Robert Dale
+     1  Cholerae Hu
+     1  Daniel Kuppitz
+     1  Norio Akagi
+     1  wangshaogan</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.3.9 -->
+    <div class="modal fade" id="contributors-3_3_9" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.3.9</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.3.8..3.3.9
+    47  Stephen Mallette
+     4  thirstycrow
+     2  Jorge Bay Gondra
+     2  Justin Chu
+     2  gion
+     2  sandszhou.zj
+     1  Ammarove
+     1  Daniel Kuppitz
+     1  Martin Kulhavy
+     1  Robert Dale
+     1  sel-fish</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.3.8 -->
+    <div class="modal fade" id="contributors-3_3_8" tabindex="-1" role="dialog">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">3.3.8</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Release Manager: Stephen Mallette</p>
+                    <pre><code>$ git shortlog -sn 3.3.7..3.3.8
+    99  Stephen Mallette
+    11  Divij Vaidya
+     6  jon-scho
+     3  Daniel Kuppitz
+     2  Eduard Tudenhoefner
+     2  Robert Dale
+     1  sandszhou.zj
+     1  xiyu.wxy</code></pre>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <!-- 3.3.7 -->
     <div class="modal fade" id="contributors-3_3_7" tabindex="-1" role="dialog">
         <div class="modal-dialog" role="document">
@@ -269,7 +574,15 @@
                 </div>
                 <div class="modal-body">
                     <p>Release Manager: Stephen Mallette</p>
-                    <pre><code>$ git shortlog -sn 3.3.6..3.3.7</code></pre>
+                    <pre><code>$ git shortlog -sn 3.3.6..3.3.7
+    46  Stephen Mallette
+     9  Robert Dale
+     4  Eduard Tudenhoefner
+     2  Daniel Kuppitz
+     2  Dwitry
+     2  Jorge Bay Gondra
+     1  Hieu Nguyen
+     1  Kevin Gallardo</code></pre>
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
@@ -1275,7 +1588,7 @@
             $("#archiveVersion").html(version);
             $("#archiveReleaseDate").html(releaseDate);
             $("#archiveReleaseNotes").attr("href", "https://github.com/apache/tinkerpop/blob/master/CHANGELOG.asciidoc#release-" + versionHyphened);
-            $("#archiveDocs").attr("href", "http://tinkerpop.apache.org/docs/" + version);
+            $("#archiveDocs").attr("href", "https://tinkerpop.apache.org/docs/" + version);
             $("#archiveContributors").attr("data-target", "#contributors-" + versionUnderscored);
 
             var versionsWithOldNaming = ["3.2.1", "3.1.3", "3.2.0-incubating", "3.1.2-incubating", "3.1.1-incubating",
@@ -1299,7 +1612,7 @@
                 $("#archiveUpgrade a").attr("href", "#");
                 $("#archiveUpgrade").hide();
             } else {
-                $("#archiveUpgrade a").attr("href", "http://tinkerpop.apache.org/docs/" + version + "/upgrade/#_tinkerpop_" + versionUnderscored);
+                $("#archiveUpgrade a").attr("href", "https://tinkerpop.apache.org/docs/" + version + "/upgrade/#_tinkerpop_" + versionUnderscored);
                 $("#archiveUpgrade").show();
             }
 
diff --git a/docs/site/home/gremlin.html b/docs/site/home/gremlin.html
index a8a6cd3..7c3e6aa 100644
--- a/docs/site/home/gremlin.html
+++ b/docs/site/home/gremlin.html
@@ -26,7 +26,7 @@
  <div class="container">
     <div class="row">
        <div class="col-sm-10 col-md-10">
-          <a href="http://arxiv.org/abs/1508.03843">Gremlin</a> is the graph traversal language of <a href="http://tinkerpop.apache.org/">Apache TinkerPop</a>.
+          <a href="http://arxiv.org/abs/1508.03843">Gremlin</a> is the graph traversal language of <a href="https://tinkerpop.apache.org/">Apache TinkerPop</a>.
           Gremlin is a <a href="https://en.wikipedia.org/wiki/Functional_programming">functional</a>, <a href="https://en.wikipedia.org/wiki/Dataflow_programming">data-flow</a>
           language that enables users to succinctly express complex traversals on (or queries of) their application's property graph. Every Gremlin traversal is composed of a sequence of (potentially nested) steps. A step
           performs an atomic operation on the data stream. Every step is either a <em>map</em>-step (transforming the objects in the stream), a <em>filter</em>-step (removing objects
@@ -250,14 +250,14 @@
        </div>
        <div class="col-sm-7 col-md-8">
           A declarative Gremlin traversal does not tell the traversers the order in which to execute their walk, but instead, allows each traverser to select a pattern to execute from a collection
-          of (potentially nested) patterns. The <a href="http://tinkerpop.apache.org/docs/current/reference/#match-step">declarative traversal</a> on the left yields the same result as the imperative traversal above. However, the declarative traversal has the added benefit
+          of (potentially nested) patterns. The <a href="https://tinkerpop.apache.org/docs/current/reference/#match-step">declarative traversal</a> on the left yields the same result as the imperative traversal above. However, the declarative traversal has the added benefit
           that it leverages not only a compile-time query planner (like imperative traversals), but also a runtime query planner that chooses which traversal pattern to execute next based on the
           historic statistics of each pattern -- favoring those patterns which tend to reduce/filter the most data.
        </div>
     </div>
     <br/>
     The user can write their traversals in any way they choose. However, ultimately when their traversal is compiled, and depending on the underlying execution engine
-    (i.e. an OLTP graph database or an OLAP graph processor), the user's traversal is rewritten by a set of <em><a href="http://tinkerpop.apache.org/docs/current/reference/#traversalstrategy">traversal strategies</a></em> which do their best to determine the most optimal execution
+    (i.e. an OLTP graph database or an OLAP graph processor), the user's traversal is rewritten by a set of <em><a href="https://tinkerpop.apache.org/docs/current/reference/#traversalstrategy">traversal strategies</a></em> which do their best to determine the most optimal execution
     plan based on an understanding of graph data access costs as well as the underlying data systems's unique capabilities (e.g. fetch the Gremlin vertex from the graph database's "name"-index).
     Gremlin has been designed to give users flexibility in how they express their queries and graph system providers flexibility in how to efficiently evaluate traversals against their TinkerPop-enabled data system.
  </div>
@@ -277,7 +277,7 @@
           "programming languages" are not as great as we are taught to believe. Gremlin unifies this divide because traversals can be written in any
           programming language that supports function <a href="https://en.wikipedia.org/wiki/Function_composition">composition</a> and <a href="https://en.wikipedia.org/wiki/Nested_function">nesting</a> (which every major programming language supports). In this way, the user's
           Gremlin traversals are written along side their application code and benefit from the advantages afforded by the host language and its tooling
-          (e.g. type checking, syntax highlighting, dot completion, etc.). Various <a href="http://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin language variants</a> exist including: Gremlin-Java, Gremlin-Groovy, <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>,
+          (e.g. type checking, syntax highlighting, dot completion, etc.). Various <a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin language variants</a> exist including: Gremlin-Java, Gremlin-Groovy, <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>,
           <a href="https://github.com/mpollmeier/gremlin-scala">Gremlin-Scala</a>, etc.
        </div>
        <div class="col-md-12">
diff --git a/docs/site/home/index.html b/docs/site/home/index.html
index c17c728..2385b84 100644
--- a/docs/site/home/index.html
+++ b/docs/site/home/index.html
@@ -26,23 +26,23 @@
             <br/>
             <p>
             </p>
-            <b><font size="4">TinkerPop</font> <font size="4">3.4.2</font></b> (<font size="2">Released: 28-May-2019</font>)
+            <b><font size="4">TinkerPop</font> <font size="4">3.4.8</font></b> (<font size="2">Released: 3-Aug-2020</font>)
             <p><b>Downloads</b></p>
             <p>
-               <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.2/apache-tinkerpop-gremlin-console-3.4.2-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
-               <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.2/apache-tinkerpop-gremlin-server-3.4.2-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
-               <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.2/apache-tinkerpop-3.4.2-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
+               <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.8/apache-tinkerpop-gremlin-console-3.4.8-bin.zip" class="btn btn-primary">Gremlin Console <span class="glyphicon glyphicon-download-alt"></span></a>
+               <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.8/apache-tinkerpop-gremlin-server-3.4.8-bin.zip" class="btn btn-primary">Gremlin Server <span class="glyphicon glyphicon-download-alt"></span></a>
+               <a href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.4.8/apache-tinkerpop-3.4.8-src.zip" class="btn btn-primary">Source <span class="glyphicon glyphicon-download-alt"></span></a>
             </p>
             <div class="row">
                <div class="col-md-6">
                   <p><b>Documentation</b></p>
                   <ul>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/">TinkerPop Documentation</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/">TinkerPop Documentation</a></li>
                      <ul>
-                        <li><a href="http://tinkerpop.apache.org/docs/current/reference">Reference Documentation</a></li>
+                        <li><a href="https://tinkerpop.apache.org/docs/current/reference">Reference Documentation</a></li>
                      </ul>
-                     <li><a href="http://tinkerpop.apache.org/docs/3.4.2/upgrade/#_tinkerpop_3_4_2">Upgrade Information</a></li>
-                     <li>TinkerPop Javadoc - <a href="http://tinkerpop.apache.org/javadocs/current/core/">core</a> / <a href="http://tinkerpop.apache.org/javadocs/current/full/">full</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/3.4.8/upgrade/#_tinkerpop_3_4_8">Upgrade Information</a></li>
+                     <li>TinkerPop Javadoc - <a href="https://tinkerpop.apache.org/javadocs/current/core/">core</a> / <a href="https://tinkerpop.apache.org/javadocs/current/full/">full</a></li>
                   </ul>
                </div>
                <div class="col-md-6">
@@ -95,19 +95,19 @@
          <div class="item">
                   <pre><code class="language-gremlin">
     // What are the names of projects that were created by two friends?
-    g.V().match(
-      as("a").out("knows").as("b"),
-      as("a").out("created").as("c"),
-      as("b").out("created").as("c"),
-      as("c").in("created").count().is(2)).
-        select("c").by("name")
+    g.V().
+      match(as("a").out("knows").as("b"),
+            as("a").out("created").as("c"),
+            as("b").out("created").as("c"),
+            as("c").in("created").count().is(2)).
+      select("c").by("name")
           </code></pre>
          </div>
          <div class="item">
                   <pre><code class="language-gremlin">
 
-    // What are the names of the managers in
-    //  the management chain going from Gremlin to the CEO?
+    // What are the names of the managers in the
+    // management chain going from Gremlin to the CEO?
     g.V().has("name","gremlin").
       repeat(in("manages")).until(has("title","ceo")).
       path().by("name")
@@ -120,7 +120,7 @@
     // What is the distribution of job titles amongst Gremlin's collaborators?
     g.V().has("name","gremlin").as("a").
       out("created").in("created").
-        where(neq("a")).
+      where(neq("a")).
       groupCount().by("title")
 
           </code></pre>
@@ -131,9 +131,9 @@
     // Get a ranking of the most relevant products for Gremlin given his purchase history.
     g.V().has("name","gremlin").out("bought").aggregate("stash").
       in("bought").out("bought").
-        where(not(within("stash"))).
+      where(not(within("stash"))).
       groupCount().
-        order(local).by(values,desc)
+      order(local).by(values,desc)
           </code></pre>
          </div>
       </div>
@@ -144,12 +144,12 @@
       <p><img src="img/graph-globe.png" style="float:left;width:15%;padding:10px;"> A <strong>graph</strong> is a structure composed of <strong>vertices</strong> and <strong>edges</strong>.
          Both vertices and edges can have an arbitrary number of key/value-pairs called <strong>properties</strong>.
          Vertices denote discrete objects such as a person, a place, or an event. Edges denote relationships between vertices. For instance, a person may know
-         another person, have been involved in an event, and/or was recently at a particular place. Properties express non-relational information about the
-         vertices and edges. Example properties include a vertex having a name, an age and an edge having a timestamp and/or a weight. Together, the aforementioned
+         another person, have been involved in an event, and/or have recently been at a particular place. Properties express non-relational information about the
+         vertices and edges. Example properties include a vertex having a name and an age, and an edge having a timestamp and/or a weight. Together, the aforementioned
          graph is known as a <strong>property graph</strong> and it is the foundational data structure of Apache TinkerPop.
       </p>
       <br/>
-      <p><img src="img/graph-vs-table.png" style="float:right;width:22%;padding:10px;">If a user's domain is composed of a heterogenous set of objects (vertices) that can be related to one another in a multitude of ways (edges),
+      <p><img src="img/graph-vs-table.png" style="float:right;width:22%;padding:10px;">If a user's domain is composed of a heterogeneous set of objects (vertices) that can be related to one another in a multitude of ways (edges),
          then a graph may be the right representation to use. In a graph, each vertex is seen as an atomic entity (not simply a "row in a table") that
          can be linked to any other vertex or have properties added or removed at will. This empowers the data modeler to think in terms of actors within
          a world of complex relations as opposed to, in relational databases, statically-typed tables joined in aggregate. Once a domain is modeled, that
@@ -159,7 +159,7 @@
          effectively leverage that structure.
       </p>
       <br/>
-      <p><a href="#"><img src="img/apache-tinkerpop-logo.png" style="float:left;width:22%;padding:10px;"/></a>Apache TinkerPop&trade; is an open source, vendor-agnostic, graph computing framework distributed under the commercial friendly <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache2 license</a>.
+      <p><a href="#"><img src="img/apache-tinkerpop-logo.png" style="float:left;width:22%;padding:10px;"/></a>Apache TinkerPop&trade; is an open source, vendor-agnostic, graph computing framework distributed under the commercial friendly <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache2 license</a>.
          When a data system is <a href="providers.html">TinkerPop-enabled</a>, its users are able to model their domain as a graph and analyze that graph using the <a href="gremlin.html">Gremlin graph traversal language</a>.
          Furthermore, all TinkerPop-enabled systems integrate with one another allowing them to easily expand their offerings as well as allowing users to choose the appropriate graph
          technology for their application. Sometimes an application is best served by an in-memory, transactional graph database. Sometimes a multi-machine distributed graph database will do the job.
@@ -172,11 +172,11 @@
       <div class="col-xs-12">
          <div class="row">
             <div class="col-xs-8">
-               TinkerPop is an open source project that <a href="http://tinkerpop.apache.org/docs/current/dev/developer#_contributing">welcomes contributions</a>. There are many ways to get involved:
+               TinkerPop is an open source project that <a href="https://tinkerpop.apache.org/docs/current/dev/developer#_contributing">welcomes contributions</a>. There are many ways to get involved:
                <p/>
                <ol>
                   <li>
-                     Join the <a href="http://groups.google.com/group/gremlin-users">Gremlin-Users</a> public mailing list.
+                     Join the <a href="https://groups.google.com/group/gremlin-users">Gremlin-Users</a> public mailing list.
                      <ul>
                         <li>Help users by answering questions and demonstrating your expertise in TinkerPop and graphs.</li>
                      </ul>
@@ -199,17 +199,17 @@
                      <li>Become a TinkerPop Committer and help determine the evolution of The TinkerPop.</li>
                   </ul>
                </ol>
-               <p>To build TinkerPop from source, please review the <a href="http://tinkerpop.apache.org/docs/current/dev/developer/#building-testing">developer documentation</a>.
+               <p>To build TinkerPop from source, please review the <a href="https://tinkerpop.apache.org/docs/current/dev/developer/#building-testing">developer documentation</a>.
             </div>
             <div class="col-xs-4">
-               <a href="http://tinkerpop.apache.org/docs/current/dev/developer/"><img src="img/gremlin-apache.png" width="250" class="img-responsive" /></a>
+               <a href="https://tinkerpop.apache.org/docs/current/dev/developer/"><img src="img/gremlin-apache.png" width="250" class="img-responsive" /></a>
             </div>
          </div>
          <h3>Community Contributions</h3>
          TinkerPop is at the center of a larger development ecosystem that extends on its core interfaces, integration points, and ideas.  The graph systems and libraries below represent both
-         TinkerPop-maintained reference implementations as well as third-party managed projects. The TinkerPop community is always interested in hearing about projects like these and aiding
+         TinkerPop-maintained reference implementations and third-party managed projects. The TinkerPop community is always interested in hearing about projects like these and aiding
          in their support. Please read our <a href="policy.html">provider listing policy</a> and feel free to promote such projects on the user and developer mailing lists. Information on
-         how to build implementations of the various interfaces that TinkerPop exposes can be found in the <a href="http://tinkerpop.apache.org/docs/current/dev/provider/">Provider Documentation</a>.
+         how to build implementations of the various interfaces that TinkerPop exposes can be found in the <a href="https://tinkerpop.apache.org/docs/current/dev/provider/">Provider Documentation</a>.
          <p/>
          <a name="graph-systems"></a>
          <h4 id="graph-systems">Graph Systems</h4>
@@ -222,22 +222,23 @@
             <li><a href="https://github.com/blazegraph/tinkerpop3">Blazegraph</a> - RDF graph database with OLTP support.</li>
             <li><a href="https://docs.microsoft.com/en-us/azure/cosmos-db/graph-introduction">CosmosDB</a> - Microsoft's distributed OLTP graph database.</li>
             <li><a href="https://github.com/MartinHaeusler/chronos/tree/master/org.chronos.chronograph">ChronoGraph</a> - A versioned graph database.</li>
-            <li><a href="http://www.datastax.com/products/datastax-enterprise-graph">DSEGraph</a> - DataStax graph database with OLTP and OLAP support.</li>
+            <li><a href="https://www.datastax.com/products/datastax-enterprise-graph">DSEGraph</a> - DataStax graph database with OLTP and OLAP support.</li>
             <li><a href="https://grakn.ai/">GRAKN.AI</a> - Distributed OLTP/OLAP knowledge graph system.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#sparkgraphcomputer">Hadoop (Spark)</a> - OLAP graph processor using Spark.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#sparkgraphcomputer">Hadoop (Spark)</a> - OLAP graph processor using Spark.</li>
             <li><a href="https://github.com/rayokota/hgraphdb">HGraphDB</a> - OLTP graph database running on Apache HBase.</li>
             <li><a href="https://www.huaweicloud.com/en-us/product/ges.html">Huawei Graph Engine Service</a> - Fully-managed, distributed, at-scale graph query and analysis service that provides a visualized interactive analytics platform.</li>
             <li><a href="https://console.ng.bluemix.net/catalog/services/ibm-graph/">IBM Graph</a> - OLTP graph database as a service.</li>
             <li><a href="http://janusgraph.org/">JanusGraph</a> - Distributed OLTP and OLAP graph database with BerkeleyDB, Apache Cassandra and Apache HBase support.</li>
             <li><a href="https://github.com/awslabs/dynamodb-janusgraph-storage-backend//">JanusGraph (Amazon)</a> - The Amazon DynamoDB Storage Backend for JanusGraph.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#neo4j-gremlin">Neo4j</a> - OLTP graph database (embedded and high availability).</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#neo4j-gremlin">Neo4j</a> - OLTP graph database (embedded and high availability).</li>
             <li><a href="https://github.com/SteelBridgeLabs/neo4j-gremlin-bolt">neo4j-gremlin-bolt</a> - OLTP graph database (using Bolt Protocol).</li>
             <li><a href="https://github.com/orientechnologies/orientdb-gremlin">OrientDB</a> - OLTP graph database</li>
-            <li><a href="http://s2graph.apache.org/">Apache S2Graph</a> - OLTP graph database running on Apache HBase.</li>
+            <li><a href="https://github.com/ShiftLeftSecurity/overflowdb">OverflowDB</a> - In-memory graph database with low memory footprint</li>
+            <li><a href="https://s2graph.apache.org/">Apache S2Graph</a> - OLTP graph database running on Apache HBase.</li>
             <li><a href="https://github.com/pietermartin/sqlg">Sqlg</a> - OLTP implementation on SQL databases.</li>
-            <li><a href="http://stardog.com/">Stardog</a> - RDF graph database with OLTP and OLAP support.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#tinkergraph-gremlin">TinkerGraph</a> - In-memory OLTP and OLAP reference implementation.</li>
-            <li><a href="http://thinkaurelius.github.io/titan/">Titan</a> - Distributed OLTP and OLAP graph database with BerkeleyDB, Apache Cassandra and Apache HBase support.</li>
+            <li><a href="https://stardog.com/">Stardog</a> - RDF graph database with OLTP and OLAP support.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#tinkergraph-gremlin">TinkerGraph</a> - In-memory OLTP and OLAP reference implementation.</li>
+            <li><a href="https://thinkaurelius.github.io/titan/">Titan</a> - Distributed OLTP and OLAP graph database with BerkeleyDB, Apache Cassandra and Apache HBase support.</li>
             <li><a href="https://github.com/awslabs/dynamodb-titan-storage-backend">Titan (Amazon)</a> - The Amazon DynamoDB storage backend for Titan.</li>
             <li><a href="https://github.com/classmethod/tupl-titan-storage-backend">Titan (Tupl)</a> - The Tupl storage backend for Titan.</li>
             <li><a href="https://github.com/rmagen/unipop">Unipop</a> - OLTP Elasticsearch and JDBC backed graph.</li>
@@ -246,22 +247,24 @@
          <h4 id="language-variants-compilers">Query Languages</h4>
          <small>[<a href="providers.html#query-language-providers">learn more</a>]</small>
          <ul>
-            <li><a href="https://github.com/opencypher/cypher-for-gremlin">cypher-for-gremlin</a> - A Cypher to Gremlin traversal transpiler.</li>
+            <li><a href="https://github.com/opencypher/cypher-for-gremlin">cypher-for-gremlin</a> - A Cypher-to-Gremlin traversal transpiler.</li>
             <li><a href="http://syncleus.com/Ferma/">Ferma</a> (java/dsl) - An ORM / OGM for Apache TinkerPop.</li>
             <li><a href="https://github.com/davebshow/goblin">Goblin</a> (python/dsl) - Goblin OGM for the TinkerPop 3 Gremlin Server.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet">Gremlin.Net</a> (.NET - C#/variant) - Gremlin hosted in C# for use with any .NET-based VM.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-javascript">gremlin-javascript</a> (js) - Gremlin hosted in JavaScript for use with Node.js.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet">Gremlin.Net</a> (.NET - C#/variant) - Gremlin hosted in C# for use with any .NET-based VM.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-javascript">gremlin-javascript</a> (js) - Gremlin hosted in JavaScript for use with Node.js.</li>
             <li><a href="https://github.com/gremlin-orm/gremlin-orm">gremlin-orm</a> (javascript) Gremlin ORM for Node.js.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-python">gremlin-python</a> (python/variant) - Gremlin hosted in Python for use with any Python-based VM.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">gremlin-python</a> (python/variant) - Gremlin hosted in Python for use with any Python-based VM.</li>
             <li><a href="https://github.com/emehrkay/gremlinpy">gremlin-py</a> (python/variant) - Write pure Python Gremlin that can be sent to Gremlin Server.</li>
+            <li><a href="https://github.com/wolf4ood/gremlin-rs">gremlin-rs</a> (rust/variant) - A Gremlin Server driver and language variant for Rust.</li>
             <li><a href="https://github.com/mpollmeier/gremlin-scala">gremlin-scala</a> (scala/variant) - A Scala-based Gremlin language variant for TinkerPop3.</li>
             <li><a href="https://github.com/karthicks/gremlin-ogm">gremlin-objects</a> (java/dsl) - An Object Graph Mapping Library For Gremlin.</li>
             <li><a href="https://github.com/jbmusso/gremlin-template-string">gremlin-template-string</a> (js/variant) - A Gremlin language builder.</li>
+            <li><a href="https://github.com/debug-ito/greskell">greskell</a> (haskell/variant) - Haskell binding for Gremlin graph query language.</li>
             <li><a href="https://github.com/davebshow/ipython-gremlin">ipython-gremlin</a> (python/variant) - Gremlin in IPython and Jupyter.</li>
             <li><a href="https://github.com/pm-dev/kotlin-gremlin-ogm">kotlin-gremlin-ogm</a> (kotlin/dsl) - An Object Graph Mapping Library for Kotlin and Gremlin.</li>
             <li><a href="http://ogre.clojurewerkz.org/">ogre</a> (clojure/variant) - A Clojure language wrapper for TinkerPop3.</li>
             <li><a href="http://bayofmany.github.io/">Peapod</a> (java/dsl) - An object-graph-wrapper.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">sparql-gremlin</a> (sparql/distinct) - A SPARQL to Gremlin traversal compiler.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">sparql-gremlin</a> (sparql/distinct) - A SPARQL to Gremlin traversal compiler.</li>
             <li><a href="https://github.com/Microsoft/spring-data-gremlin">spring-data-gremlin</a> (java/dsl) - Spring Data support for TinkerPop-enabled graph systems.</li>
             <li><a href="https://github.com/twilmes/sql-gremlin">sql-gremlin</a> (sql/distinct) - An SQL to Gremlin traversal compiler.</li>
          </ul>
@@ -270,12 +273,13 @@
          <ul>
             <li><a href="https://github.com/davebshow/gremlinclient">gremlinclient</a> (python) - An asynchronous Python 2/3 client for Gremlin Server that allows for flexible coroutine syntax - Trollius, Tornado, Asyncio.</li>
             <li><a href="https://github.com/marcelocf/gremlin_client">gremlin_client</a> (ruby) - A Gremlin Server driver for Ruby.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#connecting-via-java">gremlin-driver</a> (java) - A Gremlin Server driver for Java.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#connecting-via-java">gremlin-driver</a> (java) - A Gremlin Server driver for Java.</li>
+            <li><a href="https://github.com/northwesternmutual/grammes">grammes</a> (go) - A strongly typed Gremlin server driver for Go.</li>
             <li><a href="https://github.com/qasaur/gremgo">gremgo</a> (go) - A Gremlin Server driver for Go.</li>
             <li><a href="https://github.com/Revmaker/gremlex">gremlex</a> (elixir) - A Gremlin Server driver for Elixir.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet">Gremlin.Net</a> (.NET - C#) - Gremlin Server driver for .NET.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet">Gremlin.Net</a> (.NET - C#) - Gremlin Server driver for .NET.</li>
             <li><a href="https://github.com/PommeVerte/gremlin-php">gremlin-php</a> (php) - A Gremlin Server driver for PHP.</li>
-            <li><a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-python">gremlin-python</a> (python) - Gremlin Server driver for Python.</li>
+            <li><a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">gremlin-python</a> (python) - Gremlin Server driver for Python.</li>
             <li><a href="http://gremlinrestclient.readthedocs.org/en/latest/">gremlinrestclient</a> (python) - Python 2/3 library that uses HTTP to communicate with the Gremlin Server over REST.</li>
             <li><a href="https://github.com/ExRam/ExRam.Gremlinq">Gremlinq</a> (.NET) - A strongly typed server driver.</li>
             <li><a href="https://github.com/windj007/python-gremlin-rest">python-gremlin-rest</a> (python) - A REST-based client for Gremlin Server.</li>
@@ -289,6 +293,8 @@
             <li><a href="https://www.exakat.io/">exakat.io</a> - Static analysis engine for PHP, powered by Gremlin.</li>
             <li><a href="https://bricaud.github.io/graphexp/graphexp.html">Graphexp</a> - Interactive visualization of the Gremlin graph database with D3.js.</li>
             <li><a href="https://github.com/bechbd/gremlin-ide">gremlin-ide</a> - An IDE for Apache TinkerPop-enabled databases using React and Electron.</li>
+            <li><a href="https://gremlify.com/">gremlify</a> - A Gremlin workspace for queries and visualization.</li>
+            <li><a href="https://github.com/prabushitha/gremlin-visualizer">Gremlin-Visualizer</a> A visualization tool for the results of gremlin traversals.</li>
             <li><a href="http://cambridge-intelligence.com/keylines/">KeyLines</a> - A JavaScript SDK for building powerful, custom and scalable graph visualization applications.</li>
             <li><a href="https://github.com/meltwater/jugri">JUGRI</a> - A Jupyter Gremlin interface.</li>
             <li><a href="http://linkurio.us/">Linkurious</a> - A browser-based graph visualization software to search, explore and visualize connected data.</li>
@@ -303,37 +309,34 @@
          development, testing, documentation, etc. skills to the group. These individuals contribute to TinkerPop beyond the ever-changing requirements of their day-to-day jobs and maintain
          responsibility for their contributions through time.
          <p/>
-         <!-- to be uncommented as necessary, just establishing the template -----------
          <h4 id="contributors-active">Active</h4>
-         -->
          <ul>
             <li><a href="http://markorodriguez.com">Marko A. Rodriguez</a> (2009 - PMC): Gremlin language, Gremlin machine, documentation.</li>
-            <li><a href="http://ketrinadrawsalot.tumblr.com">Ketrina Yim</a> (2009 - Committer): Illustrator, creator of Gremlin and his merry band of robots.</li>
+            <li><a href="https://www.linkedin.com/in/joshuashinavier/">Joshua Shinavier</a> (2009 - Committer): Graph data models, semantics, and interoperability</li>
             <li><a href="http://stephen.genoprime.com/">Stephen Mallette</a> (2011 - PMC Chair): Gremlin Console/Server/Driver, Language Variants and general core development.</li>
-            <li><a href="http://jamesthornton.com/">James Thornton</a> (2013 - PMC): Promotions, evangelism.</li>
             <li><a href="http://gremlin.guru">Daniel Kuppitz</a> (2014 - PMC): Gremlin language design, benchmarking, testing, documentation, mailing list support.</li>
-            <li><a href="https://www.linkedin.com/in/hzbarcea">Hadrian Zbarcea</a> (2015 - PMC): Project mentor, provider liason.</li>
-            <li><a href="https://github.com/Humbedooh">Daniel Gruno</a> (2015 - PMC): Project mentor, infrastructure liason.</li>
-            <li><a href="https://github.com/mhfrantz">Matt Frantz</a> (2015 - Committer): Gremlin language design, ts-tinkerpop.</li>
-            <li><a href="https://github.com/pluradj">Jason Plurad</a> (2015 - PMC): Gremlin Console/Server, mailing list support.</li>
-            <li><a href="https://www.linkedin.com/in/dylan-millikin-32567934">Dylan Millikin</a> (2015 - PMC): Gremlin Server/Driver, gremlin-php, GremlinBin, mailing list support.</li>
-            <li><a href="https://github.com/twilmes">Ted Wilmes</a> (2015 - PMC): Promotions, mailing list support, benchmarking, sql-gremlin.</li>
-            <li><a href="https://github.com/pietermartin">Pieter Martin</a> (2016 - Committer): Gremlin language, Sqlg.</li>
-            <li><a href="https://github.com/jbmusso">Jean-Baptiste Musso</a> (2016 - Committer): Gremlin Server testing, Gremlin Driver (Node.js/JavaScript), mailing list support.</li>
-            <li><a href="http://www.michaelpollmeier.com/">Michael Pollmeier</a> (2016 - Committer): Gremlin language, Gremlin-Scala.</li>
-            <li><a href="https://github.com/davebshow">David Brown</a> (2016 - Committer): Python libraries, Gremlin Server testing.</li>
             <li><a href="https://github.com/robertdale">Robert Dale</a> (2016 - PMC): Gremlin Console/Server, documentation, mailing list support.</li>
             <li><a href="https://github.com/jorgebay">Jorge Bay</a> (2017 - PMC): GraphBinary serialization, JavaScript and .NET libraries, mailing list support.</li>
             <li><a href="https://github.com/FlorianHockmann/">Florian Hockmann</a> (2017 - PMC): .NET libraries, mailing list support.</li>
             <li><a href="http://www.kelvinlawrence.net/">Kelvin Lawrence</a> (2017 - Committer): Documentation and mailing list support.</li>
             <li><a href="http://harshthakkar.in/">Harsh Thakkar</a> (2018 - Committer): Gremlin-SPARQL module.</li>
+            <li><a href="https://www.linkedin.com/in/divijvaidya/">Divij Vaidya</a> (2019 - Committer): Gremlin server-client interaction.</li>
          </ul>
-         <!-- to be uncommented as necessary, just establishing the template -----------
          <h4 id="contributors-inactive">Inactive</h4>
          <ul>
-            <li><a href="http://someone.com/">John Doe</a> (2015 - 2016): Committer/PMC, Module X, Module Y, mailing list support.</li>
+             <li><a href="http://ketrinadrawsalot.tumblr.com">Ketrina Yim</a> (2009 - Committer): Illustrator, creator of Gremlin and his merry band of robots.</li>
+             <li><a href="http://jamesthornton.com/">James Thornton</a> (2013 - PMC): Promotions, evangelism.</li>
+             <li><a href="https://www.linkedin.com/in/hzbarcea">Hadrian Zbarcea</a> (2015 - PMC): Project mentor, provider liason.</li>
+             <li><a href="https://github.com/Humbedooh">Daniel Gruno</a> (2015 - PMC): Project mentor, infrastructure liason.</li>
+             <li><a href="https://github.com/mhfrantz">Matt Frantz</a> (2015 - Committer): Gremlin language design, ts-tinkerpop.</li>
+             <li><a href="https://github.com/pluradj">Jason Plurad</a> (2015 - PMC): Gremlin Console/Server, mailing list support.</li>
+             <li><a href="https://www.linkedin.com/in/dylan-millikin-32567934">Dylan Millikin</a> (2015 - PMC): Gremlin Server/Driver, gremlin-php, GremlinBin, mailing list support.</li>
+             <li><a href="https://github.com/twilmes">Ted Wilmes</a> (2015 - PMC): Promotions, mailing list support, benchmarking, sql-gremlin.</li>
+             <li><a href="https://github.com/pietermartin">Pieter Martin</a> (2016 - Committer): Gremlin language, Sqlg.</li>
+             <li><a href="https://github.com/jbmusso">Jean-Baptiste Musso</a> (2016 - Committer): Gremlin Server testing, Gremlin Driver (Node.js/JavaScript), mailing list support.</li>
+             <li><a href="http://www.michaelpollmeier.com/">Michael Pollmeier</a> (2016 - Committer): Gremlin language, Gremlin-Scala.</li>
+             <li><a href="https://github.com/davebshow">David Brown</a> (2016 - Committer): Python libraries, Gremlin Server testing.</li>
          </ul>
-         -->
       </div>
    </div>
 </div>
diff --git a/docs/site/home/policy.html b/docs/site/home/policy.html
index b1d6bee..6247c86 100644
--- a/docs/site/home/policy.html
+++ b/docs/site/home/policy.html
@@ -27,9 +27,9 @@
       <h3>Provider Listing Policy</h3>
       <p>Graph system and language providers can have the project listed in two locations on the Apache TinkerPop homepage.
          The first location is on the homepage <a href="index.html">index.html</a>. The second is on the homepage <a href="providers.html">providers.html</a>. The policies
-         for each are provided below. Note that the Apache Software Foundation's <a href="http://www.apache.org/foundation/marks/linking">linking policy</a> supercede those
+         for each are provided below. Note that the Apache Software Foundation's <a href="https://www.apache.org/foundation/marks/linking">linking policy</a> supercede those
          stipulated by Apache TinkerPop. All things considered, if your project meets the requirements, please email Apache TinkerPop's
-         <a href="http://mail-archives.apache.org/mod_mbox/incubator-tinkerpop-dev/">developer mailing list</a> requesting that your project be added to a listing.
+         <a href="https://mail-archives.apache.org/mod_mbox/incubator-tinkerpop-dev/">developer mailing list</a> requesting that your project be added to a listing.
       </p>
       <h4>Index Listing Requirements</h4>
       <ul>
@@ -54,8 +54,8 @@
       <a name="graphic-usage-policy"></a>
       <h3>Graphic Usage Policy</h3>
       <p>Apache TinkerPop has a plethora of graphics that the community can use. There are four categories of graphics. These categories and their respective policies are presented
-         below. If you are unsure of the category of a particular graphic, please ask on our <a href="http://mail-archives.apache.org/mod_mbox/incubator-tinkerpop-dev/">developer mailing</a>
-         list before using it. Finally, note that the Apache Software Foundation's <a href="http://www.apache.org/foundation/marks/">trademark policies</a> supercede those stipulated
+         below. If you are unsure of the category of a particular graphic, please ask on our <a href="https://mail-archives.apache.org/mod_mbox/incubator-tinkerpop-dev/">developer mailing</a>
+         list before using it. Finally, note that the Apache Software Foundation's <a href="https://www.apache.org/foundation/marks/">trademark policies</a> supercede those stipulated
          by Apache TinkerPop.
       </p>
       <ul>
@@ -65,7 +65,7 @@
          <img src="img/policy/gremlin-gremopoly.png" style="padding:10px;width:10%;"/> <img src="img/policy/gremlin-gremreaper.png" style="padding:10px;width:14%;"/> <img src="img/policy/gremlin-chickenwing.png" style="padding:10px;width:10%;"/> <img src="img/policy/gremlin-no-more-mr-nice-guy.png" style="padding:10px;width:10%;"/> <img src="img/policy/gremlin-new-sheriff-in-town.png" style="padding:10px;width:12%;"/> <img src="img/policy/gremlin-gremstefani.png" style="padding:10px;width:10%;"/>
          <li><strong>Explanatory Diagrams</strong>: Explanatory diagrams can be used <em>without permission</em> as long as they are being used in an Apache TinkerPop related context, it is acknowledged that they are trademarks of the Apache Software Foundation/Apache TinkerPop, and are being used for technical explanatory purposes.</li>
          <img src="img/policy/olap-traversal.png" style="padding:10px;width:22%;"/> <img src="img/policy/cyclicpath-step.png" style="padding:10px;width:22%;"/> <img src="img/policy/flat-map-lambda.png" style="padding:10px;width:15%;"/> <img src="img/policy/adjacency-list.png" style="padding:10px;width:22%;"/>
-         <li><strong>Character Scene Graphics</strong>: Character scene graphics <u><em>require permission</em></u> before being used. Please ask for permission on the Apache TinkerPop <a href="http://mail-archives.apache.org/mod_mbox/incubator-tinkerpop-dev/">developer mailing list</a>.</li>
+         <li><strong>Character Scene Graphics</strong>: Character scene graphics <u><em>require permission</em></u> before being used. Please ask for permission on the Apache TinkerPop <a href="https://mail-archives.apache.org/mod_mbox/incubator-tinkerpop-dev/">developer mailing list</a>.</li>
          <img src="img/policy/tinkerpop-reading.png" style="padding:10px;width:20%;"/> <img src="img/policy/gremlintron.png" style="padding:10px;width:20%;"/> <img src="img/policy/business-gremlin.png" style="padding:10px;width:20%;"/> <img src="img/policy/tinkerpop3-splash.png" style="padding:10px;width:20%;"/>
       </ul>
    </div>
diff --git a/docs/site/home/providers.html b/docs/site/home/providers.html
index eba92cb..8f35ce9 100644
--- a/docs/site/home/providers.html
+++ b/docs/site/home/providers.html
@@ -26,7 +26,7 @@
    <div class="container">
       <div class="row">
          <div class="col-sm-10 col-md-10">
-            <p><a href="http://tinkerpop.apache.org">Apache TinkerPop</a> grows when 3<sup>rd</sup> party data systems and query languages utilize it. While Apache's distribution of TinkerPop
+            <p><a href="https://tinkerpop.apache.org">Apache TinkerPop</a> grows when 3<sup>rd</sup> party data systems and query languages utilize it. While Apache's distribution of TinkerPop
                does provide production ready implementations and tools, it is ultimately the larger ecosystem of providers that ensure TinkerPop's widespread adoption.
                There are two types of providers. The first are those that develop a (graph) database, (graph) processor, or (graph) analytics tool and want to
                offer their users TinkerPop-specific graph computing features. The other type of provider are language designers that have a (graph) query language they
@@ -41,7 +41,7 @@
    <div class="container">
       <a name="data-system-providers"></a>
       <h3>Data System Providers</h3>
-      <p>When a data system is TinkerPop-enabled, its users are able to model their domain as a graph and analyze that graph using the <a href="http://tinkerpop.apache.org/gremlin.html">Gremlin graph traversal language</a>. Furthermore, all
+      <p>When a data system is TinkerPop-enabled, its users are able to model their domain as a graph and analyze that graph using the <a href="https://tinkerpop.apache.org/gremlin.html">Gremlin graph traversal language</a>. Furthermore, all
          TinkerPop-enabled graph systems integrate with one another allowing providers to easily expand their system's offerings as well as allowing users to choose appropriate graph technology for their
          application. Sometimes an application is best served by an in-memory, transactional graph database. Sometimes a multi-machine distributed graph database will do the job. Or perhaps the
          application requires both a distributed graph database for real-time queries and, in parallel, a Big(Graph)Data processor for batch analytics.  Whatever the application's requirements, there
@@ -69,7 +69,7 @@
       <br/>
       <ol>
          <li><strong>The Graph (required)</strong>: These foundational interfaces define the semantics of the operations on a graph, vertex, edge, and property. Once implemented, the provider's
-            data system can immediately be queried using Gremlin OLTP. However, providers may want to leverage a collection of provider-specific compiler optimizations called <a href="http://tinkerpop.apache.org/docs/current/reference/#traversalstrategy">traversal strategies</a>
+            data system can immediately be queried using Gremlin OLTP. However, providers may want to leverage a collection of provider-specific compiler optimizations called <a href="https://tinkerpop.apache.org/docs/current/reference/#traversalstrategy">traversal strategies</a>
             which can leverage their system's unique features (e.g. global indices, vertex-centric indices, sort orders, sequential scanners, push-down predicates, etc.).
          </li>
          <br/>
@@ -79,7 +79,7 @@
             of TinkerPop).
          </li>
       </ol>
-      <p>Finally, there are other tools and technologies that the provider can leverage from TinkerPop such as <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-server">Gremlin Server</a>, <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin Console</a>, and the like. The purpose of Apache TinkerPop is to
+      <p>Finally, there are other tools and technologies that the provider can leverage from TinkerPop such as <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-server">Gremlin Server</a>, <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin Console</a>, and the like. The purpose of Apache TinkerPop is to
          make it easy for providers to add graph functionality to their system and/or to build a graph system from scratch and immediately have a query language, server infrastructure, metrics/reporting
          integration, cluster-based analytics and more.
       </p>
@@ -89,32 +89,32 @@
          </li>
          <li><strong>Gremlin traversal machine</strong>: Every Gremlin language variant compiles to a language agnostic <a href="https://en.wikipedia.org/wiki/Bytecode">bytecode</a> representation. That bytecode is ultimately translated to a machine-specific traversal. It is the responsibility of the Gremlin traversal machine to execute that traversal as a
             real-time <a href="https://en.wikipedia.org/wiki/Online_transaction_processing">OLTP</a> query or as an analytic <a href="https://en.wikipedia.org/wiki/Online_analytical_processing">OLAP</a> query (or both). Note that the Gremlin traversal machine is not bound to the Gremlin language. Any language can take advantage of the the
-            Gremlin traversal machine by simply translating itself to Gremlin bytecode. In fact, compilers currently exist for <a href="https://github.com/twilmes/sql-gremlin">SQL</a> and <a href="http://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">SPARQL</a>. However, using alternative languages for graph computing leads to significantly more complicated queries
+            Gremlin traversal machine by simply translating itself to Gremlin bytecode. In fact, compilers currently exist for <a href="https://github.com/twilmes/sql-gremlin">SQL</a> and <a href="https://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">SPARQL</a>. However, using alternative languages for graph computing leads to significantly more complicated queries
             and typically does not match the expressivity provided by Gremlin.
          </li>
-         <li><strong>TinkerGraph</strong>: TinkerPop provides a simple, non-transactional, in-memory graph system called <a href="http://tinkerpop.apache.org/docs/current/reference/#tinkergraph-gremlin">TinkerGraph</a>. TinkerGraph is useful for exploring graphs that can fit
+         <li><strong>TinkerGraph</strong>: TinkerPop provides a simple, non-transactional, in-memory graph system called <a href="https://tinkerpop.apache.org/docs/current/reference/#tinkergraph-gremlin">TinkerGraph</a>. TinkerGraph is useful for exploring graphs that can fit
             in-memory, for doing tutorials and training without the overhead of database setup, etc. TinkerGraph boasts both OLTP and OLAP traversal machine support.
          </li>
-         <li><strong>Gremlin Console</strong>: A command line <a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">REPL</a> is provided called <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin Console</a>. This console is useful when learning TinkerPop as users can load provided datasets into a
+         <li><strong>Gremlin Console</strong>: A command line <a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">REPL</a> is provided called <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin Console</a>. This console is useful when learning TinkerPop as users can load provided datasets into a
             graph system and explore the Gremlin language without the overhead of creating a full-blown software project. Furthermore, the Gremlin Console is used extensively in production scenarios
             because it allows system administrators to interact with a local or remote graph to gather statistics, manually explore the data to ensure data integrity, and other useful tasks.
          </li>
-         <li><strong>Gremlin Server</strong>: It is typical for a graph database to exist on a separate machine from the user's application code. <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-server">Gremlin Server</a> bridges the network-divide
+         <li><strong>Gremlin Server</strong>: It is typical for a graph database to exist on a separate machine from the user's application code. <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-server">Gremlin Server</a> bridges the network-divide
             allowing users to seamlessly submit traversals for remote execution over a web-sockets based binary protocol. If provider already has a server, they can leverage TinkerPop-specific
             components as needed (e.g. implement <code>RemoteConnection</code>). Gremlin Server also provides an HTTP-based API, support for <a href="http://ganglia.info/">Ganglia</a>/<a href="http://graphite.wikidot.com/">Graphite</a>/<a href="http://www.oracle.com/technetwork/articles/java/javamanagement-140525.html">JMX</a>/more
             metrics, and a traversal routing framework for intelligent data/traversal co-location within a distributed graph database's machine cluster.
          </li>
-         <li><strong>SparkGraphComputer</strong>: <a href="http://spark.apache.org/">Apache Spark</a>&trade; is a Big Data OLAP processor that simplifies the creation and execution of distributed data analytics.
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#sparkgraphcomputer"><code>SparkGraphComputer</code></a> turns Spark
+         <li><strong>SparkGraphComputer</strong>: <a href="https://spark.apache.org/">Apache Spark</a>&trade; is a Big Data OLAP processor that simplifies the creation and execution of distributed data analytics.
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#sparkgraphcomputer"><code>SparkGraphComputer</code></a> turns Spark
             into a Big(Graph)Data processor via the OLAP component of the Gremlin traversal machine. Users do not have to learn Spark's data processing language as Gremlin traversals execute
             over Spark. For graph system providers, they can boast Spark integration once a custom <code>InputRDD</code> (or <code>InputFormat</code>) is developed.
          </li>
-         <li><strong>Hadoop support</strong>: <a href="http://hadoop.apache.org/">Apache Hadoop</a>&reg; has become a staple technology for Big Data applications. In TinkerPop, <code>SparkGraphComputer</code> can pull data
+         <li><strong>Hadoop support</strong>: <a href="https://hadoop.apache.org/">Apache Hadoop</a>&reg; has become a staple technology for Big Data applications. In TinkerPop, <code>SparkGraphComputer</code> can pull data
             from the Hadoop File System (<a href="https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsUserGuide.html">HDFS</a>). TinkerPop provides a collection of Input- and OutputFormats for different graph serialization standards as well as tooling that makes it easy for users
-            to <a href="http://tinkerpop.apache.org/docs/current/reference/#interacting-with-hdfs">interact with HDFS</a> from the Gremlin Console or their application.
+            to <a href="https://tinkerpop.apache.org/docs/current/reference/#interacting-with-hdfs">interact with HDFS</a> from the Gremlin Console or their application.
          </li>
       </ul>
-      <p>Information on how to build implementations of the various interfaces that TinkerPop supports can be found in the <a href="http://tinkerpop.apache.org/docs/current/dev/provider/">Provider Documentation</a>.
+      <p>Information on how to build implementations of the various interfaces that TinkerPop supports can be found in the <a href="https://tinkerpop.apache.org/docs/current/dev/provider/">Provider Documentation</a>.
       <br/>
       <h4>TinkerPop-Enabled Graph Systems</h4>
       <br/>
@@ -135,8 +135,8 @@
       <br/>
       <div class="row">
           <div class="col-sm-6 col-md-6">
-            <a href="http://datastax.com/products/datastax-enterprise-graph"><img src="img/logos/datastax-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
-            <a href="http://datastax.com/products/datastax-enterprise-graph">DataStax Enterprise Graph</a>&trade;, part of DataStax Enterprise's multi-model platform, is a real-time graph database built for cloud applications that need to manage complex and highly connected data. Built on the foundation of Apache Cassandra and Apache TinkerPop, DataStax Enterprise Graph delivers continuous uptime along with predictable performance and scale, while remaining operationally simple to manage.
+            <a href="https://datastax.com/products/datastax-enterprise-graph"><img src="img/logos/datastax-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
+            <a href="https://datastax.com/products/datastax-enterprise-graph">DataStax Enterprise Graph</a>&trade;, part of DataStax Enterprise's multi-model platform, is a real-time graph database built for cloud applications that need to manage complex and highly connected data. Built on the foundation of Apache Cassandra and Apache TinkerPop, DataStax Enterprise Graph delivers continuous uptime along with predictable performance and scale, while remaining operationally simple to manage.
          </div>
          <div class="col-sm-6 col-md-6">
             <a href="https://grakn.ai/"><img src="img/logos/grakn-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
@@ -222,7 +222,7 @@
          <div class="col-sm-8 col-md-9">
             <br/>
             <strong>Distinct query language</strong>: Query languages such as SQL and SPARQL are significantly different from Gremlin in that they require a special purpose compiler in order to
-            generate a traversal. For this reason, <a href="https://github.com/twilmes/sql-gremlin">SQL</a> and <a href="http://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">SPARQL</a> Gremlin compilers
+            generate a traversal. For this reason, <a href="https://github.com/twilmes/sql-gremlin">SQL</a> and <a href="https://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">SPARQL</a> Gremlin compilers
             currently exist. Note that, within reason, Gremlin compilers do not need to concern themselves with an optimal compilation (only a semantically correct compilation) as the Gremlin
             traversal machine will leverage traversal strategies for both compile-time and runtime optimizations. Moreover, the language designer can rest assured that queries in their language
             will be able to evaluate as either an OLTP or OLAP query. The example on the right is a SPARQL query that determines the average rating for Gremlin's friends' projects. It is because
@@ -243,7 +243,7 @@
       <br/>
       <div class="row">
          <div class="col-sm-7 col-md-8">
-            <strong>Gremlin language variants</strong>: There are various <a href="http://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin language variants</a> such as <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>. These languages
+            <strong>Gremlin language variants</strong>: There are various <a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin language variants</a> such as <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>. These languages
             generate Gremlin bytecode utilizing the same naming/style-conventions as Gremlin-Java. However, where appropriate, they can deviate from convention in order to take advantage of the unique expressive qualities of the host language. For instance, Gremlin-Python supports index slices, attribute access, etc.
          </div>
          <div class="col-sm-5 col-md-4">
@@ -275,23 +275,23 @@
       <br/>
       <div class="row">
          <div class="col-sm-6 col-md-6">
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-console"><img src="img/logos/gremlin-groovy-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin-Groovy</a> represents Gremlin inside the Groovy language and can be leveraged by any JVM-based project either through gmaven or its JSR-223 ScriptEngine implementation. It also serves as the Gremlin Console language.
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-console"><img src="img/logos/gremlin-groovy-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-console">Gremlin-Groovy</a> represents Gremlin inside the Groovy language and can be leveraged by any JVM-based project either through gmaven or its JSR-223 ScriptEngine implementation. It also serves as the Gremlin Console language.
          </div>
          <div class="col-sm-6 col-md-6">
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#_on_gremlin_language_variants"><img src="img/logos/gremlin-java-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#_on_gremlin_language_variants">Gremlin-Java</a> represents Gremlin inside the Java8 language. Gremlin-Java is considered the canonical, reference implementation of Gremlin and is the primary compiler for all lambda-free bytecode due to its speed relative to other script-based, JVM variants.
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#_on_gremlin_language_variants"><img src="img/logos/gremlin-java-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#_on_gremlin_language_variants">Gremlin-Java</a> represents Gremlin inside the Java language. Gremlin-Java is considered the canonical, reference implementation of Gremlin and is the primary compiler for all lambda-free bytecode due to its speed relative to other script-based, JVM variants.
          </div>
       </div>
       <br/>
       <div class="row">
          <div class="col-sm-6 col-md-6">
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-python"><img src="img/logos/gremlin-python-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a> represents Gremlin inside the Python language and can be used by any Python virtual machine such as CPython and Jython. Gremlin-Python traversals translate to Gremlin bytecode for RemoteConnection execution (e.g. Gremlin Server).
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python"><img src="img/logos/gremlin-python-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a> represents Gremlin inside the Python language and can be used by any Python virtual machine such as CPython. Gremlin-Python traversals translate to Gremlin bytecode for RemoteConnection execution (e.g. Gremlin Server).
          </div>
          <div class="col-sm-6 col-md-6">
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet"><img src="img/logos/gremlin-dotnet-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet">Gremlin.Net</a> represents Gremlin inside the C# language and can be used by any .NET-based project. Gremlin.Net traversals translate to Gremlin bytecode for RemoteConnection execution (e.g. Gremlin Server).
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet"><img src="img/logos/gremlin-dotnet-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet">Gremlin.Net</a> represents Gremlin inside the C# language and can be used by any .NET-based project. Gremlin.Net traversals translate to Gremlin bytecode for RemoteConnection execution (e.g. Gremlin Server).
          </div>
       </div>
       <br/>
@@ -308,8 +308,8 @@
       <br/>
       <div class="row">
          <div class="col-sm-6 col-md-6">
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin"><img src="img/logos/sparql-gremlin-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
-            <a href="http://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">SPARQL-Gremlin</a> is a compiler used to transform SPARQL queries into Gremlin bytecode. It is based on the Apache Jena SPARQL processor ARQ, which provides access to a syntax tree of a SPARQL query.
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin"><img src="img/logos/sparql-gremlin-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
+            <a href="https://tinkerpop.apache.org/docs/current/reference/#sparql-gremlin">SPARQL-Gremlin</a> is a compiler used to transform SPARQL queries into Gremlin bytecode. It is based on the Apache Jena SPARQL processor ARQ, which provides access to a syntax tree of a SPARQL query.
          </div>
          <div class="col-sm-6 col-md-6">
             <a href="https://github.com/twilmes/sql-gremlin"><img src="img/logos/sql-gremlin-logo.png" style="padding-right:20px;float:left;width:35%;"></a>
diff --git a/docs/site/home/template/header-footer.html b/docs/site/home/template/header-footer.html
index 1947063..4c198db 100644
--- a/docs/site/home/template/header-footer.html
+++ b/docs/site/home/template/header-footer.html
@@ -26,7 +26,7 @@
       <meta http-equiv="X-UA-Compatible" content="IE=edge">
       <meta name="viewport" content="width=device-width, initial-scale=1">
       <title>Apache TinkerPop</title>
-      <meta name="description" content="A Graph Computing Framework">
+      <meta name="description" content="Apache TinkerPop: A Graph Computing Framework">
       <meta name="author" content="Apache TinkerPop">
       <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
       <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
@@ -65,7 +65,7 @@
             <span class="icon-bar"></span>
             <span class="icon-bar"></span>
             </button>
-            <a class="navbar-brand" href="http://tinkerpop.apache.org"><font face="american typewriter"><b>Apache TinkerPop</b></font></a>
+            <a class="navbar-brand" href="https://tinkerpop.apache.org"><font face="american typewriter"><b>Apache TinkerPop</b></font></a>
          </div>
          <div id="navbar-collapse-1" class="collapse navbar-collapse">
             <ul class="nav navbar-nav">
@@ -75,32 +75,32 @@
                   Documentation <b class="caret"></b>
                   </a>
                   <ul class="dropdown-menu">
-                     <li class="dropdown-header">Latest: 3.4.2 (28-May-2019)</li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current">TinkerPop 3.4.2</a></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/upgrade">Upgrade Information</a></li>
-                     <li><a href="http://tinkerpop.apache.org/javadocs/current/core/">Core Javadoc API</a></li>
-                     <li><a href="http://tinkerpop.apache.org/javadocs/current/full/">Full Javadoc API</a></li>
+                     <li class="dropdown-header">Latest: 3.4.8 (3-Aug-2020)</li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current">TinkerPop 3.4.8</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/upgrade">Upgrade Information</a></li>
+                     <li><a href="https://tinkerpop.apache.org/javadocs/current/core/">Core Javadoc API</a></li>
+                     <li><a href="https://tinkerpop.apache.org/javadocs/current/full/">Full Javadoc API</a></li>
                      <li role="separator" class="divider"></li>
-                     <li class="dropdown-header">Maintenance: 3.3.7 (28-May-2019)</li>
-                     <li><a href="http://tinkerpop.apache.org/docs/3.3.7/">TinkerPop 3.3.6</a></li>
-                     <li><a href="http://tinkerpop.apache.org/javadocs/3.3.7/core/">Core Javadoc API</a></li>
-                     <li><a href="http://tinkerpop.apache.org/javadocs/3.3.7/full/">Full Javadoc API</a></li>
+                     <li class="dropdown-header">Maintenance: 3.3.11 (1-Jun-2020)</li>
+                     <li><a href="https://tinkerpop.apache.org/docs/3.3.11/">TinkerPop 3.3.11</a></li>
+                     <li><a href="https://tinkerpop.apache.org/javadocs/3.3.11/core/">Core Javadoc API</a></li>
+                     <li><a href="https://tinkerpop.apache.org/javadocs/3.3.11/full/">Full Javadoc API</a></li>
                      <li role="separator" class="divider"></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/">Documentation Archives</a></li>
-                     <li><a href="http://tinkerpop.apache.org/javadocs/">Javadoc Archives</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/">Documentation Archives</a></li>
+                     <li><a href="https://tinkerpop.apache.org/javadocs/">Javadoc Archives</a></li>
                      <li role="separator" class="divider"></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/index.html#publications">Publications</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/index.html#publications">Publications</a></li>
                   </ul>
                </li>
                <li class="dropdown">
                   <a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
                   <ul class="dropdown-menu">
                      <li><a href="gremlin.html">Introduction to Gremlin</a></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/tutorials/getting-started/">Getting Started</a></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The Gremlin Console</a></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/recipes/">Gremlin Recipes</a></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin Language Variants</a></li>
-                     <li><a href="http://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's Anatomy</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/getting-started/">Getting Started</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The Gremlin Console</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/recipes/">Gremlin Recipes</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin Language Variants</a></li>
+                     <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's Anatomy</a></li>
                      <li role="separator" class="divider"></li>
                      <li><a href="http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html">Book: Practical Gremlin by Kelvin Lawrence</a></li>
                      <li><a href="http://sql2gremlin.com/">SQL2Gremlin</a></li>
@@ -128,12 +128,12 @@
                   Apache Software Foundation <b class="caret"></b>
                   </a>
                   <ul class="dropdown-menu">
-                     <li><a href="http://www.apache.org/">Apache Homepage</a></li>
-                     <li><a href="http://www.apache.org/licenses/">License</a></li>
+                     <li><a href="https://www.apache.org/">Apache Homepage</a></li>
+                     <li><a href="https://www.apache.org/licenses/">License</a></li>
                      <li><a href="https://www.apache.org/events/current-event">Events</a></li>
-                     <li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
-                     <li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
-                     <li><a href="http://www.apache.org/security/">Security</a></li>
+                     <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
+                     <li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
+                     <li><a href="https://www.apache.org/security/">Security</a></li>
                   </ul>
                </li>
             </ul>
@@ -142,7 +142,7 @@
       !!!!!BODY!!!!!
       <div id="footer">
          <div class="container">
-            <p class="muted credit">Copyright © 2015-2019 The Apache Software Foundation.<br/>Apache TinkerPop, TinkerPop, Apache, Apache feather logo, and Apache TinkerPop project logo are either registered trademarks or trademarks of <a href="http://www.apache.org/">The Apache Software Foundation</a> in the United States and other countries.
+            <p class="muted credit">Copyright © 2015-2019 The Apache Software Foundation.<br/>Apache TinkerPop, TinkerPop, Apache, Apache feather logo, and Apache TinkerPop project logo are either registered trademarks or trademarks of <a href="https://www.apache.org/">The Apache Software Foundation</a> in the United States and other countries.
             </p>
          </div>
       </div>
diff --git a/docs/src/dev/developer/development-environment.asciidoc b/docs/src/dev/developer/development-environment.asciidoc
index c02dea8..b2fea52 100644
--- a/docs/src/dev/developer/development-environment.asciidoc
+++ b/docs/src/dev/developer/development-environment.asciidoc
@@ -26,8 +26,10 @@
 [[system-configuration]]
 == System Configuration
 
-At a minimum, development of TinkerPop requires link:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html[Java 1.8.0_40+]
-and link:https://maven.apache.org/download.cgi[Maven 3.2.5+]. Maven is used as the common build system, which even
+At a minimum, development of TinkerPop requires link:https://openjdk.java.net/projects/jdk8/[Java 8] but it is
+preferable to use link:https://openjdk.java.net/projects/jdk/11/[Java 11] cross-compiled to Java 8 (the
+cross-compilation happens automatically as part of the build). Maven (requiring a minimum of
+link:https://maven.apache.org/download.cgi[Maven 3.3.9+]) is used as the common build system, which even
 controls the builds of non-JVM link:https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/[GLVs]
 such as `gremlin-python`. Java and Maven are described as a "minimum" for a development environment, because they
 will only build JVM portions of TinkerPop and many integration tests will not fire with this simple setup. It is
@@ -37,6 +39,9 @@
 To gain the ability to execute all aspects of the TinkerPop build system, other environmental configurations must be
 established. Those prerequisites are defined in the following subsections.
 
+IMPORTANT: Use Java 11 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
 when submitting a pull request. Consider setting up the full environment.
 
@@ -107,11 +112,32 @@
 scripts should work on Mac and Linux.
 
 To generate documentation, it is required that link:https://hadoop.apache.org[Hadoop 2.7.x] is running in
-link:https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/SingleCluster.html#Pseudo-Distributed_Operation[pseudo-distributed]
+link:https://hadoop.apache.org/docs/r2.7.7/hadoop-project-dist/hadoop-common/SingleCluster.html#Pseudo-Distributed_Operation[pseudo-distributed]
 mode. Be sure to set the `HADOOP_GREMLIN_LIBS` environment variable as described in the
 link:https://tinkerpop.apache.org/docs/current/reference/#hadoop-gremlin[reference documentation]. It is also important
 to set the `CLASSPATH` to point at the directory containing the Hadoop configuration files, like `mapred-site.xml`.
 
+The `/etc/hadoop/yarn-site.xml` file prefers this configuration over the one provided in the Hadoop documentation
+referenced above:
+
+[source,xml]
+----
+<configuration>
+    <property>
+        <name>yarn.nodemanager.aux-services</name>
+        <value>mapreduce_shuffle</value>
+    </property>
+    <property>
+        <name>yarn.nodemanager.vmem-check-enabled</name>
+        <value>false</value>
+    </property>
+    <property>
+        <name>yarn.nodemanager.vmem-pmem-ratio</name>
+        <value>4</value>
+    </property>
+</configuration>
+----
+
 Also note that link:http://www.grymoire.com/Unix/Awk.html[awk] version `4.0.1` is required for documentation generation.
 
 Documentation can be generated locally with:
@@ -138,8 +164,13 @@
 Java tests that require Python code will be skipped. Developers should also install link:https://pypi.python.org/pypi/pip[pip]
 and link:https://virtualenv.pypa.io/en/stable/[virtualenv] (version 15.0.2 - older versions may cause build failures).
 
-The build expects two Python executables `python` and `python3` where `python` maps to 2.7.6 and `python3` is 3.4.3 or
-higher. Once the Python environment is established, the full building and testing of `gremlin-python` may commence. It
+The build expects Python a `python3` installation which should be 3.5.3 or better. Python also tests kerberos and
+therefore requires:
+
+[source,text]
+sudo apt install libkrb5-dev krb5-user
+
+Once the Python environment is established, the full building and testing of `gremlin-python` may commence. It
 can be done manually from the command line with:
 
 [source,text]
@@ -149,10 +180,10 @@
 `gremlin-python` module which will signify to Maven that the environment is Python-ready. The `.glv` file need not have
 any contents and is ignored by Git. A standard `mvn clean install` will then build `gremlin-python` in full.
 
-As of TinkerPop 3.2.5, the build also requires Python to execute `gremlin-console` integration tests. The integration
-test is configured by a "console-integration-tests" Maven profile. This profile can be activated manually or can more
-simply piggy-back on the `.glv` file in `gremlin-python`. Note that unlike `gremlin-python` the tests are actually
-integration tests and therefore must be actively switched on with `-DskipIntegrationTests=false`:
+The build also requires Python to execute `gremlin-console` integration tests. The integration test is configured by a
+"console-integration-tests" Maven profile. This profile can be activated manually or can more simply piggy-back on
+the `.glv` file in `gremlin-python`. Note that unlike `gremlin-python` the tests are actually integration tests and
+therefore must be actively switched on with `-DskipIntegrationTests=false`:
 
 [source,text]
 mvn clean install -pl gremlin-console -DskipIntegrationTests=false
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index 5519795..8f7b63d 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -99,7 +99,7 @@
 * `3.0-dev` - 3.0.x (no longer maintained)
 * `3.1-dev` - 3.1.x (no longer maintained)
 * `3.2-dev` - 3.2.x (no longer maintained)
-* `3.3-dev` - 3.3.x (major bug fixes only)
+* `3.3-dev` - 3.3.x (no longer maintained)
 * `3.4-dev` - 3.4.x (current development)
 * `master` - 3.5.x (future development)
 * `4.0-dev` - 4.0.x (future development)
@@ -232,7 +232,7 @@
 ** `get_g_V_groupCount_byXnameX()`
 ** `get_g_V_groupCountXaX_byXnameX_capXaX()`
 * The name of the actual test case should be the name of the traversal generator minus the `get_` prefix.
-* The Gremlin-Groovy version of the test should use the sugar syntax in order to test sugar (as Gremlin-Java8 tests test standard syntax).
+* The Gremlin-Groovy version of the test should use the sugar syntax in order to test sugar (as Gremlin-Java tests test standard syntax).
 ** `g.V.age.sum`
 * Avoid using lambdas in the test case unless that is explicitly what is being tested as OLAP systems will typically not be able to execute those tests.
 * `AbstractGremlinProcessTest` has various static methods to make writing a test case easy.
diff --git a/docs/src/dev/developer/release.asciidoc b/docs/src/dev/developer/release.asciidoc
index 677e5f9..823d8c6 100644
--- a/docs/src/dev/developer/release.asciidoc
+++ b/docs/src/dev/developer/release.asciidoc
@@ -144,12 +144,18 @@
 . `docker/build.sh -t -i -n`
 . `bin/publish-docs.sh <username>` - note that under a release candidate the documentation is published as SNAPSHOT
 . `mvn versions:set -DnewVersion=xx.yy.zz -DgenerateBackupPoms=false` to update the project files to reference a non-SNAPSHOT version
+. `mvn clean install -DskipTests` to update GLV versions
+.. Review `Gremlin.Net.csproj`, `Gremlin.Net.Template.csproj` and `Gremlin.Net.Template.nuspec` in `gremlin-dotnet`
+.. Review `package.json` in `gremlin-javascript`
 . `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-standalone/bin/gremlin.sh gremlin.sh; popd`
 . `git diff` and review the updated files
 . `git commit -a -m "TinkerPop xx.yy.zz release"` and `git push`
 . `git tag -a -m "TinkerPop xx.yy.zz release" xx.yy.zz` and `git push --tags`
 . `mvn clean install`
 . `mvn versions:set -DnewVersion=xx.yy.zz-SNAPSHOT -DgenerateBackupPoms=false` to go back to SNAPSHOT
+. `mvn clean install -DskipTests` to update GLV versions
+.. Review `Gremlin.Net.csproj`, `Gremlin.Net.Template.csproj` and `Gremlin.Net.Template.nuspec` in `gremlin-dotnet`
+.. Review `package.json` in `gremlin-javascript`
 . `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-SNAPSHOT-standalone/bin/gremlin.sh gremlin.sh; popd`
 . `git commit -a -m "Returned to xx.yy.zz-SNAPSHOT"` and `git push`
 . Announce the release candidate to `dev` mailing list and await feedback
@@ -205,6 +211,9 @@
 as accurate as possible and the release tags are present).
 .. Preview changes locally with `bin/generate-home.sh` then commit changes to git.
 . `mvn versions:set -DnewVersion=xx.yy.zz -DgenerateBackupPoms=false` to update project files to reference the non-SNAPSHOT version
+. `mvn clean install -DskipTests` to update GLV versions
+.. Review `Gremlin.Net.csproj`, `Gremlin.Net.Template.csproj` and `Gremlin.Net.Template.nuspec` in `gremlin-dotnet`
+.. Review `package.json` in `gremlin-javascript`
 . `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-standalone/bin/gremlin.sh gremlin.sh; popd`
 . `git diff` and review the updated files
 . `mvn clean install` - need to build first so that the right version of the console is used with `bin/publish-docs.sh`
@@ -280,6 +289,9 @@
 . Prepare Git administration tasks. Apply the following steps as needed per release branch:
 .. Make the appropriate branching changes as required by the release and bump the version to `SNAPSHOT` with
 `mvn versions:set -DnewVersion=xx.yy.zz-SNAPSHOT -DgenerateBackupPoms=false`.
+. `mvn clean install -DskipTests` to update GLV versions
+.. Review `Gremlin.Net.csproj`, `Gremlin.Net.Template.csproj` and `Gremlin.Net.Template.nuspec` in `gremlin-dotnet`
+.. Review `package.json` in `gremlin-javascript`
 .. `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-SNAPSHOT-standalone/bin/gremlin.sh gremlin.sh; popd`
 .. Update CHANGELOG and upgrade docs to have the appropriate headers for the next version.
 .. `mvn clean install -DskipTests` - need to build first so that the right version of the console is used with `bin/publish-docs.sh`
diff --git a/docs/src/dev/io/gryo.asciidoc b/docs/src/dev/io/gryo.asciidoc
index e06fcc2..15bafd2 100644
--- a/docs/src/dev/io/gryo.asciidoc
+++ b/docs/src/dev/io/gryo.asciidoc
@@ -25,7 +25,7 @@
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.gryo.*
 import org.apache.tinkerpop.gremlin.structure.io.*
-import org.apache.commons.configuration.BaseConfiguration
+import org.apache.commons.configuration2.BaseConfiguration
 import java.time.*
 
 new File("io-output/dev-docs/").mkdirs()
@@ -157,7 +157,8 @@
 side, newer release of TinkerPop are fully backward compatible with Gryo produced on older versions of TinkerPop.
 
 As of TinkerPop 3.3.0, there is now a new version of Gryo in 3.0 that is only partially compatible with 1.0. Attempts
-to use 3.0 serializers with 1.0 serializers will likely lead to failure.
+to use 3.0 serializers with 1.0 serializers will likely lead to failure. For best results, users should always
+utilize the same version of TinkerPop on the client as on the server.
 
 Both versions of Gryo support all the types defined by GraphSON as well as others that are bound more specifically
 to the JVM. The link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java[GryoVersion]
diff --git a/docs/src/dev/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc
index 863a799..02162a4 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -39,7 +39,7 @@
 [[graph-system-provider-requirements]]
 == Graph System Provider Requirements
 
-image:tinkerpop-enabled.png[width=140,float=left] At the core of TinkerPop 3.x is a Java8 API. The implementation of this
+image:tinkerpop-enabled.png[width=140,float=left] At the core of TinkerPop 3.x is a Java API. The implementation of this
 core API and its validation via the `gremlin-test` suite is all that is required of a graph system provider wishing to
 provide a TinkerPop-enabled graph engine. Once a graph system has a valid implementation, then all the applications
 provided by TinkerPop (e.g. Gremlin Console, Gremlin Server, etc.) and 3rd-party developers (e.g. Gremlin-Scala,
@@ -79,7 +79,7 @@
 `Graph.addVertex(Object...)` or `Vertex.addEdge(String,Vertex,Object...)`, the respective element is created along
 with the provided key/value pair properties appended to it.
 
-Below is a sequence of basic graph mutation operations represented in Java 8.
+Below is a sequence of basic graph mutation operations represented in Java:
 
 image:basic-mutation.png[width=240,float=right]
 [source,java]
@@ -1023,14 +1023,13 @@
 !Key !Description
 !`authentication` !A request that contains the response to a server challenge for authentication.
 !`eval` !Evaluate a Gremlin script provided as a `String`.
-!`close` !Close the specified session. Will return a `NO CONTENT` message as confirmation of the close being completed.
 |=========================================================
 
-NOTE: The "close" message is deprecated as of 3.3.11 as servers at this version are required to automatically interrupt
-running processes on the close of the connection and release resources such as sessions. Servers wishing to be
-compatible with older versions of the driver need only send back a `NO_CONTENT` for this message. Drivers wishing to
-be compatible with servers prior to 3.3.11 may continue to send the message on calls to `close()` otherwise such code
-can be removed.
+NOTE: There was a "close" message related to sessions that was deprecated as of 3.3.11. It's functionality was removed
+in 3.5.0. Servers wishing to be compatible with older versions of the driver need only send back a `NO_CONTENT` for
+this message (which is what Gremlin Server does as of 3.5.0). Drivers wishing to be compatible with servers prior to
+3.3.11 may continue to send the message on calls to `close()` (TinkerPop drivers no longer do that as of 3.5.0)
+otherwise such code can be removed.
 
 **`authentication` operation arguments**
 
@@ -1112,14 +1111,6 @@
 unroll it to represent the actual number of times it exists when iterated. The unrolling is typically handled
 directly within TinkerPop's remote traversal implementations.
 
-One of the important aspects of the Traversal OpProcessor is that it enables the user to not only get the results of
-the `Traversal` but also the side-effects that it produces. When the `Traversal` is submitted with the "bytecode"
-operation, the results are iterated back as usual, but any side-effects are retained on the server in a cache keyed by
-the identifier of the request that originally submitted the `Traversal`. The client will want to retain that identifier
-if it intends to later get side-effects. The Traversal OpProcessor supplies the "keys" and "gather" operations to get
-the keys stored in the side-effect and to get the value of a specific side-effect respectively. Finally, a "close"
-operation is available to clear the cache of a specific side-effect.
-
 [width="100%",cols="3,10a",options="header"]
 |=========================================================
 |Key |Description
@@ -1130,9 +1121,6 @@
 !Key !Description
 !`authentication` !A request that contains the response to a server challenge for authentication.
 !`bytecode` !A request that contains the `Bytecode` representation of a `Traversal`.
-!`close` !Releases side-effects held in cache for a particular `Traversal`.
-!`gather` !Gets a particular side-effect as produced by a previously executed `Traversal`.
-!`keys` !Gets all the keys of all side-effects as produced by a previously executed `Traversal`.
 |=========================================================
 
 **`authentication` operation arguments**
@@ -1159,45 +1147,6 @@
 single alias).
 |=========================================================
 
-**`close` operation arguments**
-
-[width="100%",cols="2,2,9",options="header"]
-|=========================================================
-|Key |Type |Description
-|sideEffect |UUID | *Required* The unique identifier for the request that original submitted the traversal (side-effects are keyed by that value)
-|=========================================================
-
-**`gather` operation arguments**
-
-[width="100%",cols="2,2,9",options="header"]
-|=========================================================
-|Key |Type |Description
-|sideEffect |UUID | *Required* The unique identifier for the request that original submitted the traversal (side-effects are keyed by that value)
-|sideEffectKey |String | *Required* The key for a specific side-effect.
-|aliases |Map | *Required* A map with a single key/value pair that refers to a globally bound `TraversalSource` object
-to be aliased to different variable names for purposes of the current request.  The value represents the name of the
-global variable and its key represents the new binding name as it will be referenced in the Gremlin query.  For
-example, if the Gremlin Server defines two `TraversalSource` instances named `g1`, it would be possible
-to send an alias pair with key of "g" and value of "g1" and thus allow the script to refer to "g1" simply as "g". Note
-that unlike users of `alias` in other contexts, in this case, the key can *only* be set to "g" and there can be only
-one key value pair present (since only one `Traversal` is being submitted, there is no sense to having more than a
-single alias).
-|=========================================================
-
-When using "gather" it is important to note the metadata that is returned on the `ResponseMessage`. It returns both the
-"sideEffectKey" that was requested as well as a value keyed as "aggregateTo". The "aggregateTo" field describes how the
-streamed side-effect data should be treated on the client. It provides a hint as to whether or not the data should be
-rolled back up into a single object or simply left as-is. There are four values for "aggregateTo": `bulkset`, `list`,
-`map`, `set` and `none`.
-
-**`keys` operation arguments**
-
-[width="100%",cols="2,2,9",options="header"]
-|=========================================================
-|Key |Type |Description
-|sideEffect |UUID | *Required* The unique identifier for the request that original submitted the traversal (side-effects are keyed by that value)
-|=========================================================
-
 === Authentication
 
 Gremlin Server supports link:https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL-based]
diff --git a/docs/src/recipes/anti-patterns.asciidoc b/docs/src/recipes/anti-patterns.asciidoc
index a9b3abc..16a623c 100644
--- a/docs/src/recipes/anti-patterns.asciidoc
+++ b/docs/src/recipes/anti-patterns.asciidoc
@@ -56,7 +56,7 @@
           from("p${relation.from}").
           to("p${relation.to}")
 } ; []
-traversalAsString = org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslator.of("g").translate(t.bytecode) ; []
+traversalAsString = org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslator.of("g").translate(t.bytecode).getScript() ; []
 [ "Traversal String Length": traversalAsString.length()
 , "Traversal Preview": traversalAsString.replaceFirst(/^(.{104}).*(.{64})$/, '$1 ... $2') ]
 ----
@@ -228,9 +228,12 @@
 [[steps-instead-of-tokens]]
 == Steps Instead of Tokens
 
-When child traversals contain a single step, there's a good chance that the step can be replaced with a token. These tokens are translated
-into optimized traversals that execute much faster then their step traversal pendants. A few examples of single step child traversals are
-shown in the following code block.
+NOTE: As of 3.5.0, `ByModulatorOptimizationStrategy` is present to automatically translate this anti-pattern to their
+more performant versions for most cases however, it is still best to write Gremlin according to the contents that follow.
+
+When child traversals contain a single step, there's a good chance that the step can be replaced with a token. These
+tokens are translated into optimized traversals that execute much faster then their step traversal pendants. A few
+examples of single step child traversals are shown in the following code block.
 
 [gremlin-groovy,modern]
 ----
@@ -260,33 +263,3 @@
 
 <1> Note, that tokens use a `fold()` reducer by default.
 <2> `by("name")` doesn't use a token, but falls into the same category as the String `"name"` is translated into an optimized traversal.
-
-But this is not all about readability; as initially mentioned, the use of tokens also improves the overall query performance as shown in
-the `profile()` output below.
-
-[gremlin-groovy,existing]
-----
-g.V().groupCount().by(label()).profile()               // not using token
-g.V().groupCount().by(label).profile()                 // using a token
-g.V().group().by(label()).by(id().fold()).profile()    // not using tokens
-g.V().group().by(label).by(id).profile()               // using tokens
-g.V().project("id","label").
-    by(id()).
-    by(label()).profile()                              // not using tokens
-g.V().project("id","label").
-    by(id).
-    by(label).profile()                                // using tokens
-g.V().choose(label()).
-    option("person", project("person").by(values("name"))).
-    option("software", project("product").by(values("name"))).
-  profile()                                            // not using tokens
-g.V().choose(label).
-    option("person", project("person").by("name")).
-    option("software", project("product").by("name")).
-  profile()                                            // using tokens
-----
-
-NOTE: Pay attention to all metrics. The time difference does not always look significant, sometimes it might even be worse in the
-optimized query, but that's usually because TinkerGraph keeps everything in memory and thus even bad queries can sometimes perform
-surprisingly well. The more important metrics, however, are the number of traversers that are used and the overall number of
-generated steps.
diff --git a/docs/src/recipes/centrality.asciidoc b/docs/src/recipes/centrality.asciidoc
index c5e19a2..79d5f01 100644
--- a/docs/src/recipes/centrality.asciidoc
+++ b/docs/src/recipes/centrality.asciidoc
@@ -185,5 +185,5 @@
 [gremlin-groovy,modern]
 ----
 g = traversal().withEmbedded(graph).withComputer()
-g.V().pageRank().by('pageRank').values('pageRank')
+g.V().pageRank().with(PageRank.propertyName,'pageRank').values('pageRank')
 ----
diff --git a/docs/src/recipes/olap-spark-yarn.asciidoc b/docs/src/recipes/olap-spark-yarn.asciidoc
index f5e8558..64cc6a0 100644
--- a/docs/src/recipes/olap-spark-yarn.asciidoc
+++ b/docs/src/recipes/olap-spark-yarn.asciidoc
@@ -63,8 +63,8 @@
 #!/bin/bash
 # Variables to be adapted to the actual environment
 GREMLIN_HOME=/home/yourdir/lib/apache-tinkerpop-gremlin-console-x.y.z-standalone
-export HADOOP_HOME=/usr/local/lib/hadoop-2.7.2
-export HADOOP_CONF_DIR=/usr/local/lib/hadoop-2.7.2/etc/hadoop
+export HADOOP_HOME=/usr/local/lib/hadoop-2.7.7
+export HADOOP_CONF_DIR=/usr/local/lib/hadoop-2.7.7/etc/hadoop
 
 # Have TinkerPop find the hadoop cluster configs and hadoop native libraries
 export CLASSPATH=$HADOOP_CONF_DIR
@@ -94,7 +94,7 @@
 archive = 'spark-gremlin.zip'
 archivePath = "/tmp/$archive"
 ['bash', '-c', "rm -f $archivePath; cd ext/spark-gremlin/lib && zip $archivePath *.jar"].execute().waitFor()
-conf = new PropertiesConfiguration('conf/hadoop/hadoop-gryo.properties')
+conf = new Configurations().properties(new File('conf/hadoop/hadoop-gryo.properties'))
 conf.setProperty('spark.master', 'yarn')
 conf.setProperty('spark.submit.deployMode', 'client')
 conf.setProperty('spark.yarn.archive', "$archivePath")
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 0617aab..6aa95f7 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -475,15 +475,10 @@
 [INFO] OpLoader - Adding the standard OpProcessor.
 [INFO] OpLoader - Adding the session OpProcessor.
 [INFO] OpLoader - Adding the traversal OpProcessor.
-[INFO] TraversalOpProcessor - Initialized cache for TraversalOpProcessor with size 1000 and expiration time of 600000 ms
 [INFO] GremlinServer - Executing start up LifeCycleHook
 [INFO] Logger$info - Loading 'modern' graph data.
 [INFO] GremlinServer - idleConnectionTimeout was set to 0 which resolves to 0 seconds when configuring this value - this feature will be disabled
 [INFO] GremlinServer - keepAliveInterval was set to 0 which resolves to 0 seconds when configuring this value - this feature will be disabled
-[WARN] AbstractChannelizer - The org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0 serialization class is deprecated.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
-[WARN] AbstractChannelizer - The org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0 serialization class is deprecated.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo-stringd with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
 [INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
 [INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
 [INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0 with org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
@@ -988,8 +983,8 @@
 |scriptEngines.<name>.staticImports |A comma separated list of "static" imports to make available to the `ScriptEngine`. |_none_
 |scriptEngines.<name>.scripts |A comma separated list of script files to execute on `ScriptEngine` initialization. `Graph` and `TraversalSource` instance references produced from scripts will be stored globally in Gremlin Server, therefore it is possible to use initialization scripts to add Traversal Strategies or create entirely new `Graph` instances all together. Instantiating a `LifeCycleHook` in a script provides a way to execute scripts when Gremlin Server starts and stops.|_none_
 |scriptEngines.<name>.config |A `Map` of configuration settings for the `ScriptEngine`.  These settings are dependent on the `ScriptEngine` implementation being used. |_none_
-|evaluationTimeout |The amount of time in milliseconds before a script evaluation and iteration of result times out. This feature can be turned off by setting the value to `0`. |30000
-|serializers |A `List` of `Map` settings, where each `Map` represents a `MessageSerializer` implementation to use along with its configuration. If this value is not set, then Gremlin Server will configure with GraphSON and Gryo but will not register any `ioRegistries` for configured graphs. |_empty_
+|evaluationTimeout |The amount of time in milliseconds before a request evaluation and iteration of result times out. This feature can be turned off by setting the value to `0`. |30000
+|serializers |A `List` of `Map` settings, where each `Map` represents a `MessageSerializer` implementation to use along with its configuration. If this value is not set, then Gremlin Server will configure with GraphSON and GraphBinary but will not register any `ioRegistries` for configured graphs. |_empty_
 |serializers[X].className |The full class name of the `MessageSerializer` implementation. |_none_
 |serializers[X].config |A `Map` containing `MessageSerializer` specific configurations. |_none_
 |ssl.enabled |Determines if SSL is turned on or not. |false
@@ -1056,16 +1051,7 @@
 ===== TraversalOpProcessor
 
 The `TraversalOpProcessor` provides a way to accept traversals configured via <<connecting-via-drivers,withRemote()>>.
-
-[width="100%",cols="3,10,^2",options="header"]
-|=========================================================
-|Name |Description |Default
-|cacheExpirationTime |Time in milliseconds before side-effects from a `Traversal` will be evicted. |60000
-|cacheMaxSize |The maximum number of entries in the side-effect cache. |1000
-|=========================================================
-
-If there is no intention to gather side-effects from traversals, the `cacheMaxSize` can be set to zero to disable the
-cache.
+It has no special configuration settings.
 
 [[security]]
 ==== Security
@@ -1091,7 +1077,8 @@
 |Pluggable SASL |3.0.0-incubating
 |GSSAPI SASL (Kerberos) |3.3.0
 |Gremlin.NET |PLAIN SASL |3.3.0
-|Gremlin-Python |PLAIN SASL |3.2.2
+1.2+v|Gremlin-Python |PLAIN SASL |3.2.2
+|GSSAPI SASL (Kerberos) |3.4.7
 |Gremlin.Net |PLAIN SASL |3.2.7
 |Gremlin-Javascript |PLAIN SASL |3.3.0
 |=========================================================
@@ -1271,14 +1258,21 @@
     principal: gremlinserver/hostname.your.org@YOUR.REALM,
     keytab: /etc/security/keytabs/gremlinserver.service.keytab}}
 
-Krb5Authenticator needs a Kerberos service principal and a keytab that holds the secret key for that principal. The keytab
-location and service name, e.g. gremlinserver, are free to be chosen, but Gremlin clients have to specify this service name
-as the `protocol`. For Gremlin-Console the `protocol` is an entry in the remote.yaml file, for Gremlin-java the client builder
-has a `protocol()` method.
+`Krb5Authenticator` needs a Kerberos service principal and a keytab that holds the secret key for that principal. The keytab
+location and service name, e.g. gremlinserver, are free to be chosen. `Krb5Authenticator` finds the KDC's hostname and
+port from the krb5.conf file with Kerberos configurations. This file can reside at either the
+https://web.mit.edu/kerberos/krb5-devel/doc/mitK5defaults.html[default location] or a location to be specified as a
+system property in the JAVA_OPTIONS environment variable of Gremlin Server:
+
+[source, bash]
+export JAVA_OPTIONS="${JAVA_OPTIONS} -Xms512m -Xmx4096m -Djava.security.krb5.conf=/etc/krb5.conf"
+
+Gremlin clients have to specify the service name as the `protocol` connection parameter. For Gremlin-Console the
+`protocol` is an entry in the remote.yaml file, for Gremlin-java the client builder has a `protocol()` method.
 
 In addition to the `protocol`, the Gremlin client needs to specify a `jaasEntry`, an entry in the
-link:https://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS] configuration file. Gremlin-Console
-comes with a sample gremlin-jaas.conf file with a `GremlinConsole` jaasEntry:
+link:https://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS] configuration file. As a
+start one can define a conf/gremlin-jaas.conf file with a `GremlinConsole` jaasEntry:
 
 [source, jaas]
 GremlinConsole {
@@ -1287,15 +1281,20 @@
   useTicketCache=true;
 };
 
-This configuration tells Gremlin-Console to pass authentication requests from gremlin-server to the Krb5LoginModule, which is
-part of the java standard library.  The Krb5LoginModule does not prompt the user for a username and password but uses the ticket cache that
-is normally refreshed when a user logs in to a host within the Kerberos realm.
+This configuration tells Gremlin Console to pass authentication requests from Gremlin Server to the Krb5LoginModule, which is
+part of the java standard library. The Krb5LoginModule does not prompt the user for a username and password but uses the
+ticket cache that is normally refreshed when a user logs in to a host within the Kerberos realm.
 
-Finally, the Gremlin client needs the location of the JAAS configuration file to be passed as a system property to the JVM. For
-Gremlin-Console the easiest way to do this is to pass it to the run script via the JAVA_OPTIONS environment property:
+The Gremlin client needs the location of the JAAS configuration file to be passed as a system property to the JVM. For
+Gremlin-Console the easiest way to do this is to pass it to the run script via the JAVA_OPTIONS environment property.
+If the krb5.conf Kerberos configuration file is not available from the
+https://web.mit.edu/kerberos/krb5-devel/doc/mitK5defaults.html[default location] it has to be provided as a system
+property as well:
 
 [source, bash]
-export JAVA_OPTIONS="$JAVA_OPTIONS -Djava.security.auth.login.config=conf/gremlin-jaas.conf"
+JAAS_OPTION="-Djava.security.auth.login.config=conf/gremlin-jaas.conf"
+KRB5_OPTION="-Djava.security.krb5.conf=/etc/krb5.conf"
+export JAVA_OPTIONS="${JAVA_OPTIONS} ${KRB5_OPTION} ${JAAS_OPTION}"
 
 [[script-execution]]
 ===== Protecting Script Execution
@@ -1479,7 +1478,8 @@
 some serializers have additional configuration options as defined by the `serializers[X].config` setting.  The
 `config` setting is a `Map` where the keys and values get passed to the serializer at its initialization.  The
 available and/or expected keys are dependent on the serializer being used.  Gremlin Server comes packaged with three
-different serializers: GraphSON, Gryo, and GraphBinary.
+different serializers: GraphSON, Gryo, and GraphBinary (however, GraphSON and GraphBinary are the only two configured
+by default).
 
 ===== GraphSON
 
@@ -1519,14 +1519,17 @@
 
 ===== Gryo
 
+WARNING: Gryo is no longer the recommended serialization format for Gremlin Server. Consider using
+<<server-graphbinary, GraphBinary>> instead.
+
 The Gryo serializer utilizes Kryo-based serialization which produces a binary output.  This format is best consumed
 by JVM-based languages. The format itself is described in the
 link:https://tinkerpop.apache.org/docs/current/dev/io/#gryo[IO Documentation].
 
 [source,yaml]
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerGremlinV1d0 }
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerGremlinV3d0 }
 
-It has the MIME type of `application/vnd.gremlin-v1.0+gryo` and the following configuration options:
+It has the MIME type of `application/vnd.gremlin-v3.0+gryo` and the following configuration options:
 
 [width="100%",cols="3,10,^2",options="header"]
 |=========================================================
@@ -1546,6 +1549,7 @@
 but not on the client).  Implementations should typically instantiate `ClassResolver` implementations that are
 extensions of the `GryoClassResolver` as this class is important to most serialization tasks in TinkerPop.
 
+[[server-graphbinary]]
 ===== GraphBinary
 
 GraphBinary is a binary serialization format suitable for object trees, designed to reduce serialization overhead on
@@ -1858,10 +1862,6 @@
 case but GraphBinary will not. Therefore, script-based requests that use Gryo or GraphSON should definitely follow the
 best practice of only returning the data required by the application.
 
-NOTE: Gryo does have the exception for the `GryoMessageSerializerGremlinV1d0` with the `serializeResultToString`
-option enabled, which will simply convert all results using the Java `toString()` method prior to serialization and
-is typically only use by the Gremlin Console for remote sessions where the actual object from the server is not of use.
-
 For bytecode-based requests, graph elements have reference detachment and thus only return the `id` and `label` of
 the elements. While this approach alleviates a potential performance problem that the script approach exposes, it is
 still important to follow the practice of being specific about the data that is required by the requesting application
@@ -2364,7 +2364,7 @@
 link:http://en.wikipedia.org/wiki/Syntactic_sugar[syntactic sugars] that users could rely on to make their traversals
 more succinct. Unfortunately, many of these conventions made use of link:http://docs.oracle.com/javase/tutorial/reflect/[Java reflection]
 and thus, were not performant. In TinkerPop, these conveniences have been removed in support of the standard
-Gremlin-Groovy syntax being both inline with Gremlin-Java8 syntax as well as always being the most performant
+Gremlin-Groovy syntax being both inline with Gremlin-Java syntax as well as always being the most performant
 representation. However, for those users that would like to use the previous syntactic sugars (as well as new ones),
 there is `SugarGremlinPlugin` (a.k.a Gremlin-Groovy-Sugar).
 
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 934e4ae..4f1a884 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -291,18 +291,17 @@
 
 Remote systems like Gremlin Server and Remote Gremlin Providers respond to requests made in a particular serialization
 format and respond by serializing results to some format to be interpreted by the client. For JVM-based languages,
-there are three options for serialization: Gryo, GraphSON and GraphBinary. When using Gryo serialization (the default
-serializer for the Java driver), it is important that the client and server have the same serializers configured or
-else one or the other will experience serialization exceptions and fail to always communicate. Discrepancy in
-serializer registration between client and server can happen fairly easily as graphs will automatically include
-serializers on the server-side, thus leaving the client to be configured manually. This can be done manually as
-follows:
+there are three options for serialization: Gryo, GraphSON and GraphBinary. It is important that the client and server
+have the same serializers configured in the same way or else one or the other will experience serialization exceptions
+and fail to always communicate. Discrepancy in serializer registration between client and server can happen fairly
+easily as different graph systems may automatically include serializers on the server-side, thus leaving the client
+to be configured manually. As an example:
 
 [source,java]
 ----
 IoRegistry registry = ...; // an IoRegistry instance exposed by a specific graph provider
-GryoMapper kryo = GryoMapper.build().addRegistry(registry).create();
-MessageSerializer serializer = new GryoMessageSerializerV3d0(kryo);
+TypeSerializerRegistry typeSerializerRegistry = TypeSerializerRegistry.build().addRegistry(registry).create();
+MessageSerializer serializer = new GraphBinaryMessageSerializerV1(typeSerializerRegistry);
 Cluster cluster = Cluster.build().
                           serializer(serializer).
                           create();
@@ -312,10 +311,12 @@
 
 The `IoRegistry` tells the serializer what classes from the graph provider to auto-register during serialization.
 Gremlin Server roughly uses this same approach when it configures its serializers, so using this same model will
-ensure compatibility when making requests. Obviously, it is possible to switch to GraphSON or GraphBinary by building
-the appropriate `MessageSerializer` (`GraphSONMessageSerializerV3d0` or `GraphBinaryMessageSerializerV1` respectively)
+ensure compatibility when making requests. Obviously, it is possible to switch to GraphSON or Gryo by using
+the appropriate `MessageSerializer` (e.g. `GraphSONMessageSerializerV3d0` or `GryoMessageSerializerV3d0` respectively)
 in the same way and building that into the `Cluster` object.
 
+NOTE: Gryo is no longer the preferred binary serialization format for Gremlin Server - please prefer GraphBinary.
+
 [[gremlin-java-lambda]]
 === The Lambda Solution
 
@@ -421,7 +422,7 @@
 
 There are a number of overloads to `Client.submit()` that accept a `RequestOptions` object. The `RequestOptions`
 provide a way to include options that are specific to the request made with the call to `submit()`. A good use-case for
-this feature is to set a per-request override to the `scriptEvaluationTimeout` so that it only applies to the current
+this feature is to set a per-request override to the `evaluationTimeout` so that it only applies to the current
 request.
 
 [source,java]
@@ -648,6 +649,7 @@
 [source,bash]
 ----
 pip install gremlinpython
+pip install gremlinpython[kerberos]     # Optional, not available on Microsoft Windows
 ----
 
 [[gremlin-python-connecting]]
@@ -667,9 +669,36 @@
 
 [source,python]
 ----
-g = traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g',headers={'Header':'Value'}))
+g = traversal().withRemote(DriverRemoteConnection(
+    'ws://localhost:8182/gremlin', 'g', headers={'Header':'Value'}))
 ----
 
+Gremlin-Python supports plain text and Kerberos SASL authentication, you can set it on the connection options.
+
+[source,python]
+----
+# Plain text authentication
+g = traversal().withRemote(DriverRemoteConnection(
+    'ws://localhost:8182/gremlin', 'g', username='stephen', password='password'))
+
+# Kerberos authentication
+g = traversal().withRemote(DriverRemoteConnection(
+    'ws://localhost:8182/gremlin', 'g', kerberized_service='gremlin@hostname.your.org'))
+----
+
+The value specified for the kerberized_service should correspond to the first part of the principal name configured for
+the gremlin service, but with the slash replaced by an _at_ sign. The Gremlin-Python client reads the kerberos
+configurations from your system. It finds the KDC's hostname and port from the krb5.conf file at the
+https://web.mit.edu/kerberos/krb5-devel/doc/mitK5defaults.html[default location] or as indicated in the KRB5_CONFIG
+environment variable. It finds credentials from the credential cache or a keytab file at the
+https://web.mit.edu/kerberos/krb5-devel/doc/mitK5defaults.html[default locations] or as indicated
+in the KRB5CCNAME or KRB5_KTNAME environment variables.
+
+If you authenticate to a remote <<connecting-gremlin-server,Gremlin Server>> or
+<<connecting-rgp,Remote Gremlin Provider>>, this server normally has SSL activated and the websockets url will start
+with 'wss://'. If Gremlin-Server uses a self-signed certificate for SSL, Gremlin-Python needs access to a local copy of
+the CA certificate file (in openssl .pem format), to be specified in the SSL_CERT_FILE environment variable.
+
 NOTE: If connecting from an inherently single-threaded Python process where blocking while waiting for Gremlin
 traversals to complete is acceptable, it might be helpful to set `pool_size` and `max_workers` parameters to 1.
 See the <<python-configuration,Configuration>> section just below.  Examples where this could apply are serverless cloud functions or WSGI
@@ -705,9 +734,10 @@
 
 These can be used analogously to how they are used in Gremlin-Java.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g.V().hasLabel('person').has('age',P.gt(30)).order().by('age',Order.desc).toList()
+>>> g.V().hasLabel('person').has('age',P.gt(30)).order().by('age',Order.desc).toList()
+[v[6], v[4]]
 ----
 
 Moreover, by importing the `statics` of Gremlin-Python, the class prefixes can be omitted.
@@ -719,17 +749,19 @@
 
 With statics loaded its possible to represent the above traversal as below.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g.V().hasLabel('person').has('age',gt(30)).order().by('age',desc).toList()
+>>> g.V().hasLabel('person').has('age',gt(30)).order().by('age',desc).toList()
+[v[6], v[4]]
 ----
 
 Finally, statics includes all the `+__+`-methods and thus, anonymous traversals like `+__.out()+` can be expressed as below.
 That is, without the `+__+`-prefix.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g.V().repeat(out()).times(2).name.fold().toList()
+>>> g.V().repeat(out()).times(2).name.fold().toList()
+[['ripple', 'lop']]
 ----
 
 anchor:python-configuration[]
@@ -750,6 +782,7 @@
 |protocol_factory |A callable that returns an instance of `AbstractBaseProtocol`. |`gremlin_python.driver.protocol.GremlinServerWSProtocol`
 |transport_factory |A callable that returns an instance of `AbstractBaseTransport`. |`gremlin_python.driver.tornado.transport.TornadoTransport`
 |username |The username to submit on requests that require authentication. |""
+|kerberized_service |the first part of the principal name configured for the gremlin service|"""
 |session | A unique string-based identifier (typically a UUID) to enable a <<sessions,session-based connection>>. This is not a valid configuration for `DriverRemoteConnection`. |None
 |=========================================================
 
@@ -767,17 +800,23 @@
 In order to add and remove <<traversalstrategy,traversal strategies>> from a traversal source, Gremlin-Python has a
 `TraversalStrategy` class along with a collection of subclasses that mirror the standard Gremlin-Java strategies.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g = g.withStrategies(SubgraphStrategy(vertices=hasLabel('person'),edges=has('weight',gt(0.5))))
-g.V().name.toList()
-g.V().outE().elementMap().toList()
-g = g.withoutStrategies(SubgraphStrategy)
-g.V().name.toList()
-g.V().outE().elementMap().toList()
-g = g.withComputer(workers=2,vertices=has('name','marko'))
-g.V().name.toList()
-g.V().outE().valueMap().with_(WithOptions.tokens).toList()
+>>> g = g.withStrategies(SubgraphStrategy(vertices=hasLabel('person'),edges=has('weight',gt(0.5))))
+>>> g.V().name.toList()
+['marko', 'vadas', 'josh', 'peter']
+>>> g.V().outE().elementMap().toList()
+[{<T.id: 1>: 8, <T.label: 4>: 'knows', <Direction.IN: 2>: {<T.id: 1>: 4, <T.label: 4>: 'person'}, <Direction.OUT: 3>: {<T.id: 1>: 1, <T.label: 4>: 'person'}, 'weight': 1.0}]
+>>> g = g.withoutStrategies(SubgraphStrategy)
+>>> g.V().name.toList()
+['marko', 'vadas', 'lop', 'josh', 'ripple', 'peter']
+>>> g.V().outE().elementMap().toList()
+[{<T.id: 1>: 9, <T.label: 4>: 'created', <Direction.IN: 2>: {<T.id: 1>: 3, <T.label: 4>: 'software'}, <Direction.OUT: 3>: {<T.id: 1>: 1, <T.label: 4>: 'person'}, 'weight': 0.4}, {<T.id: 1>: 7, <T.label: 4>: 'knows', <Direction.IN: 2>: {<T.id: 1>: 2, <T.label: 4>: 'person'}, <Direction.OUT: 3>: {<T.id: 1>: 1, <T.label: 4>: 'person'}, 'weight': 0.5}, {<T.id: 1>: 8, <T.label: 4>: 'knows', <Direction.IN: 2>: {<T.id: 1>: 4, <T.label: 4>: 'person'}, <Direction.OUT: 3>: {<T.id: 1>: 1, <T.label: 4>: 'person'}, 'weight': 1.0}, {<T.id: 1>: 10, <T.label: 4>: 'created', <Direction.IN: 2>: {<T.id: 1>: 5, <T.label: 4>: 'software'}, <Direction.OUT: 3>: {<T.id: 1>: 4, <T.label: 4>: 'person'}, 'weight': 1.0}, {<T.id: 1>: 11, <T.label: 4>: 'created', <Direction.IN: 2>: {<T.id: 1>: 3, <T.label: 4>: 'software'}, <Direction.OUT: 3>: {<T.id: 1>: 4, <T.label: 4>: 'person'}, 'weight': 0.4}, {<T.id: 1>: 12, <T.label: 4>: 'created', <Direction.IN: 2>: {<T.id: 1>: 3, <T.label: 4>: 'software'}, <Direction.OUT: 3>: {<T.id: 1>: 6, <T.label: 4>: 'person'}, 'weight': 0.2}]
+>>> g = g.withComputer(workers=2,vertices=has('name','marko'))
+>>> g.V().name.toList()
+['marko']
+>>> g.V().outE().valueMap().with_(WithOptions.tokens).toList()
+[{<T.id: 1>: 9, <T.label: 4>: 'created', 'weight': 0.4}, {<T.id: 1>: 7, <T.label: 4>: 'knows', 'weight': 0.5}, {<T.id: 1>: 8, <T.label: 4>: 'knows', 'weight': 1.0}]
 ----
 
 NOTE: Many of the `TraversalStrategy` classes in Gremlin-Python are proxies to the respective strategy on
@@ -791,98 +830,34 @@
 Supporting link:https://en.wikipedia.org/wiki/Anonymous_function[anonymous functions] across languages is difficult as
 most languages do not support lambda introspection and thus, code analysis. In Gremlin-Python,
 a link:https://docs.python.org/2/reference/expressions.html#lambda[Python lambda] should be represented as a zero-arg
-callable that returns a string representation of a lambda. The default lambda language is `gremlin-python` and can be
-changed via `gremlin_python.statics.default_lambda_language`. When the lambda is represented in `Bytecode` its language
-is encoded such that the remote connection host can infer which translator and ultimate execution engine to use.
+callable that returns a string representation of a lambda. The lambda should be written as a `Gremlin-Groovy`string.
+When the lambda is represented in `Bytecode` its language is encoded such that the remote connection host can infer
+which translator and ultimate execution engine to use.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g.V().out().map(lambda: "lambda x: len(x.get().value('name'))").sum().toList()                     <1>
-statics.default_lambda_language                                                                    <2>
-g.V().out().map(lambda: ("it.get().value('name').length()", "gremlin-groovy")).sum().toList()      <3>
-statics.default_lambda_language = 'gremlin-groovy'                                                 <4>
-g.V().out().map(lambda: "it.get().value('name').length()").sum().toList()                          <5>
-g.V().out().map(lambda: ("lambda x: len(x.get().value('name'))", "gremlin-python")).sum().toList() <6>
-statics.default_lambda_language = 'gremlin-python'                                                 <7>
-g.V().out().map(lambda: "x: len(x.get().value('name'))").sum().toList()                            <8>
+>>> g.V().out().map(lambda: "it.get().value('name').length()").sum().toList()
+[24]
 ----
 
-<1> A zero-arg lambda yields a string representation of a lambda in Gremlin-Python.
-<2> The default lambda language is currently Gremlin-Python.
-<3> A zero-arg lambda yields a 2-tuple where the second element is the language of the lambda (Gremlin-Groovy).
-<4> The default lambda language can be statically changed.
-<5> A zero-arg lambda yields a string representation of a closure in Gremlin-Groovy.
-<6> A zero-arg lambda yields a 2-tuple where the second element is the language of the lambda (Gremlin-Python).
-<7> The default lambda language is changed back to Gremlin-Python.
-<8> If the `lambda`-prefix is not provided, then it is appended automatically in order to give a more natural look to the expression.
-
 TIP: When running into situations where Groovy cannot properly discern a method signature based on the `Lambda`
 instance created, it will help to fully define the closure in the lambda expression - so rather than
 `lambda: ("it.get().value("name')","gremlin-groovy")`, prefer `lambda: ("x -> x.get().value("name"),"gremlin-groovy")`.
 
-WARNING: Jython support has been deprecated as for 3.3.10 and will be removed in 3.5.0. Gremlin-Python will at that
-point default to Groovy for lambda processing and Python lambdas will not be supported.
-
 Finally, Gremlin `Bytecode` that includes lambdas requires that the traversal be processed by the
 `ScriptEngine`. To avoid continued recompilation costs, it supports the encoding of bindings, which allow a remote
 engine to to cache traversals that will be reused over and over again save that some parameterization may change. Thus,
 instead of translating, compiling, and then executing each submitted bytecode, it is possible to simply execute.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g.V(Bindings.of('id',1)).out('created').map(lambda: ("it.get().value('name').length()", "gremlin-groovy")).sum().toList()
-g.V(Bindings.of('id',4)).out('created').map(lambda: ("it.get().value('name').length()", "gremlin-groovy")).sum().toList()
+>>> g.V(Bindings.of('x',1)).out('created').map(lambda: "it.get().value('name').length()").sum().toList()
+[3]
+>>> g.V(Bindings.of('x',4)).out('created').map(lambda: "it.get().value('name').length()").sum().toList()
+[9]
 ----
 
-==== Native Python Lambdas
-
-To process lambdas in Python, the `GremlinJythonScriptEngine` must be enabled on the remote end. If that remote is
-Gremlin Server, then these instructions can help configuration it. As an example, the
-`conf/gremlin-server-modern-py.yaml` configuration maintains a `GremlinJythonScriptEngine`.
-
-[source,bash]
-----
-$ bin/gremlin-server.sh install org.apache.tinkerpop gremlin-python x.y.z
-$ bin/gremlin-server.sh conf/gremlin-server-modern-py.yaml
-[INFO] GremlinServer -
-       \,,,/
-       (o o)
----oOOo-(3)-oOOo---
-
-[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-modern-py.yaml
-[INFO] MetricManager - Configured Metrics Slf4jReporter configured with interval=180000ms and loggerName=org.apache.tinkerpop.gremlin.server.Settings$Slf4jReporterMetrics
-[INFO] GraphManager - Graph [graph] was successfully configured via [conf/tinkergraph-empty.properties].
-[INFO] ServerGremlinExecutor - Initialized Gremlin thread pool.  Threads in pool named with pattern gremlin-*
-[INFO] ScriptEngines - Loaded gremlin-jython ScriptEngine
-[INFO] ScriptEngines - Loaded gremlin-python ScriptEngine
-[INFO] ScriptEngines - Loaded gremlin-groovy ScriptEngine
-[INFO] GremlinExecutor - Initialized gremlin-groovy ScriptEngine with scripts/generate-modern.groovy
-[INFO] ServerGremlinExecutor - Initialized GremlinExecutor and configured ScriptEngines.
-[INFO] ServerGremlinExecutor - A GraphTraversalSource is now bound to [g] with graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
-[INFO] OpLoader - Adding the standard OpProcessor.
-[INFO] OpLoader - Adding the session OpProcessor.
-[INFO] OpLoader - Adding the traversal OpProcessor.
-[INFO] TraversalOpProcessor - Initialized cache for TraversalOpProcessor with size 1000 and expiration time of 600000 ms
-[INFO] GremlinServer - Executing start up LifeCycleHook
-[INFO] Logger$info - Loading 'modern' graph data.
-[WARN] AbstractChannelizer - The org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0 serialization class is deprecated.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
-[WARN] AbstractChannelizer - The org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0 serialization class is deprecated.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo-stringd with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
-[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
-[INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0 with org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
-[INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0-stringd with org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
-[INFO] GremlinServer$1 - Gremlin Server configured with worker thread pool of 1, gremlin pool of 8 and boss thread pool of 1.
-[INFO] GremlinServer$1 - Channel started at port 8182.
-----
-
-NOTE: The command to use `install` need only be executed once to gather `gremlin-python` dependencies into Gremlin Servers'
-path. Future starts of Gremlin Server will not require that command.
-
-WARNING: As explained throughout the documentation, when possible <<a-note-on-lambdas,avoid>> lambdas. If lambdas
-must be used, then consider submitting Groovy lambdas as opposed to Python-based ones. The `GremlinGroovyScriptEngine`
-is far more featured and performant than its Jython sibling and will likely yield better results.
+WARNING: As explained throughout the documentation, when possible <<a-note-on-lambdas,avoid>> lambdas.
 
 [[gremlin-python-scripts]]
 === Submitting Scripts
@@ -1016,11 +991,14 @@
 Python supports meta-programming and operator overloading. There are three uses of these techniques in Gremlin-Python
 that makes traversals a bit more concise.
 
-[gremlin-python,modern]
+[source,python]
 ----
-g.V().both()[1:3].toList()
-g.V().both()[1].toList()
-g.V().both().name.toList()
+>>> g.V().both()[1:3].toList()
+[v[2], v[4]]
+>>> g.V().both()[1].toList()
+[v[2]]
+>>> g.V().both().name.toList()
+['lop', 'lop', 'lop', 'vadas', 'josh', 'josh', 'josh', 'marko', 'marko', 'marko', 'peter', 'ripple']
 ----
 
 [[gremlin-python-differences]]
@@ -1044,7 +1022,9 @@
 results within a collection across different languages. If a `Set` is needed then convert `List` results
 to `Set` manually.
 * Gremlin is capable of returning `Dictionary` results that use non-hashable keys (e.g. Dictionary as a key) and Python
-does not support that at a language level. Gremlin that returns such results will need to be re-written to avoid that.
+does not support that at a language level. Using GraphSON 3.0 or GraphBinary (after 3.5.0) makes it possible to return
+such results. In all other cases, Gremlin that returns such results will need to be re-written to avoid that sort of
+key.
 * The `subgraph()`-step is not supported by any variant that is not running on the Java Virtual Machine as there is
 no `Graph` instance to deserialize a result into on the client-side. A workaround is to replace the step with `store()`
 and then convert those results to something the client can use locally.
@@ -1053,7 +1033,7 @@
 === Application Examples
 
 The TinkerPop source code contains a simple Python script that shows a basic example of how gremlinpython works. It
-can be found in GitHub link:https://github.com/apache/tinkerpop/tree/xx.yy.zz/gremlin-python/src/main/jython/example.py[here]
+can be found in GitHub link:https://github.com/apache/tinkerpop/tree/xx.yy.zz/gremlin-python/src/main/python/example.py[here]
 and is designed to work best with a running <<gremlin-server,Gremlin Server>> configured with the default
 `conf/gremlin-server.yaml` file as included with the standard release packaging.
 
@@ -1296,6 +1276,25 @@
 g.V().Repeat(__.Out()).Times(2).Values<string>("name");
 ----
 
+Gremlin allows for `Map` instances to include `null` keys, but `null` keys in C# `Dictionary` instances are not allowed.
+It is therefore necessary to rewrite a traversal such as:
+
+[source,javascript]
+----
+g.V().groupCount().by('age')
+----
+
+where "age" is not a valid key for all vertices in a way that will remove the need for a `null` to be returned.
+
+[source,javascript]
+----
+g.V().has('age').groupCount().by('age')
+g.V().hasLabel('person').groupCount().by('age')
+----
+
+Either of the above two options accomplishes the desired goal as both prevent `groupCount()` from having to process
+the possibility of `null`.
+
 anchor:gremlin-net-limitations[]
 [[gremlin-dotnet-limitations]]
 === Limitations
@@ -1450,6 +1449,17 @@
 
 With this configuration, the state of variables within scripts are preserved between requests.
 
+==== Per Request Settings
+
+Some settings can be established per request, like an override of the `scriptEvaluationTimeout` which can be helpful
+when it is known that particular request might need to execute longer than what the server might allow with its
+settings:
+
+[source,javascript]
+----
+const result = await client.submit('g.V().repeat(both()).times(100)', null, {"scriptEvaluationTimeout": 60000});
+----
+
 [[gremlin-javascript-dsl]]
 === Domain Specific Languages
 
@@ -1519,6 +1529,41 @@
 
 *Steps* - <<from-step,from_()>>, <<in-step,in_()>>, <<with-step,with_()>>
 
+Gremlin allows for `Map` instances to include `null` keys, but `null` keys in Javascript have some interesting behavior
+as in:
+
+[source,text]
+----
+> var a = { null: 'something', 'b': 'else' };
+> JSON.stringify(a)
+'{"null":"something","b":"else"}'
+> JSON.parse(JSON.stringify(a))
+{ null: 'something', b: 'else' }
+> a[null]
+'something'
+> a['null']
+'something'
+----
+
+This behavior needs to be considered when using Gremlin to return such results. A typical situation where this might
+happen is with `group()` or `groupCount()` as in:
+
+[source,javascript]
+----
+g.V().groupCount().by('age')
+----
+
+where "age" is not a valid key for all vertices. In these cases, it will return `null` for that key and group on that.
+It may bet better in Javascript to filter away those vertices to avoid the return of `null` in the returned `Map`:
+
+[source,javascript]
+----
+g.V().has('age').groupCount().by('age')
+g.V().hasLabel('person').groupCount().by('age')
+----
+
+Either of the above two options accomplishes the desired goal as both prevent `groupCount()` from having to process
+the possibility of `null`.
 [[gremlin-javascript-limitations]]
 === Limitations
 
diff --git a/docs/src/reference/implementations-neo4j.asciidoc b/docs/src/reference/implementations-neo4j.asciidoc
index 612ba31..7cf9512 100644
--- a/docs/src/reference/implementations-neo4j.asciidoc
+++ b/docs/src/reference/implementations-neo4j.asciidoc
@@ -28,7 +28,7 @@
 <dependency>
   <groupId>org.neo4j</groupId>
   <artifactId>neo4j-tinkerpop-api-impl</artifactId>
-  <version>0.7-3.2.3</version>
+  <version>0.9-3.4.0</version>
 </dependency>
 ----
 
diff --git a/docs/src/reference/implementations-tinkergraph.asciidoc b/docs/src/reference/implementations-tinkergraph.asciidoc
index 3384f55..55b0e61 100644
--- a/docs/src/reference/implementations-tinkergraph.asciidoc
+++ b/docs/src/reference/implementations-tinkergraph.asciidoc
@@ -39,7 +39,7 @@
 * Use TinkerGraph as a sandbox to develop and debug complex traversals by simulating data from a larger graph inside
 a TinkerGraph.
 
-Constructing a simple graph using TinkerGraph in Java8 is presented below:
+Constructing a simple graph using TinkerGraph in Java is presented below:
 
 [source,java]
 ----
@@ -121,6 +121,7 @@
 |gremlin.tinkergraph.edgeIdManager |The `IdManager` implementation to use for edges.
 |gremlin.tinkergraph.vertexPropertyIdManager |The `IdManager` implementation to use for vertex properties.
 |gremlin.tinkergraph.defaultVertexPropertyCardinality |The default `VertexProperty.Cardinality` to use when `Vertex.property(k,v)` is called.
+|gremlin.tinkergraph.allowNullPropertyValues |A boolean value that determines whether or not `null` property values are allowed and defaults to `true`.
 |gremlin.tinkergraph.graphLocation |The path and file name for where TinkerGraph should persist the graph data. If a
 value is specified here, the `gremlin.tinkergraph.graphFormat` should also be specified.  If this value is not
 included (default), then the graph will stay in-memory and not be loaded/persisted to disk.
diff --git a/docs/src/reference/intro.asciidoc b/docs/src/reference/intro.asciidoc
index 555bea1..530f5ac 100644
--- a/docs/src/reference/intro.asciidoc
+++ b/docs/src/reference/intro.asciidoc
@@ -424,11 +424,13 @@
 
 The first of these points is serialization. When Gremlin Server receives a request, the results must be serialized to
 the form requested by the client and then the client deserializes those into objects native to the language. TinkerPop
-has two such formats that it uses with link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#gryo[Gryo] and
-link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphson[GraphSON]. Gryo is a JVM-only format and thus carries the
-advantage that serializing and deserializing occurs on the classes native to the JVM on both the client and server side.
-As the client has full access to the same classes that the server does it basically has a full GTM on its own and
-therefore has the ability to do some slightly more advanced things.
+has three such formats that it uses with link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphbinary[GraphBinary],
+link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#gryo[Gryo] and
+link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphson[GraphSON]. Among these serialization formats, users
+should prefer GraphBinary as it combines the best features of both GraphSON and Gryo and it provides the most even
+user experience across different programming languages. There are areas however where this is not quite true, as
+Gremlin Language Variants don't have full GTMs present and therefore don't have the complete means to accomplish what
+a pure JVM solution would.
 
 A good example is the `subgraph()`-step which returns a `Graph` instance as its result. The subgraph returned from
 the server can be deserialized into an actual `Graph` instance on the client, which then means it is possible to
diff --git a/docs/src/reference/the-graphcomputer.asciidoc b/docs/src/reference/the-graphcomputer.asciidoc
index 25da35e..fece039 100644
--- a/docs/src/reference/the-graphcomputer.asciidoc
+++ b/docs/src/reference/the-graphcomputer.asciidoc
@@ -377,7 +377,12 @@
 ----
 g = traversal().withEmbedded(graph).withComputer()
 g.V().pageRank().elementMap()
-g.V().pageRank().by('pageRank').times(5).order().by('pageRank').elementMap()
+g.V().pageRank().
+        with(PageRank.propertyName, 'pageRank').
+        with(PageRank.times, 5).
+  order().
+    by('pageRank').
+  elementMap()
 ----
 
 [[peerpressurevertexprogram]]
@@ -399,8 +404,11 @@
 [gremlin-groovy,modern]
 ----
 g = traversal().withEmbedded(graph).withComputer()
-g.V().peerPressure().by('cluster').elementMap()
-g.V().peerPressure().by(outE('knows')).by('cluster').elementMap()
+g.V().peerPressure().with(PeerPressure.propertyName, 'cluster').elementMap()
+g.V().peerPressure().
+        with(PeerPressure.edges,outE('knows')).
+        with(PeerPressure.propertyName, 'cluster').
+  elementMap()
 ----
 
 [[connectedcomponentvertexprogram]]
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 4c56e45..4dbf6d5 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -809,9 +809,12 @@
 g.V().values('lang')
 g.V().values('lang').dedup()
 g.V(1).repeat(bothE('created').dedup().otherV()).emit().path() <1>
+g.V().bothE().properties().dedup() <2>
 ----
 
 <1> Traverse all `created` edges, but don't touch any edge twice.
+<2> Note that `Property` instances will compare on key and value, whereas a `VertexProperty` will also include its
+element as it is a first-class citizen.
 
 If a by-step modulation is provided to `dedup()`, then the object is processed accordingly prior to determining if it
 has been seen or not.
@@ -2108,14 +2111,16 @@
 [[pagerank-step]]
 === PageRank Step
 
-The `pageRank()`-step (*map*/*sideEffect*) calculates link:http://en.wikipedia.org/wiki/PageRank[PageRank] using <<pagerankvertexprogram,`PageRankVertexProgram`>>.
+The `pageRank()`-step (*map*/*sideEffect*) calculates link:http://en.wikipedia.org/wiki/PageRank[PageRank] using
+<<pagerankvertexprogram,`PageRankVertexProgram`>>.
 
-IMPORTANT: The `pageRank()`-step is a `VertexComputing`-step and as such, can only be used against a graph that supports `GraphComputer` (OLAP).
+IMPORTANT: The `pageRank()`-step is a `VertexComputing`-step and as such, can only be used against a graph that
+supports `GraphComputer` (OLAP).
 
 [gremlin-groovy,modern]
 ----
 g = traversal().withEmbedded(graph).withComputer()
-g.V().pageRank().by('pageRank').values('pageRank')
+g.V().pageRank().with(PageRank.propertyName, 'friendRank').values('pageRank')
 g.V().hasLabel('person').
   pageRank().
     with(PageRank.edges, __.outE('knows')).
@@ -2127,7 +2132,8 @@
 Note the use of the `with()` modulating step which provides configuration options to the algorithm. It takes
 configuration keys from the `PageRank` and is automatically imported to the Gremlin Console.
 
-The <<explain-step,`explain()`>>-step can be used to understand how the traversal is compiled into multiple `GraphComputer` jobs.
+The <<explain-step,`explain()`>>-step can be used to understand how the traversal is compiled into multiple
+`GraphComputer` jobs.
 
 [gremlin-groovy,modern]
 ----
@@ -2250,7 +2256,7 @@
 [gremlin-groovy,modern]
 ----
 g = traversal().withEmbedded(graph).withComputer()
-g.V().peerPressure().by('cluster').values('cluster')
+g.V().peerPressure().with(PeerPressure.propertyName, 'cluster').values('cluster')
 g.V().hasLabel('person').
   peerPressure().
     with(PeerPressure.propertyName, 'cluster').
@@ -4075,6 +4081,44 @@
 Display stack trace? [yN]
 ----
 
+=== SeedStrategy
+
+There are number of components of the Gremlin language that, by design, can produce non-deterministic results:
+
+* <<coin-step,coin()>>
+* <<order-step,order()>> when `Order.shuffle` is used
+* <<sample-step,sample()>>
+
+To get these steps to return deterministic results, `SeedStrategy` allows assignment of a seed value to the `Random`
+operations of the steps. The following example demonstrates the random nature of `shuffle`:
+
+[gremlin-groovy,modern]
+----
+g.V().values('name').fold().order(local).by(shuffle)
+g.V().values('name').fold().order(local).by(shuffle)
+g.V().values('name').fold().order(local).by(shuffle)
+g.V().values('name').fold().order(local).by(shuffle)
+g.V().values('name').fold().order(local).by(shuffle)
+----
+
+With `SeedStrategy` in place, however, the same order is applied each time:
+
+[gremlin-groovy,modern]
+----
+seedStrategy = new SeedStrategy(999998L)
+g.withStrategies(seedStrategy).V().values('name').fold().order(local).by(shuffle)
+g.withStrategies(seedStrategy).V().values('name').fold().order(local).by(shuffle)
+g.withStrategies(seedStrategy).V().values('name').fold().order(local).by(shuffle)
+g.withStrategies(seedStrategy).V().values('name').fold().order(local).by(shuffle)
+g.withStrategies(seedStrategy).V().values('name').fold().order(local).by(shuffle)
+----
+
+IMPORTANT: `SeedStrategy` only makes specific steps behave in a deterministic fashion and does not necessarily make
+the entire traversal deterministic itself. If the underlying graph database or processing engine happens to not
+guarantee iteration order, then it is possible that the final result of the traversal will appear to be
+non-deterministic. In these cases, it would be necessary to enforce a deterministic iteration with `order()` prior to
+these steps that make use of randomness to return results.
+
 === SubgraphStrategy
 
 `SubgraphStrategy` is similar to `PartitionStrategy` in that it constrains a `Traversal` to certain vertices, edges,
diff --git a/docs/src/tutorials/gremlin-language-variants/index.asciidoc b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
index ef8cd36..39fa04f 100644
--- a/docs/src/tutorials/gremlin-language-variants/index.asciidoc
+++ b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
@@ -542,10 +542,6 @@
 [INFO] TraversalOpProcessor - Initialized cache for TraversalOpProcessor with size 1000 and expiration time of 600000 ms
 [INFO] GremlinServer - Executing start up LifeCycleHook
 [INFO] Logger$info - Executed once at startup of Gremlin Server.
-[WARN] AbstractChannelizer - The org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0 serialization class is deprecated.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
-[WARN] AbstractChannelizer - The org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0 serialization class is deprecated.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo-stringd with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
 [INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
 [INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
 [INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0 with org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
diff --git a/docs/src/tutorials/the-gremlin-console/index.asciidoc b/docs/src/tutorials/the-gremlin-console/index.asciidoc
index c4d08f3..ad04607 100644
--- a/docs/src/tutorials/the-gremlin-console/index.asciidoc
+++ b/docs/src/tutorials/the-gremlin-console/index.asciidoc
@@ -571,9 +571,9 @@
 gremlin> :install com.datastax.cassandra cassandra-driver-core 2.1.9
 ==>Loaded: [com.datastax.cassandra, cassandra-driver-core, 2.1.9]
 gremlin> import com.datastax.driver.core.*
-==>groovy.grape.Grape, org.apache.commons.configuration.*, ..., com.datastax.driver.core.*
+==>groovy.grape.Grape, org.apache.commons.configuration2.*, ..., com.datastax.driver.core.*
 gremlin> import static com.datastax.driver.core.querybuilder.QueryBuilder.*
-==>groovy.grape.Grape, org.apache.commons.configuration.*, ..., static com.datastax.driver.core.querybuilder.QueryBuilder.*
+==>groovy.grape.Grape, org.apache.commons.configuration2.*, ..., static com.datastax.driver.core.querybuilder.QueryBuilder.*
 gremlin> cluster = com.datastax.driver.core.Cluster.builder().addContactPoint("localhost").build()
 ==>com.datastax.driver.core.Cluster@3e1624c7
 gremlin> session = cluster.connect()
diff --git a/docs/src/upgrade/appendix.asciidoc b/docs/src/upgrade/appendix.asciidoc
index a9df0e4..7ce5b22 100644
--- a/docs/src/upgrade/appendix.asciidoc
+++ b/docs/src/upgrade/appendix.asciidoc
@@ -24,8 +24,8 @@
 
 One of the major differences between TinkerPop 2.x and TinkerPop 3.x is that in TinkerPop 3.x, the Java convention of
 using setters and getters was abandoned in favor of a syntax that is more aligned with the syntax of Gremlin-Groovy in
-TinkerPop2. Given that Gremlin-Java8 and Gremlin-Groovy are nearly identical due to the inclusion of Java 8 lambdas, a
-big effort was made to ensure that both languages were as similar as possible.
+TinkerPop2. Given that Gremlin-Java and Gremlin-Groovy are nearly identical due to the inclusion of lambdas from
+Java 8, a big effort was made to ensure that both languages were as similar as possible.
 
 In addition, TinkerPop2 and below made a sharp distinction between the various TinkerPop projects: Blueprints, Pipes,
 Gremlin, Frames, Furnace, and Rexster. With TinkerPop 3.x, all of these projects have been merged and are generally
diff --git a/docs/src/upgrade/index.asciidoc b/docs/src/upgrade/index.asciidoc
index a2bf20f..8e78f4f 100644
--- a/docs/src/upgrade/index.asciidoc
+++ b/docs/src/upgrade/index.asciidoc
@@ -34,6 +34,8 @@
 * Graph Language Provider
 * Graph Plugin Provider
 
+include::release-3.5.x.asciidoc[]
+
 include::release-3.4.x.asciidoc[]
 
 include::release-3.3.x.asciidoc[]
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index 9359e07..67e8048 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -15,6 +15,15 @@
 limitations under the License.
 ////
 
+== TinkerPop 3.5.0
+
+=== Upgrading for Users
+
+==== Upgrade Neo4j
+
+Refer to Neo4j link:https://neo4j.com/guides/upgrade-archive/[3.4 Upgrade FAQ] for guide on how to upgrade from the previous 3.2.3 version.
+For example, configuration setting `dbms.allow_format_migration` is now `dbms.allow_upgrade`.
+
 = TinkerPop 3.4.0
 
 image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/avant-gremlin.png[width=225]
diff --git a/docs/src/upgrade/release-3.5.x.asciidoc b/docs/src/upgrade/release-3.5.x.asciidoc
new file mode 100644
index 0000000..e5f09b5
--- /dev/null
+++ b/docs/src/upgrade/release-3.5.x.asciidoc
@@ -0,0 +1,749 @@
+////
+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.
+////
+
+= TinkerPop 3.5.0
+
+image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/gremlin-sleeping-beauty.png[width=225]
+
+*The Sleeping Gremlin: No. 18 Entr'acte symphonique*
+
+== TinkerPop 3.5.0
+
+*Release Date: NOT OFFICIALLY RELEASED YET*
+
+Please see the link:https://github.com/apache/tinkerpop/blob/3.5.0/CHANGELOG.asciidoc#release-3-5-0[changelog] for a complete list of all the modifications that are part of this release.
+
+=== Upgrading for Users
+
+==== Java 11
+
+TinkerPop now builds and is compatible with Java 11.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2076[TINKERPOP-2076]
+
+==== Anonymous Child Traversals
+
+TinkerPop conventions for child traversals is to spawn them anonymously from `__`, therefore:
+
+[source,groovy]
+g.addV('person').addE('self').to(__.V(1))
+
+or more succinctly via static import as:
+
+[source,groovy]
+g.addV('person').addE('self').to(V(1))
+
+Some users have chosen to instead write the above as:
+
+[source,groovy]
+g.addV('person').addE('self').to(g.V(1))
+
+which spawns a child traversal from a `GraphTraversalSource`. When spawned this way, a traversal is bound to a "source"
+and therefore is not anonymous. While the above code worked, it is important that there be less ways to do things
+with Gremlin so as to avoid confusion in examples, documentations and mailing list answers.
+
+As of 3.5.0, attempting to use a traversal spawned from a "source" will result in an exception. Users will need to
+modify their code if they use the unconventional syntax.
+
+link:https://issues.apache.org/jira/browse/TINKERPOP-2361[TINKERPOP-2361]
+
+==== Gryo Usage
+
+Since the first release of TinkerPop 3.x, Gryo has been the default serialization format for Gremlin Server and
+Java Driver. It was also used as the default serialization format for Gremlin Console remote connectivity to Gremlin
+Server. As of this release, Gryo has been replaced as the default by GraphBinary. All packaged configuration files
+and programmatic defaults have been modified as such.
+
+It is still possible to utilize Gryo as a message serialization format by modifying Gremlin Server configuration files
+to include the appropriate Gryo configurations. If using Gryo, do not user earlier versions of the driver and server
+with 3.5.0. Use a 3.5.0 client to connect to a 3.5.0 server. Generally speaking, mixed version combinations will
+appear to work properly, but problems will likely occur during general course of usage and it is therefore not
+advisable to take this approach.
+
+For best compatibility between 3.4.x and 3.5.x, please use GraphBinary.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2259[TINKERPOP-2259]
+
+==== Configuration Upgrade
+
+There is a major breaking change in the use of `Configuration` objects. Prior to 3.5.0, `Configuration` objects were
+from the Apache Commons `commons-configuration` library, but in this version, they are of `commons-configuration2`.
+While this is a breaking change, the fix for most implementations will be quite simple, Simply, change the import
+statements from:
+
+[source,text]
+----
+org.apache.commons.configuration.*
+----
+
+to
+
+[source,text]
+----
+org.apache.commons.configuration2.*
+----
+
+It is also worth noting that default list handling in configurations is treated differently. TinkerPop largely
+disabled the default list handling approach in `Configuration` 1.x, but if that functionality is still needed, it can
+be reclaimed by setting the `LegacyListDelimiterHandler` - details for doing taking this step and other relevant
+upgrade information can be found in the link:https://commons.apache.org/proper/commons-configuration/userguide/upgradeto2_0.html[2.x Upgrade Documentation].
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2185[TINKERPOP-2185]
+
+==== Use of null
+
+Gremlin has traditionally disallowed `null` as a value in traversals and not always in consistent ways:
+
+[source,text]
+----
+gremlin> g.inject(1, null, null, 2, null)
+java.lang.NullPointerException
+Type ':help' or ':h' for help.
+Display stack trace? [yN]n
+gremlin> g.V().has('person','name','marko').property('age', null)
+The AddPropertyStep does not have a provided value: AddPropertyStep({key=[age]})
+Type ':help' or ':h' for help.
+Display stack trace? [yN]
+gremlin> g.addV("person").property("name", 'stephen').property("age", null)
+==>v[13]
+gremlin> g.V().has('person','name','stephen').elementMap()
+==>[id:13,label:person,name:stephen]
+gremlin> g.V().constant(null)
+gremlin>
+----
+
+Note how `null` can produce exception behavior or act as a filter. For 3.5.0, TinkerPop has not only made `null` usage
+consistent, but has also made it an allowable value within a `Traversal`:
+
+[source,text]
+----
+gremlin> g.inject(1, null, null, 2, null)
+==>1
+==>null
+==>null
+==>null
+==>2
+gremlin> g.V().constant(null)
+==>null
+==>null
+==>null
+==>null
+==>null
+==>null
+----
+
+TinkerGraph can be configured to support `null` as a property value and all graphs may not support this feature (for
+example, Neo4j does not). Please be sure to check the new `supportsNullPropertyValues()` feature (or the documentation
+of the graph provider) to determine if the `Graph` implementation allows `null` as a property value.
+
+With respect to `null` in relation to properties, there was a bit of inconsistency in the handling of `null` in calls
+to `property()` depending on the type of mutation being executed demonstrated as follows in earlier versions:
+
+[source,text]
+----
+gremlin> g.V(1).property("x", 1).property("y", null).property("z", 2)
+The AddPropertyStep does not have a provided value: AddPropertyStep({key=[y]})
+Type ':help' or ':h' for help.
+Display stack trace? [yN]N
+gremlin> g.addV("test").property("x", 1).property("y", null).property("z", 2)
+==>v[13]
+gremlin> g.V(13).properties()
+==>vp[x->1]
+==>vp[z->2]
+----
+
+This behavior has been altered to become consistent. First, assuming `null` is not supported as a property value, the
+setting of a property to `null` should have the behavior of removing the property in the same way in which you might
+do `g.V().properties().drop()`:
+
+[source,text]
+----
+gremlin> g.V(1).property("x", 1).property("y", null).property("z", 2)
+==>v[1]
+gremlin> g.V(1).elementMap()
+==>[id:1,label:person,name:marko,x:1,z:2,age:29]
+gremlin> g.V().hasLabel('person').property('age',null).iterate()
+gremlin> g.V().hasLabel('person').elementMap()
+==>[id:1,label:person,name:marko]
+==>[id:2,label:person,name:vadas]
+==>[id:4,label:person,name:josh]
+==>[id:6,label:person,name:peter]
+----
+
+Then, assuming `null` is supported as a property value:
+
+[source,text]
+----
+gremlin> g.addV("person").property("name", 'stephen').property("age", null)
+==>v[13]
+gremlin> g.V().has('person','name','stephen').elementMap()
+==>[id:13,label:person,name:stephen,age:null]
+gremlin> g.V().has('person','age',null)
+==>v[13]
+----
+
+The above described changes also has an effect on steps like `group()` and `groupCount()` which formerly produced
+exceptions when keys could not be found:
+
+[source,text]
+----
+gremlin> g.V().group().by('age')
+The property does not exist as the key has no associated value for the provided element: v[3]:age
+Type ':help' or ':h' for help.
+Display stack trace? [yN]n
+----
+
+The solution was to filter away vertices that did not have the available key so that such steps would work properly
+or to write a more complex `by()` modulator to better handle the possibility of a missing key. With the latest changes
+however none of that is necessary unless desired:
+
+[source,text]
+----
+gremlin> g.V().groupCount().by('age')
+==>[null:2,32:1,35:1,27:1,29:1]
+----
+
+In conclusion, this change in greater support of `null` may affect the behavior of existing traversals written in past
+versions of TinkerPop as it is no longer possible to rely on `null` to expect a filtering action for traversers.
+Please review existing Gremlin carefully to ensure that there are no unintended consequences of this change and that
+there are no opportunities to improve existing logic to take greater advantage of this expansion of `null` semantics.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2235[TINKERPOP-2235],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2099[TINKERPOP-2099]
+
+==== Remote SideEffects
+
+Remote traversals no longer support the retrieval of remote side-effects. Users must therefore directly return
+side-effects as part of their query if they need that data. Note that server settings for `TraversalOpProcessor`, which
+formerly held the cache for these side-effects, no longer have any effect and can be removed.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2269[TINKERPOP-2269]
+
+==== ByModulatorOptimizationStrategy
+
+The new `ByModulatorOptimizationStrategy` attempts to re-write `by()` modulator traversals to use their more optimized
+forms which can provide a major performance improvement. As a simple an example, a traversal like `by(id())` would
+be replaced by `by(id)`, thus replacing a step-based traversal with a token-based traversal.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1682[TINKERPOP-1682]
+
+==== SeedStrategy
+
+The new `SeedStrategy` allows the user to set a seed value for steps that make use of `Random` so that the traversal
+has the ability to return deterministic results. While this feature is useful for testing and debugging purposes,
+there are also some practical applications as well.
+
+[source,text]
+----
+gremlin> g.V().values('name').fold().order(local).by(shuffle)
+==>[josh,marko,vadas,peter,ripple,lop]
+gremlin> g.V().values('name').fold().order(local).by(shuffle)
+==>[vadas,lop,marko,peter,josh,ripple]
+gremlin> g.V().values('name').fold().order(local).by(shuffle)
+==>[peter,ripple,josh,lop,marko,vadas]
+gremlin> g.withStrategies(new SeedStrategy(22323)).V().values('name').fold().order(local).by(shuffle)
+==>[lop,peter,josh,marko,vadas,ripple]
+gremlin> g.withStrategies(new SeedStrategy(22323)).V().values('name').fold().order(local).by(shuffle)
+==>[lop,peter,josh,marko,vadas,ripple]
+gremlin> g.withStrategies(new SeedStrategy(22323)).V().values('name').fold().order(local).by(shuffle)
+==>[lop,peter,josh,marko,vadas,ripple]
+----
+
+==== by(T) for Property
+
+The `Property` interface is not included in the hierarchy of `Element`. This means that an edge property or a
+meta-property are not considered elements the way that a `VertexProperty` is. As a result, some usages of `T` in
+relation to properties do not work consistently. One such example is `by(T)`, a token-based traversal, where the
+following works for a `VertexProperty` but will not for edge properties or meta-properties:
+
+[source,text]
+----
+gremlin> g.V(1).properties().as('a').select('a').by(key)
+==>name
+==>age
+----
+
+For a `Property` you would need to use `key()`-step:
+
+[source,text]
+----
+gremlin> g.E(11).properties().as('a').select(last,'a').by(key())
+==>weight
+----
+
+Aside from the inconsistency, this issue also presents a situation where performance is impacted as token-based
+traversals are inherently faster than step-based ones. In 3.5.0, this issue has been resolved in conjunction with the
+introduction of `ByModulatorOptimizationStrategy` which will optimize `by(key())` and `by(value())` to their
+appropriate token versions automatically.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1682[TINKERPOP-1682]
+
+==== Complex dict Deserialization
+
+In Gremlin it is common to return a `dict` as a key value in another `dict`. The problem for Python is that a `dict`
+is not hashable and will result in an error. By introducing a `HashableDict` for those keys, it is now possible to
+return these types of results and not have to work around them:
+
+[source,text]
+----
+>>> g.V().has('person', 'name', 'marko').elementMap("name").groupCount().next()
+{{<T.id: 1>: 1, <T.label: 4>: 'person', 'name': 'marko'}: 1}
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2395[TINKERPOP-2395]
+
+==== Python 2.x Support
+
+The gremlinpython module no longer supports Python 2.x. Users must use Python 3 going forward. For the most part, from
+a user's perspective, there are no specific API changes to consider as a result of this change. It is also worth
+noting that Jython support has been removed and that `gremlin-python` no longer produces a JVM-based artifact. This
+change means that the `GremlinJythonScriptEngine` no longer exists and there is no way to write native Python lambdas.
+All lambdas should be written using `gremlin-groovy` if they are needed.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2317[TINKERPOP-2317]
+
+==== Python Kerberos Support
+
+The Python Driver now supports Kerberos based authentication:
+
+[source,python]
+----
+g = traversal().withRemote(DriverRemoteConnection(
+    'ws://localhost:8182/gremlin', 'g', kerberized_service='gremlin@hostname.your.org'))
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1641[TINKERPOP-1641],
+link:https://tinkerpop.apache.org/docs/current/reference/#gremlin-python-connecting[Reference Documentation]
+
+==== .NET Standard 2.0 Only
+
+Gremlin.NET no longer targets .NET Standard 1.3, but only .NET Standard 2.0. Since .NET Core 2.0 and .NET Framework
+4.6.1 already support this .NET Standard version, most users should not be impacted by this.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2335[TINKERPOP-2335]
+
+=== Gremlin.NET: New JSON Library
+
+Gremlin.NET now uses `System.Text.Json` instead of Newtonsoft.Json as `System.Text.Json` is already included in .NET
+Core 3.0 and higher which means that we have one dependency less on this platform and because it offers an increased
+performance.
+Most users should not notice this change. But users who have implemented their own GraphSON serializers or
+deserializers probably have to change them accordingly. The same applies to users that let Gremlin.NET return data
+without deserializing it first as the returned data types will change in this case, for example from Newtonsoft.Json's
+`JObject` or `JToken` to `JsonElement` with `System.Text.Json`.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2349[TINKERPOP-2349],
+link:http://tinkerpop.apache.org/docs/3.5.0/dev/provider/#_supporting_gremlin_net_io[Documentation for custom JSON serialization with Gremlin.NET]
+
+==== Neo4j Changes
+
+There were two key changes to the neo4j-gremlin module:
+
+* The underlying Neo4j version moved from the 3.2.x line to 3.4.x line. Please see the
+link:https://neo4j.com/guides/upgrade-archive/[Neo4j Upgrade FAQ] for more information as features and
+configuration options may have changed.
+* Experimental support for multi/meta-properties in Neo4j which were previously deprecated have now been permanently
+removed.
+
+==== Deprecation Removal
+
+The following deprecated classes, methods or fields have been removed in this version:
+
+* `gremlin-core`
+** `org.apache.tinkerpop.gremlin.process.computer.bulkdumping.BulkDumperVertexProgram`
+** `org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoader`
+** `org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgram`
+** `org.apache.tinkerpop.gremlin.process.computer.bulkloading.IncrementalBulkLoader`
+** `org.apache.tinkerpop.gremlin.process.computer.bulkloading.OneTimeBulkLoader`
+** `org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.PeerPressureVertexProgram.Builder#traversal(*)`
+** `org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram.Builder#traversal(*)`
+** `org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram.Builder#vertexCount()`
+** `org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRankVertexProgramStep.modulateBy(*)`
+** `org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRankVertexProgramStep.modulateTimes()`
+** `org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressureVertexProgramStep.modulateBy(*)`
+** `org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressureVertexProgramStep.modulateTimes()`
+** `org.apache.tinkerpop.gremlin.process.remote.traversal.AbstractRemoteTraversalSideEffects`
+** `org.apache.tinkerpop.gremlin.process.remote.traversal.EmbeddedRemoteTraversalSideEffects`
+** `org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversalSideEffects`
+** `org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversal#getSideEffects()`
+** `org.apache.tinkerpop.gremlin.process.traversal.Order.decr`
+** `org.apache.tinkerpop.gremlin.process.traversal.Order.incr`
+** `org.apache.tinkerpop.gremlin.process.traversal.TraversalSource#withRemote(*)`
+** `org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource#withRemote(*)`
+** `org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep(Traversal.Admin, boolean, PropertyType, String...)`
+** `org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep#isIncludeTokens()`
+** `org.apache.tinkerpop.gremlin.structure.util.star.StarGraph#builder()`
+** `org.apache.tinkerpop.gremlin.structure.util.star.StarGraph.Builder#create()`
+* `gremlin-driver`
+** `org.apache.tinkerpop.gremlin.driver.Tokens#ARGS_SCRIPT_EVAL_TIMEOUT`
+** `org.apache.tinkerpop.gremlin.driver.Cluster.Builder#keyCertChainFile(String)`
+** `org.apache.tinkerpop.gremlin.driver.Cluster.Builder#keyFile(String)`
+** `org.apache.tinkerpop.gremlin.driver.Cluster.Builder#keyPassword(String)`
+** `org.apache.tinkerpop.gremlin.driver.Cluster.Builder#maxWaitForSessionClose(Integer)`
+** `org.apache.tinkerpop.gremlin.driver.Cluster.Builder#trustCertificateChainFile(String)`
+** `org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder`
+** `org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder`
+** `org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversalSideEffects`
+** `org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal#getSideEffects()`
+** `org.apache.tinkerpop.gremlin.driver.simple.NioClient`
+* `gremlin-python`
+** `org.apache.tinkerpop.gremlin.python.jsr223.*`
+* `gremlin-server`
+** `org.apache.tinkerpop.gremlin.server.Settings.scriptEvaluationTimeout`
+** `org.apache.tinkerpop.gremlin.server.Settings.SslSettings.keyCertChainFile`
+** `org.apache.tinkerpop.gremlin.server.Settings.SslSettings.keyFile`
+** `org.apache.tinkerpop.gremlin.server.Settings.SslSettings.keyPassword`
+** `org.apache.tinkerpop.gremlin.server.Settings.SslSettings.trustCertificateChainFile`
+** `org.apache.tinkerpop.gremlin.server.ResponseHandlerContext`
+** `org.apache.tinkerpop.gremlin.server.channel.NioChannelizer`
+** `org.apache.tinkerpop.gremlin.server.handler.NioGremlinBinaryRequestDecoder`
+** `org.apache.tinkerpop.gremlin.server.handler.NioGremlinResponseFrameEncoder`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractEvalOpProcessor.evalOpInternal(ResponseHandlerContext, Supplier, BindingSupplier)`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor.generateMetaData(ChannelHandlerContext, RequestMessage, ResponseStatusCode, Iterator)`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor.handleIterator(ResponseHandlerContext, Iterator)`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor.makeFrame(ChannelHandlerContext, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor.makeFrame(Context, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor.makeFrame(ResponseHandlerContext, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)`
+** `org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor.makeFrame(ResponseHandlerContext, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map, Map)`
+** `org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor.onSideEffectSuccess(Graph, Context)`
+** `org.apache.tinkerpop.gremlin.server.util.SideEffectIterator`
+* `neo4j-gremlin`
+** `org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph#getTrait()`
+** `org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph#CONFIG_META_PROPERTIES`
+** `org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph#CONFIG_MULTI_PROPERTIES`
+** `org.apache.tinkerpop.gremlin.neo4j.structure.trait.MultiMetaNeo4jTrait`
+** `org.apache.tinkerpop.gremlin.neo4j.structure.trait.NoMultiNoMetaNeo4jTrait`
+** `org.apache.tinkerpop.gremlin.neo4j.structure.trait.Neo4jTrait`
+
+Certain elements of the API were not or could not be deprecated in prior versions and were simply renamed for this
+release:
+
+* `org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode#SERVER_ERROR_SCRIPT_EVALUATION` became `SERVER_ERROR_EVALUATION`
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2080[TINKERPOP-2080],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2231[TINKERPOP-2231],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2233[TINKERPOP-2233],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2239[TINKERPOP-2239],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2269[TINKERPOP-2269],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2273[TINKERPOP-2273],
+link:https://tinkerpop.apache.org/docs/3.5.0/upgrade/#_ssl_security[3.2.10 Upgrade Documentation for SSL]
+
+=== Upgrading for Provider
+
+==== Graph System Providers
+
+===== ScalarMapStep
+
+`MapStep` had a single abstract method that needed to be implemented:
+
+[source,java]
+----
+protected abstract E map(final Traverser.Admin<S> traverser);
+----
+
+This method made it easy to implement new implementations because it hid certain processing logic and made it so that
+the implementer only had to reason about how to take the current object from the `Traverser` and transform it to a
+new value. As 3.5.0 changed semantics around how `null` is processed, this method became a bit of a hindrance to the
+more complex logic which those semantics entailed. Specifically, this method could not easily communicate to underlying
+processing what a `null` might mean - is the `null` the end of the traversal stream or should the `null` be promoted
+down the stream as a value to be processed.
+
+Interestingly, the method that enabled the handling of this more complex decision making already existed in
+`AbstractStep`:
+
+[source,java]
+----
+protected Traverser.Admin<E> processNextStart()
+----
+
+It returns a whole `Traverser` object and forces manual retrieval of the "next" `Traverser`. At this level it becomes
+possible to make choices on `null` and return it if it should be propagated or dismiss it and return an
+`EmptyTraverser`. To better accommodate the `MapStep` which provides the nice helper `map(Traverser)` method as well
+as the more flexible version that doesn't need that infrastructure, `ScalarMapStep` was added to extend `MapStep`. The
+`map(Traverser)` was then moved to `ScalarMapStep` and those steps that could rely on that helper method now extend
+from it. All other steps of this sort still extend `MapStep` and directly implement `processNextStart()`.
+
+Providers will get compile errors if they extended `MapStep`. The easy solution will be to simply modify that code so
+that their step instead extends `ScalarMapStep`. As a secondary task, providers should then examine their step
+implementation to ensure that `null` semantics as presented in 3.5.0 apply properly. If they do not, then it is likely
+that the step should simply implement `MapStep` directly and former `map(Traverser)` logic should be migrated to
+`processNextStart()`.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2235[TINKERPOP-2235],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2099[TINKERPOP-2099]
+
+===== TraversalStrategy Application
+
+The methodology for strategy application has been altered and the change is most easily described by example. Given a
+traversal with the structure:
+
+[source,text]
+----
+a(b(),c(d()))
+----
+
+Strategies were formerly applied in the following order:
+
+[source,text]
+----
+StrategyA on a
+StrategyB on a
+StrategyA on b
+StrategyB on b
+StrategyA on c
+StrategyB on c
+StrategyA on d
+StrategyB on d
+----
+
+This approach has always prevented strategies from performing global operations across the traversal and all decedents
+effectively as children will not have been processed by preceding strategies yet. As of this release, the approach
+has been altered to apply strategies as follows:
+
+[source,text]
+----
+StrategyA on a
+StrategyA on b
+StrategyA on c
+StrategyA on d
+StrategyB on a
+StrategyB on b
+StrategyB on c
+StrategyB on d
+----
+
+In this way, strategy B can check if it is being applied to the root traversal and if it is it knows that A has been
+applied globally.
+
+This revised methodology could represent a breaking change for `TraversalStrategy` implementations if they somehow
+relied on the old ordering of application. It may also present an opportunity to revise how a `TraversalStrategy` is
+written to gain some processing benefit to the new order. Please be sure to review any custom strategies carefully
+when upgrading to this version.
+
+As part of this change, there have been some adjustments to the `Traversal` and `Traversal.Admin` interfaces which have
+helped to clarify coding intent. There is now an `isRoot()` method which determines whether or not the traversal has a
+parent or not. Under revised semantics for 3.5.0, a traversal's parent must be an `EmptyStep` instance and should not
+be `null`. With this change, provider `TraversalStrategy` implementations should be reviewed to evaluate if `isRoot()`
+semantics cause any breaks in logic to existing code.
+
+In addition, `TraversalStrategies` now implements `Iterable` and exposes an `iterator()` method which may be preferred
+over the old `toList()` style construction for getting the list of configured strategies.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1568[TINKERPOP-1568],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2310[TINKERPOP-2310],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2311[TINKERPOP-2311]
+
+===== Null Semantics
+
+Graph providers should take note of the changes to `null` semantics described in the "users" section of these upgrade
+notes. As `null` is now acceptable as a `Traverser` object, this change may affect custom steps. Further note that
+`null` now works more consistently with mutation steps and graph providers may need to include additional logic to
+deal with those possible conditions. Please see the console sessions below which uses TinkerGraph to demonstrate the
+current behavioral expectations.
+
+[source,text]
+----
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>false
+gremlin> g.addV(null).property(id, null).property('name',null)
+==>v[0]
+gremlin> g.V().elementMap()
+==>[id:0,label:vertex]
+...
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>true
+gremlin> g.addV(null).property(id, null).property('name',null)
+==>v[0]
+gremlin> g.V().elementMap()
+==>[id:0,label:vertex,name:null]
+----
+
+In the above example, `addV()` defaults to `Vertex.DEFAULT_LABEL`, the `id` is generated and setting the "name"
+property to `null` results in the value not being set. If the property value is set to an actual value and then set
+to `null` TinkerGraph will remove the property key all together:
+
+[source,text]
+----
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>false
+gremlin> g.addV().property('name','stephen')
+==>v[0]
+gremlin> g.V().elementMap()
+==>[id:0,label:vertex,name:stephen]
+gremlin> g.V().has('vertex','name','stephen').property('name',null)
+==>v[0]
+gremlin> g.V().elementMap()
+==>[id:0,label:vertex]
+...
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>true
+gremlin> g.addV().property('name','stephen')
+==>v[2]
+gremlin> g.V().has('vertex','name','stephen').property('name',null)
+==>v[2]
+gremlin> g.V().elementMap()
+==>[id:2,label:vertex,name:null]
+----
+
+The above examples point out the default operations of TinkerGraph, but it can be configured to actually accept the
+`null` as a property value and it is up to graph providers to decided how they wish to treat a `null` property value.
+Providers should use the new `supportsNullPropertyValues()` feature to indicate to users how `null` is handled.
+
+For edges, the `label` still cannot be defaulted and must be specified, therefore:
+
+[source,text]
+----
+gremlin> g.V(0L).as('a').addE(null).to('a')
+Label can not be null
+Type ':help' or ':h' for help.
+Display stack trace? [yN]n
+gremlin> g.V(0L).as('a').addE(constant(null)).to('a')
+Label can not be null
+Type ':help' or ':h' for help.
+Display stack trace? [yN]
+----
+
+Also, edges have similar behavior to vertices when it comes to setting properties (again, the default configuration for
+TinkerGraph is being used here):
+
+[source,text]
+----
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>false
+gremlin> g.addV().property('name','stephen')
+==>v[0]
+gremlin> g.V().has('vertex','name','stephen').as('a').addE('knows').to('a').property(id,null).property('weight',null)
+==>e[2][0-knows->0]
+gremlin> g.E().elementMap()
+==>[id:2,label:knows,IN:[id:0,label:vertex],OUT:[id:0,label:vertex]]
+gremlin> g.E().property('weight',0.5)
+==>e[2][0-knows->0]
+gremlin> g.E().elementMap()
+==>[id:2,label:knows,IN:[id:0,label:vertex],OUT:[id:0,label:vertex],weight:0.5]
+gremlin> g.E().property('weight',null)
+==>e[2][0-knows->0]
+gremlin> g.E().elementMap()
+==>[id:2,label:knows,IN:[id:0,label:vertex],OUT:[id:0,label:vertex]]
+...
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>true
+gremlin> g.addV().property('name','stephen')
+==>v[8]
+gremlin> g.V().has('vertex','name','stephen').as('a').addE('knows').to('a').property(id,null).property('weight',null)
+==>e[10][8-knows->8]
+gremlin> g.E().elementMap()
+==>[id:10,label:knows,IN:[id:8,label:vertex],OUT:[id:8,label:vertex],weight:null]
+gremlin> g.E().property('weight',0.5)
+==>e[10][8-knows->8]
+gremlin> g.E().elementMap()
+==>[id:10,label:knows,IN:[id:8,label:vertex],OUT:[id:8,label:vertex],weight:0.5]
+gremlin> g.E().property('weight',null)
+==>e[10][8-knows->8]
+gremlin> g.E().elementMap()
+==>[id:10,label:knows,IN:[id:8,label:vertex],OUT:[id:8,label:vertex],weight:null]
+----
+
+Graphs that support multi/meta-properties have some issues to consider as well as demonstrated with TinkerGraph:
+
+[source,text]
+----
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>false
+gremlin> g.addV().property(list,'foo',"x").property(list,"foo", null).property(list,'foo','bar')
+==>v[0]
+gremlin> g.V().elementMap()
+==>[id:0,label:vertex,foo:bar]
+gremlin> g.V().valueMap()
+==>[foo:[x,bar]]
+gremlin> g.V().property('foo',null)
+==>v[0]
+gremlin> g.V().valueMap(true)
+==>[id:0,label:vertex]
+...
+gremlin> g.addV().property(list,'foo','bar','x',1,'y',null)
+==>v[0]
+gremlin> g.V().properties('foo').valueMap(true)
+==>[id:1,key:foo,value:bar,x:1]
+gremlin> g.V().properties('foo').property('x',null)
+==>vp[foo->bar]
+gremlin> g.V().properties('foo').valueMap(true)
+==>[id:1,key:foo,value:bar]
+...
+gremlin> g.getGraph().features().vertex().supportsNullPropertyValues()
+==>false
+gremlin> g.addV().property(list,'foo',"x").property(list,"foo", null).property(list,'foo','bar')
+==>v[11]
+gremlin> g.V().elementMap()
+==>[id:11,label:vertex,foo:bar]
+gremlin> g.V().valueMap()
+==>[foo:[x,null,bar]]
+...
+gremlin> g.addV().property(list,'foo','bar','x',1,'y',null)
+==>v[0]
+gremlin> g.V().properties('foo').valueMap(true)
+==>[id:1,key:foo,value:bar,x:1,y:null]
+gremlin> g.V().properties('foo').property('x',null)
+==>vp[foo->bar]
+gremlin> g.V().properties('foo').valueMap(true)
+==>[id:1,key:foo,value:bar,x:null,y:null]
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2235[TINKERPOP-2235],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2099[TINKERPOP-2099]
+
+===== AbstractOpProcessor API Change
+
+The `generateMetaData()` method was removed as it was deprecated in a previous version. There already was a preferred
+method called `generateResultMetaData()` that took an extra `Settings` parameter. To fix compilation issues simply
+replace implementations of the `generateMetaData()` method with `generateResultMetaData()`. Gremlin Server has
+only been calling `generateResultMetaData()` since the deprecation, so this correction should be straightforward.
+
+===== StoreStep and AggregateStep
+
+Note that `StoreStep` has been renamed to `AggregateLocalStep` and `AggregateStep` has been renamed to
+`AggregateGlobalStep`. The renaming is important to consider if any custom `TraversalStrategies` have been written
+that rely on the old step names.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2254[TINKERPOP-2254]
+
+===== Session Close
+
+TinkerPop drivers no longer send the session "close" message to kill a session. The close of the connection itself
+should be responsible for the close of the session. It is also expected that a session is bound to the client that
+created it. Closing the session explicitly by closing the connection will act as a force close where transaction are
+not explicitly rolled-back by Gremlin Server. Such transactions would be handled by the underlying graph system in the
+manner that they provide.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2336[TINKERPOP-2336]
+
+==== Graph Driver Providers
+
+===== TraversalOpProcessor Side-effects
+
+`TraversalOpProcessor` no longer holds a cache of side-effects and more generally the entire side-effect protocol has
+been removed and is no longer supported in the server or drivers.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2269[TINKERPOP-2269]
+
+===== Close Message
+
+The functionality of the "close" message is no longer in place in Gremlin Server. Sending the message (from older
+drivers for example) will simply result in a no-op on the server and the expected return of the `NO_CONTENT` message.
+From 3.5.0 forward, drivers need not send this message to close the session and simply rely on the close of the
+connection to kill the session.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2336[TINKERPOP-2336]
\ No newline at end of file
diff --git a/docs/static/images/gremlin-sleeping-beauty.png b/docs/static/images/gremlin-sleeping-beauty.png
new file mode 100644
index 0000000..3095da3
--- /dev/null
+++ b/docs/static/images/gremlin-sleeping-beauty.png
Binary files differ
diff --git a/gremlin-archetype/gremlin-archetype-dsl/pom.xml b/gremlin-archetype/gremlin-archetype-dsl/pom.xml
index 21b6820..c554cb2 100644
--- a/gremlin-archetype/gremlin-archetype-dsl/pom.xml
+++ b/gremlin-archetype/gremlin-archetype-dsl/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>gremlin-archetype</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype-dsl</artifactId>
diff --git a/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/README.asciidoc b/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/README.asciidoc
index 49fd7c8..1471018 100644
--- a/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/README.asciidoc
+++ b/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/README.asciidoc
@@ -23,8 +23,8 @@
 
 == Prerequisites
 
-* Java 8 Update 40+
-* link:https://maven.apache.org/[Maven 3.x]
+* Java 11
+* link:https://maven.apache.org/[Maven 3.3+]
 
 == Building and Running
 
diff --git a/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/pom.xml b/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/pom.xml
index d7bb31c..282779f 100644
--- a/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/pom.xml
+++ b/gremlin-archetype/gremlin-archetype-dsl/src/main/resources/archetype-resources/pom.xml
@@ -49,15 +49,41 @@
     <build>
         <plugins>
             <plugin>
-                <!-- TinkerPop3 requires Java 8 -->
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.3</version>
+                <version>3.8.0</version>
                 <configuration>
                     <source>1.8</source>
                     <target>1.8</target>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
                 </configuration>
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <version>3.8.1</version>
+                        <configuration>
+                            <release>8</release>
+                            <compilerArgs>
+                                <arg>-parameters</arg>
+                            </compilerArgs>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
\ No newline at end of file
diff --git a/gremlin-archetype/gremlin-archetype-server/pom.xml b/gremlin-archetype/gremlin-archetype-server/pom.xml
index df4d660..e3ce2fd 100644
--- a/gremlin-archetype/gremlin-archetype-server/pom.xml
+++ b/gremlin-archetype/gremlin-archetype-server/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>gremlin-archetype</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype-server</artifactId>
diff --git a/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/README.asciidoc b/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/README.asciidoc
index d4a0eb1..9daafb2 100644
--- a/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/README.asciidoc
+++ b/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/README.asciidoc
@@ -24,8 +24,8 @@
 
 == Prerequisites
 
-* Java 8 Update 40+
-* link:https://maven.apache.org/[Maven 3.x]
+* Java 11
+* link:https://maven.apache.org/[Maven 3.3+]
 * Gremlin Server is link:http://archive.apache.org/dist/tinkerpop/[downloaded] and unpackaged
 
 == Building and Running
diff --git a/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/pom.xml b/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/pom.xml
index ca29604..3f4945b 100644
--- a/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/pom.xml
+++ b/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/pom.xml
@@ -55,19 +55,21 @@
     <build>
         <plugins>
             <plugin>
-                <!-- TinkerPop3 requires Java 8 -->
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.3</version>
+                <version>3.8.0</version>
                 <configuration>
                     <source>1.8</source>
                     <target>1.8</target>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
                 </configuration>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.17</version>
+                <version>2.22.0</version>
                 <configuration>
                     <systemPropertyVariables>
                         <log4j.configuration>file:conf/log4j-test.properties</log4j.configuration>
@@ -76,4 +78,28 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <version>3.8.1</version>
+                        <configuration>
+                            <release>8</release>
+                            <compilerArgs>
+                                <arg>-parameters</arg>
+                            </compilerArgs>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
\ No newline at end of file
diff --git a/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/src/test/resources/gremlin-server.yaml b/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/src/test/resources/gremlin-server.yaml
index 9530b50..3ba912d 100644
--- a/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/src/test/resources/gremlin-server.yaml
+++ b/gremlin-archetype/gremlin-archetype-server/src/main/resources/archetype-resources/src/test/resources/gremlin-server.yaml
@@ -28,8 +28,7 @@
                org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-modern.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0]}}
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                                                                                                                # application/vnd.gremlin-v1.0+gryo-stringd
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
diff --git a/gremlin-archetype/gremlin-archetype-tinkergraph/pom.xml b/gremlin-archetype/gremlin-archetype-tinkergraph/pom.xml
index 79b8a00..c3b9e19 100644
--- a/gremlin-archetype/gremlin-archetype-tinkergraph/pom.xml
+++ b/gremlin-archetype/gremlin-archetype-tinkergraph/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>gremlin-archetype</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype-tinkergraph</artifactId>
diff --git a/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/README.asciidoc b/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/README.asciidoc
index ddb6de6..6535647 100644
--- a/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/README.asciidoc
+++ b/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/README.asciidoc
@@ -22,8 +22,8 @@
 
 == Prerequisites
 
-* Java 8 Update 40+
-* link:https://maven.apache.org/[Maven 3.x]
+* Java 11
+* link:https://maven.apache.org/[Maven 3.3+]
 
 == Building and Running
 
diff --git a/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/pom.xml b/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/pom.xml
index 0727319..6f1ebed 100644
--- a/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/pom.xml
+++ b/gremlin-archetype/gremlin-archetype-tinkergraph/src/main/resources/archetype-resources/pom.xml
@@ -49,15 +49,41 @@
     <build>
         <plugins>
             <plugin>
-                <!-- TinkerPop3 requires Java 8 -->
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.3</version>
+                <version>3.8.0</version>
                 <configuration>
                     <source>1.8</source>
                     <target>1.8</target>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
                 </configuration>
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <version>3.8.1</version>
+                        <configuration>
+                            <release>8</release>
+                            <compilerArgs>
+                                <arg>-parameters</arg>
+                            </compilerArgs>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
\ No newline at end of file
diff --git a/gremlin-archetype/pom.xml b/gremlin-archetype/pom.xml
index c50bc89..ac40e41 100644
--- a/gremlin-archetype/pom.xml
+++ b/gremlin-archetype/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype</artifactId>
diff --git a/gremlin-console/Dockerfile b/gremlin-console/Dockerfile
index ff57227..3291d69 100644
--- a/gremlin-console/Dockerfile
+++ b/gremlin-console/Dockerfile
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-FROM openjdk:8-jre-alpine
+FROM adoptopenjdk/openjdk11:alpine-slim
 
 LABEL maintainer="dev@tinkerpop.apache.org"
 
diff --git a/gremlin-console/bin/gremlin.sh b/gremlin-console/bin/gremlin.sh
index b584e28..b8c1d21 120000
--- a/gremlin-console/bin/gremlin.sh
+++ b/gremlin-console/bin/gremlin.sh
@@ -1 +1 @@
-../target/apache-tinkerpop-gremlin-console-3.4.9-SNAPSHOT-standalone/bin/gremlin.sh
\ No newline at end of file
+../target/apache-tinkerpop-gremlin-console-3.5.0-SNAPSHOT-standalone/bin/gremlin.sh
\ No newline at end of file
diff --git a/gremlin-console/pom.xml b/gremlin-console/pom.xml
index a2b6e61..dd5b518 100644
--- a/gremlin-console/pom.xml
+++ b/gremlin-console/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-console</artifactId>
     <name>Apache TinkerPop :: Gremlin Console</name>
@@ -68,7 +68,7 @@
         </dependency>
         <dependency>
             <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
+            <artifactId>hamcrest</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -339,6 +339,14 @@
                                         <copy todir="${project.build.directory}/python">
                                             <fileset dir="src/test/python"/>
                                         </copy>
+                                        <exec dir="${project.build.directory}/python" executable="python3"
+                                              failonerror="true">
+                                            <arg line="--version"/>
+                                        </exec>
+                                        <exec dir="${project.build.directory}/python" executable="virtualenv"
+                                              failonerror="true">
+                                            <arg line="--version"/>
+                                        </exec>
                                         <exec dir="${project.build.directory}/python" executable="virtualenv"
                                               failonerror="true">
                                             <arg line="--python=python3 env"/>
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Colorizer.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Colorizer.groovy
index 0fee402..f155024 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Colorizer.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Colorizer.groovy
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.console;
 
-import org.codehaus.groovy.tools.shell.AnsiDetector
+import org.apache.groovy.groovysh.AnsiDetector
 import org.fusesource.jansi.Ansi
 import org.fusesource.jansi.AnsiConsole
 
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
index 3dd8e69..7f299e9 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
@@ -42,11 +42,11 @@
 import org.apache.tinkerpop.gremlin.structure.Vertex
 import org.apache.tinkerpop.gremlin.util.Gremlin
 import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator
-import org.codehaus.groovy.tools.shell.ExitNotification
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.ExitNotification
+import org.apache.groovy.groovysh.Groovysh
 import org.codehaus.groovy.tools.shell.IO
-import org.codehaus.groovy.tools.shell.InteractiveShellRunner
-import org.codehaus.groovy.tools.shell.commands.SetCommand
+import org.apache.groovy.groovysh.InteractiveShellRunner
+import org.apache.groovy.groovysh.commands.SetCommand
 import org.fusesource.jansi.Ansi
 import sun.misc.Signal
 import sun.misc.SignalHandler
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/GremlinGroovysh.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/GremlinGroovysh.groovy
index 96015db..b7cfd94 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/GremlinGroovysh.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/GremlinGroovysh.groovy
@@ -22,12 +22,12 @@
 import org.apache.tinkerpop.gremlin.console.commands.GremlinSetCommand
 import org.codehaus.groovy.control.CompilerConfiguration
 import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
-import org.codehaus.groovy.tools.shell.Command
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.Command
+import org.apache.groovy.groovysh.Groovysh
 import org.codehaus.groovy.tools.shell.IO
-import org.codehaus.groovy.tools.shell.ParseCode
-import org.codehaus.groovy.tools.shell.Parser
-import org.codehaus.groovy.tools.shell.util.CommandArgumentParser
+import org.apache.groovy.groovysh.ParseCode
+import org.apache.groovy.groovysh.Parser
+import org.apache.groovy.groovysh.util.CommandArgumentParser
 
 /**
  * Overrides the posix style parsing of Groovysh allowing for commands to parse prior to Groovy 2.4.x.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/PluggedIn.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/PluggedIn.groovy
index fb87f79..fec8fd8 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/PluggedIn.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/PluggedIn.groovy
@@ -18,7 +18,6 @@
  */
 package org.apache.tinkerpop.gremlin.console
 
-import org.apache.tinkerpop.gremlin.console.Preferences;
 import org.apache.tinkerpop.gremlin.jsr223.BindingsCustomizer
 import org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin
 import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer
@@ -26,7 +25,7 @@
 import org.apache.tinkerpop.gremlin.jsr223.console.ConsoleCustomizer
 import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.Groovysh
 import org.codehaus.groovy.tools.shell.IO
 
 /**
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Preferences.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Preferences.groovy
index d8c1afe..63ccfd6 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Preferences.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Preferences.groovy
@@ -22,7 +22,7 @@
 import java.util.prefs.PreferenceChangeEvent
 import java.util.prefs.PreferenceChangeListener
 
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.Groovysh
 import org.codehaus.groovy.tools.shell.IO
 
 public class Preferences {
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy
index d2455cc..e853b27 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy
@@ -25,8 +25,8 @@
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper
-import org.codehaus.groovy.tools.shell.ComplexCommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.ComplexCommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Commands that help work with Gremlin bytecode.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/ClsCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/ClsCommand.groovy
index b21e0c4..451d942 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/ClsCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/ClsCommand.groovy
@@ -19,8 +19,8 @@
 package org.apache.tinkerpop.gremlin.console.commands
 
 import org.apache.tinkerpop.gremlin.console.Mediator
-import org.codehaus.groovy.tools.shell.CommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Clear the console.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/GremlinSetCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/GremlinSetCommand.groovy
index f86042d..e071d8e 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/GremlinSetCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/GremlinSetCommand.groovy
@@ -20,9 +20,9 @@
 
 import jline.console.completer.Completer
 
-import org.codehaus.groovy.tools.shell.Groovysh
-import org.codehaus.groovy.tools.shell.commands.SetCommand
-import org.codehaus.groovy.tools.shell.util.PackageHelper
+import org.apache.groovy.groovysh.Groovysh
+import org.apache.groovy.groovysh.commands.SetCommand
+import org.apache.groovy.groovysh.util.PackageHelper
 import org.codehaus.groovy.tools.shell.util.Preferences
 import org.codehaus.groovy.tools.shell.util.SimpleCompletor
 
@@ -79,8 +79,8 @@
         }
 
         return [
-            new SimpleCompletor(loader),
-            null
+                new SimpleCompletor(loader),
+                null
         ]
     }
 }
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/InstallCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/InstallCommand.groovy
index 9736f44..8fa2aaa 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/InstallCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/InstallCommand.groovy
@@ -25,8 +25,8 @@
 import org.apache.tinkerpop.gremlin.groovy.util.Artifact
 import org.apache.tinkerpop.gremlin.groovy.util.DependencyGrabber
 import org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin
-import org.codehaus.groovy.tools.shell.CommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Install a dependency into the console.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/PluginCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/PluginCommand.groovy
index 98cd7cf..2841d7d 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/PluginCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/PluginCommand.groovy
@@ -20,8 +20,8 @@
 
 import org.apache.tinkerpop.gremlin.console.ConsoleFs
 import org.apache.tinkerpop.gremlin.console.Mediator
-import org.codehaus.groovy.tools.shell.ComplexCommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.ComplexCommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Activate and manage a plugin.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/RemoteCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/RemoteCommand.groovy
index 68e48d9..4e25a1a 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/RemoteCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/RemoteCommand.groovy
@@ -21,8 +21,8 @@
 import org.apache.tinkerpop.gremlin.console.Mediator
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
-import org.codehaus.groovy.tools.shell.ComplexCommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.ComplexCommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Configure a remote connection to a Gremlin Server.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/SubmitCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/SubmitCommand.groovy
index 5021458..ec156cb 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/SubmitCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/SubmitCommand.groovy
@@ -19,8 +19,8 @@
 package org.apache.tinkerpop.gremlin.console.commands
 
 import org.apache.tinkerpop.gremlin.console.Mediator
-import org.codehaus.groovy.tools.shell.CommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Submit a script to a Gremlin Server instance.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/UninstallCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/UninstallCommand.groovy
index 285a231..982102a 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/UninstallCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/UninstallCommand.groovy
@@ -20,8 +20,8 @@
 
 import org.apache.tinkerpop.gremlin.console.ConsoleFs
 import org.apache.tinkerpop.gremlin.console.Mediator
-import org.codehaus.groovy.tools.shell.CommandSupport
-import org.codehaus.groovy.tools.shell.Groovysh
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 
 /**
  * Uninstall a maven dependency from the Console's path.
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy
index 5e44800..4cb8ffd 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy
@@ -28,7 +28,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.LambdaSideEffectStep
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy
@@ -91,7 +91,7 @@
                         Thread.sleep(acceptor.vizStepDelay)
                     }
                 }), s, traversal)
-                TraversalHelper.insertAfterStep(new AggregateStep(traversal, sideEffectKey), s, traversal)
+                TraversalHelper.insertAfterStep(new AggregateGlobalStep(traversal, sideEffectKey), s, traversal)
             }
 
             // decay all vertices except those that made it through the filter - "this way you can watch
@@ -109,7 +109,7 @@
                         Thread.sleep(acceptor.vizStepDelay)
                     }
                 }), s, traversal)
-                TraversalHelper.insertAfterStep(new AggregateStep(traversal, sideEffectKey), s, traversal)
+                TraversalHelper.insertAfterStep(new AggregateGlobalStep(traversal, sideEffectKey), s, traversal)
             }
         }
     }
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
index 80a78ab..2f12c4c 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
@@ -35,7 +35,6 @@
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal;
-import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversalSideEffects;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0;
@@ -93,8 +92,7 @@
                     Serializers.class,
                     SerTokens.class,
                     DriverRemoteConnection.class,
-                    DriverRemoteTraversal.class,
-                    DriverRemoteTraversalSideEffects.class).create();
+                    DriverRemoteTraversal.class).create();
 
     public DriverGremlinPlugin() {
         super(NAME, imports, new DriverConsoleCustomizer());
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java
index 310a49a..22ec4bc 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java
@@ -25,7 +25,7 @@
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.structure.io.Storage;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.codehaus.groovy.tools.shell.Groovysh;
+import org.apache.groovy.groovysh.Groovysh;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java
index ab11d2e..0cc895b 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java
@@ -21,7 +21,7 @@
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
 import org.apache.tinkerpop.gremlin.structure.io.Storage;
-import org.codehaus.groovy.tools.shell.Groovysh;
+import org.apache.groovy.groovysh.Groovysh;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java
index b1f8eff..7c269f4 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java
@@ -25,7 +25,7 @@
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.codehaus.groovy.tools.shell.Groovysh;
+import org.apache.groovy.groovysh.Groovysh;
 import org.codehaus.groovy.tools.shell.IO;
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java
index e24b77c..e13efb6 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.console.jsr223;
 
 import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment;
-import org.codehaus.groovy.tools.shell.Groovysh;
+import org.apache.groovy.groovysh.Groovysh;
 import org.codehaus.groovy.tools.shell.IO;
 
 /**
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java
index 385e086..bee14ad 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java
@@ -21,7 +21,7 @@
 import org.apache.commons.io.input.NullInputStream;
 import org.apache.tinkerpop.gremlin.console.PluggedIn;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.codehaus.groovy.tools.shell.Groovysh;
+import org.apache.groovy.groovysh.Groovysh;
 import org.codehaus.groovy.tools.shell.IO;
 import org.junit.Test;
 
diff --git a/gremlin-core/pom.xml b/gremlin-core/pom.xml
index 4e93f34..ce243ad 100644
--- a/gremlin-core/pom.xml
+++ b/gremlin-core/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-core</artifactId>
     <name>Apache TinkerPop :: Gremlin Core</name>
@@ -31,8 +31,12 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>commons-configuration</groupId>
-            <artifactId>commons-configuration</artifactId>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-configuration2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
         </dependency>
         <dependency>
             <groupId>commons-collections</groupId>
@@ -105,13 +109,42 @@
         </dependency>
         <dependency>
             <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
+            <artifactId>hamcrest</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>com.google.testing.compile</groupId>
             <artifactId>compile-testing</artifactId>
-            <version>0.10</version>
+            <version>0.15</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.errorprone</groupId>
+                    <artifactId>error_prone_annotations</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- resolve self-conflict within compile-testing -->
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>23.4-android</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.errorprone</groupId>
+                    <artifactId>error_prone_annotations</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.google.errorprone</groupId>
+            <artifactId>error_prone_annotations</artifactId>
+            <version>2.0.19</version>
             <scope>test</scope>
             <exclusions>
               <exclusion>
@@ -154,4 +187,31 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.apache.maven.plugins</groupId>
+                            <artifactId>maven-compiler-plugin</artifactId>
+                            <version>3.8.1</version>
+                            <configuration>
+                                <release>8</release>
+                                <compilerArgs>
+                                    <arg>-parameters</arg>
+                                    <arg>-proc:none</arg>
+                                </compilerArgs>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index cc7881c..9adf03b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -19,28 +19,25 @@
 
 package org.apache.tinkerpop.gremlin.jsr223;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.CombinedConfiguration;
-import org.apache.commons.configuration.CompositeConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationBuilder;
-import org.apache.commons.configuration.ConfigurationUtils;
-import org.apache.commons.configuration.FileConfiguration;
-import org.apache.commons.configuration.HierarchicalConfiguration;
-import org.apache.commons.configuration.MapConfiguration;
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.apache.commons.configuration.SubsetConfiguration;
-import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.CombinedConfiguration;
+import org.apache.commons.configuration2.CompositeConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ConfigurationUtils;
+import org.apache.commons.configuration2.FileBasedConfiguration;
+import org.apache.commons.configuration2.HierarchicalConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.commons.configuration2.PropertiesConfiguration;
+import org.apache.commons.configuration2.SubsetConfiguration;
+import org.apache.commons.configuration2.XMLConfiguration;
+import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
+import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.bulkdumping.BulkDumperVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoader;
-import org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.bulkloading.IncrementalBulkLoader;
-import org.apache.tinkerpop.gremlin.process.computer.bulkloading.OneTimeBulkLoader;
 import org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgram;
 import org.apache.tinkerpop.gremlin.process.computer.clustering.connected.ConnectedComponentVertexProgram;
 import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.ClusterCountMapReduce;
@@ -85,6 +82,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy;
@@ -224,14 +222,13 @@
         CLASS_IMPORTS.add(CombinedConfiguration.class);
         CLASS_IMPORTS.add(CompositeConfiguration.class);
         CLASS_IMPORTS.add(Configuration.class);
-        CLASS_IMPORTS.add(ConfigurationBuilder.class);
         CLASS_IMPORTS.add(ConfigurationUtils.class);
-        CLASS_IMPORTS.add(FileConfiguration.class);
         CLASS_IMPORTS.add(HierarchicalConfiguration.class);
         CLASS_IMPORTS.add(MapConfiguration.class);
         CLASS_IMPORTS.add(PropertiesConfiguration.class);
         CLASS_IMPORTS.add(SubsetConfiguration.class);
         CLASS_IMPORTS.add(XMLConfiguration.class);
+        CLASS_IMPORTS.add(Configurations.class);
         // strategies
         CLASS_IMPORTS.add(ConnectiveStrategy.class);
         CLASS_IMPORTS.add(ElementIdStrategy.class);
@@ -243,6 +240,8 @@
         CLASS_IMPORTS.add(MatchAlgorithmStrategy.class);
         CLASS_IMPORTS.add(ProfileStrategy.class);
         CLASS_IMPORTS.add(AdjacentToIncidentStrategy.class);
+        CLASS_IMPORTS.add(ByModulatorOptimizationStrategy.class);
+        CLASS_IMPORTS.add(CountStrategy.class);
         CLASS_IMPORTS.add(FilterRankingStrategy.class);
         CLASS_IMPORTS.add(IdentityRemovalStrategy.class);
         CLASS_IMPORTS.add(IncidentToAdjacentStrategy.class);
@@ -250,7 +249,6 @@
         CLASS_IMPORTS.add(EarlyLimitStrategy.class);
         CLASS_IMPORTS.add(OrderLimitStrategy.class);
         CLASS_IMPORTS.add(PathProcessorStrategy.class);
-        CLASS_IMPORTS.add(CountStrategy.class);
         CLASS_IMPORTS.add(ComputerVerificationStrategy.class);
         CLASS_IMPORTS.add(LambdaRestrictionStrategy.class);
         CLASS_IMPORTS.add(ReadOnlyStrategy.class);
@@ -275,11 +273,6 @@
         CLASS_IMPORTS.add(Memory.class);
         CLASS_IMPORTS.add(VertexProgram.class);
         CLASS_IMPORTS.add(CloneVertexProgram.class);
-        CLASS_IMPORTS.add(BulkDumperVertexProgram.class);
-        CLASS_IMPORTS.add(BulkLoader.class);
-        CLASS_IMPORTS.add(BulkLoaderVertexProgram.class);
-        CLASS_IMPORTS.add(IncrementalBulkLoader.class);
-        CLASS_IMPORTS.add(OneTimeBulkLoader.class);
         CLASS_IMPORTS.add(ClusterCountMapReduce.class);
         CLASS_IMPORTS.add(ClusterPopulationMapReduce.class);
         CLASS_IMPORTS.add(MemoryTraversalSideEffects.class);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
index 7945d7c..6034793 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.jsr223;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
@@ -214,7 +214,7 @@
                         for (int i = 0; i < parameters.length; i++) {
                             if (parameters[i].isVarArgs()) {
                                 final Class<?> parameterClass = parameters[i].getType().getComponentType();
-                                if (argumentsCopy.length > i && !parameterClass.isAssignableFrom(argumentsCopy[i].getClass())) {
+                                if (argumentsCopy.length > i && argumentsCopy[i] != null && !parameterClass.isAssignableFrom(argumentsCopy[i].getClass())) {
                                     found = false;
                                     break;
                                 }
@@ -226,13 +226,34 @@
                                 newArguments[i] = varArgs;
                                 break;
                             } else {
-                                if (i < argumentsCopy.length &&
-                                        (parameters[i].getType().isAssignableFrom(argumentsCopy[i].getClass()) ||
+                                // try to detect the right method by comparing the type of the parameter to the type
+                                // of the argument. doesn't always work so well because of null arguments which don't
+                                // bring their type in bytecode and rely on position. this doesn't seem to happen often
+                                // ...luckily...because method signatures tend to be sufficiently unique and do not
+                                // encourage whacky use - like g.V().has(null, null) is clearly invalid so we don't
+                                // even need to try to sort that out. on the other hand g.V().has('name',null) which
+                                // is valid hits like four different possible overloads, but we can rely on the most
+                                // generic one which takes Object as the second parameter. that seems to work in this
+                                // case, but it's a shame this isn't nicer. seems like nicer would mean a heavy
+                                // overhaul to Gremlin or to GLVs/bytecode and/or to serialization mechanisms.
+                                //
+                                // the check where argumentsCopy[i] is null could be accompanied by a type check for
+                                // allowable signatures like:
+                                // null == argumentsCopy[i] && parameters[i].getType() == Object.class
+                                // but that doesn't seem helpful. perhaps this approach is fine as long as we ensure
+                                // consistency of null calls to all overloads. in other words addV(String) must behave
+                                // the same as addV(Traversal) if null is used as the argument. so far, that seems to
+                                // be the case. if we find that is not happening we either fix that specific
+                                // inconsistency, start special casing those method finds here, or as mentioned above
+                                // do something far more drastic that doesn't involve reflection.
+                                if (i < argumentsCopy.length && (null == argumentsCopy[i] ||
+                                        (argumentsCopy[i] != null && (
+                                        parameters[i].getType().isAssignableFrom(argumentsCopy[i].getClass()) ||
                                                 (parameters[i].getType().isPrimitive() &&
                                                         (Number.class.isAssignableFrom(argumentsCopy[i].getClass()) ||
                                                                 argumentsCopy[i].getClass().equals(Boolean.class) ||
                                                                 argumentsCopy[i].getClass().equals(Byte.class) ||
-                                                                argumentsCopy[i].getClass().equals(Character.class))))) {
+                                                                argumentsCopy[i].getClass().equals(Character.class))))))) {
                                     newArguments[i] = argumentsCopy[i];
                                 } else {
                                     found = false;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MapReduce.java
index 60a8ad3..05996af 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MapReduce.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MapReduce.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.util.DefaultComputerResult;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/VertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/VertexProgram.java
index 5637740..682ca5b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/VertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/VertexProgram.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.computer;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkdumping/BulkDumperVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkdumping/BulkDumperVertexProgram.java
deleted file mode 100644
index f70fcc2..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkdumping/BulkDumperVertexProgram.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.computer.bulkdumping;
-
-import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
-import org.apache.tinkerpop.gremlin.process.computer.Memory;
-import org.apache.tinkerpop.gremlin.process.computer.MessageScope;
-import org.apache.tinkerpop.gremlin.process.computer.Messenger;
-import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.javatuples.Tuple;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @deprecated As of release 3.2.10, replaced by {@link CloneVertexProgram}.
- */
-@Deprecated
-public class BulkDumperVertexProgram implements VertexProgram<Tuple> {
-
-    private BulkDumperVertexProgram() {
-    }
-
-    @Override
-    public void setup(final Memory memory) {
-    }
-
-    @Override
-    public void execute(final Vertex sourceVertex, final Messenger<Tuple> messenger, final Memory memory) {
-    }
-
-    @Override
-    public boolean terminate(final Memory memory) {
-        return true;
-    }
-
-    @Override
-    public Set<MessageScope> getMessageScopes(final Memory memory) {
-        return Collections.emptySet();
-    }
-
-    @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"})
-    @Override
-    public VertexProgram<Tuple> clone() {
-        return this;
-    }
-
-    @Override
-    public GraphComputer.ResultGraph getPreferredResultGraph() {
-        return GraphComputer.ResultGraph.NEW;
-    }
-
-    @Override
-    public GraphComputer.Persist getPreferredPersist() {
-        return GraphComputer.Persist.EDGES;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.vertexProgramString(this);
-    }
-
-    public static Builder build() {
-        return new Builder();
-    }
-
-    public static class Builder extends AbstractVertexProgramBuilder<Builder> {
-
-        private Builder() {
-            super(BulkDumperVertexProgram.class);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public BulkDumperVertexProgram create(final Graph graph) {
-            return (BulkDumperVertexProgram) VertexProgram.createVertexProgram(graph, configuration);
-        }
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoader.java
deleted file mode 100644
index 3767f73..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoader.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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.computer.bulkloading;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @deprecated As of release 3.2.10, not directly replaced - consider graph provider specific bulk loading methods
- */
-@Deprecated
-public interface BulkLoader {
-
-    /**
-     * Gets or creates a clone of the given vertex in the given graph.
-     *
-     * @param vertex The vertex to be cloned.
-     * @param graph  The graph that holds the cloned vertex after this method was called.
-     * @param g      A standard traversal source for the given graph.
-     * @return The cloned vertex.
-     */
-    public Vertex getOrCreateVertex(final Vertex vertex, final Graph graph, final GraphTraversalSource g);
-
-    /**
-     * Creates a clone of the given edge between the given in- and out-vertices.
-     *
-     * @param edge      The edge to be cloned.
-     * @param outVertex The out-vertex in the given graph..
-     * @param inVertex  The in-vertex in the given graph.
-     * @param graph     The graph that holds the cloned edge after this method was called.
-     * @param g         A standard traversal source for the given graph.
-     * @return The cloned edge.
-     */
-    public default Edge createEdge(final Edge edge, final Vertex outVertex, final Vertex inVertex, final Graph graph, final GraphTraversalSource g) {
-        final Edge result = outVertex.addEdge(edge.label(), inVertex);
-        edge.properties().forEachRemaining(property -> result.property(property.key(), property.value()));
-        return result;
-    }
-
-    /**
-     * Gets or creates a clone of the given edge between the given in- and out-vertices.
-     *
-     * @param edge      The edge to be cloned.
-     * @param outVertex The out-vertex in the given graph..
-     * @param inVertex  The in-vertex in the given graph.
-     * @param graph     The graph that holds the cloned edge after this method was called.
-     * @param g         A standard traversal source for the given graph.
-     * @return The cloned edge.
-     */
-    public Edge getOrCreateEdge(final Edge edge, final Vertex outVertex, final Vertex inVertex, final Graph graph, final GraphTraversalSource g);
-
-    /**
-     * Creates a clone of the given property for the given vertex.
-     *
-     * @param property The property to be cloned.
-     * @param vertex   The vertex in the given graph..
-     * @param graph    The graph that holds the given vertex.
-     * @param g        A standard traversal source for the given graph.
-     * @return The cloned property.
-     */
-    public default VertexProperty createVertexProperty(final VertexProperty<?> property, final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        final VertexProperty result = vertex.property(property.key(), property.value());
-        property.properties().forEachRemaining(metaProperty -> result.property(metaProperty.key(), metaProperty.value()));
-        return result;
-    }
-
-    /**
-     * Gets or creates a clone of the given property for the given vertex.
-     *
-     * @param property The property to be cloned.
-     * @param vertex   The vertex in the given graph..
-     * @param graph    The graph that holds the given vertex.
-     * @param g        A standard traversal source for the given graph.
-     * @return The cloned property.
-     */
-    public VertexProperty getOrCreateVertexProperty(final VertexProperty<?> property, final Vertex vertex, final Graph graph, final GraphTraversalSource g);
-
-    /**
-     * Get a vertex that matches the given vertex from the given graph.
-     *
-     * @param vertex The vertex to be matched.
-     * @param graph  The graph that holds the given vertex.
-     * @param g      A standard traversal source for the given graph.
-     * @return The matched vertex.
-     */
-    public Vertex getVertex(final Vertex vertex, final Graph graph, final GraphTraversalSource g);
-
-    /**
-     * Gets a vertex by its ID from the given graph.
-     *
-     * @param id    The vertex ID.
-     * @param graph The graph that holds the vertex with the given ID.
-     * @param g     A standard traversal source for the given graph.
-     * @return The vertex with the given ID.
-     */
-    public default Vertex getVertexById(final Object id, final Graph graph, final GraphTraversalSource g) {
-        return g.V().hasId(id).next();
-    }
-
-    /**
-     * @return Whether to use user supplied identifiers or not.
-     */
-    public boolean useUserSuppliedIds();
-
-    /**
-     * @return Whether to keep the original vertex identifiers in the target graph or not.
-     */
-    public boolean keepOriginalIds();
-
-    /**
-     * @return The name of the vertex property that is used to store the original vertex id.
-     */
-    public default String getVertexIdProperty() {
-        return BulkLoaderVertexProgram.DEFAULT_BULK_LOADER_VERTEX_ID;
-    }
-
-    /**
-     * Configures the BulkLoader instance.
-     *
-     * @param configuration The BulkLoader configuration.
-     */
-    public void configure(final Configuration configuration);
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoaderVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoaderVertexProgram.java
deleted file mode 100644
index 3570422..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoaderVertexProgram.java
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * 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.computer.bulkloading;
-
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.ConfigurationUtils;
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
-import org.apache.tinkerpop.gremlin.process.computer.Memory;
-import org.apache.tinkerpop.gremlin.process.computer.MessageScope;
-import org.apache.tinkerpop.gremlin.process.computer.Messenger;
-import org.apache.tinkerpop.gremlin.process.computer.VertexComputeKey;
-import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.MutationListener;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.javatuples.Pair;
-import org.javatuples.Tuple;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @deprecated As of release 3.2.10, not directly replaced - consider graph provider specific bulk loading methods
- */
-@Deprecated
-public class BulkLoaderVertexProgram implements VertexProgram<Tuple> {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(BulkLoaderVertexProgram.class);
-
-    public static final String BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX = "gremlin.bulkLoaderVertexProgram";
-    public static final String BULK_LOADER_CLASS_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "class");
-    public static final String BULK_LOADER_VERTEX_ID_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "vertexIdProperty");
-    public static final String INTERMEDIATE_BATCH_SIZE_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "intermediateBatchSize");
-    public static final String KEEP_ORIGINAL_IDS_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "keepOriginalIds");
-    public static final String USER_SUPPLIED_IDS_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "userSuppliedIds");
-    public static final String WRITE_GRAPH_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "writeGraph");
-    public static final String DEFAULT_BULK_LOADER_VERTEX_ID = "bulkLoader.vertex.id";
-
-    private final MessageScope messageScope;
-    private final Set<VertexComputeKey> elementComputeKeys;
-    private Configuration configuration;
-    private BulkLoader bulkLoader;
-    private Graph graph;
-    private GraphTraversalSource g;
-    private long intermediateBatchSize;
-
-    private BulkLoadingListener listener;
-
-    private BulkLoaderVertexProgram() {
-        messageScope = MessageScope.Local.of(__::inE);
-        elementComputeKeys = new HashSet<>();
-    }
-
-    private BulkLoader createBulkLoader() {
-        final BulkLoader loader;
-        final Configuration config = configuration.subset(BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX);
-        if (config.containsKey("class")) {
-            final String className = config.getString("class");
-            try {
-                final Class<?> bulkLoaderClass = Class.forName(className);
-                loader = (BulkLoader) bulkLoaderClass.getConstructor().newInstance();
-            } catch (ClassNotFoundException e) {
-                LOGGER.error("Unable to find custom bulk loader class: {}", className);
-                throw new IllegalStateException(e);
-            } catch (Exception e) {
-                LOGGER.error("Unable to create an instance of the given bulk loader class: {}", className);
-                throw new IllegalStateException(e);
-            }
-        } else {
-            loader = new IncrementalBulkLoader();
-        }
-        loader.configure(configuration);
-        return loader;
-    }
-
-    /**
-     * Eventually commits the current transaction and closes the current graph instance. commit() will be called
-     * if close is set true, otherwise it will only be called if the intermediate batch size is set and reached.
-     *
-     * @param close Whether to close the current graph instance after calling commit() or not.
-     */
-    private void commit(final boolean close) {
-        if (!close && (intermediateBatchSize == 0L || listener.mutations() < intermediateBatchSize))
-            return;
-        if (null != graph) {
-            if (graph.features().graph().supportsTransactions()) {
-                LOGGER.info("Committing transaction on Graph instance: {} [{} mutations]", graph, listener.mutations());
-                try {
-                    graph.tx().commit();
-                    LOGGER.debug("Committed transaction on Graph instance: {}", graph);
-                    listener.resetCounter();
-                } catch (Exception e) {
-                    LOGGER.error("Failed to commit transaction on Graph instance: {}", graph);
-                    graph.tx().rollback();
-                    listener.resetCounter();
-                    throw e;
-                }
-            }
-            if (close) {
-                try {
-                    graph.close();
-                    LOGGER.info("Closed Graph instance: {}", graph);
-                    graph = null;
-                } catch (Exception e) {
-                    LOGGER.warn("Failed to close Graph instance", e);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void setup(final Memory memory) {
-    }
-
-    @Override
-    public void loadState(final Graph graph, final Configuration config) {
-        configuration = new BaseConfiguration();
-        if (config != null) {
-            ConfigurationUtils.copy(config, configuration);
-        }
-        intermediateBatchSize = configuration.getLong(INTERMEDIATE_BATCH_SIZE_CFG_KEY, 0L);
-        elementComputeKeys.add(VertexComputeKey.of(DEFAULT_BULK_LOADER_VERTEX_ID, true));
-        bulkLoader = createBulkLoader();
-    }
-
-    @Override
-    public void storeState(final Configuration config) {
-        VertexProgram.super.storeState(config);
-        if (configuration != null) {
-            ConfigurationUtils.copy(configuration, config);
-        }
-    }
-
-    @Override
-    public void workerIterationStart(final Memory memory) {
-        if (null == graph) {
-            graph = GraphFactory.open(configuration.subset(WRITE_GRAPH_CFG_KEY));
-            LOGGER.info("Opened Graph instance: {}", graph);
-            try {
-                listener = new BulkLoadingListener();
-                g = graph.traversal().withStrategies(EventStrategy.build().addListener(listener).create());
-            } catch (Exception e) {
-                try {
-                    graph.close();
-                } catch (Exception e2) {
-                    LOGGER.warn("Failed to close Graph instance", e2);
-                }
-                throw e;
-            }
-        } else {
-            LOGGER.warn("Leaked Graph instance: {}", graph);
-        }
-    }
-
-    @Override
-    public void workerIterationEnd(final Memory memory) {
-        this.commit(true);
-    }
-
-    @Override
-    public void execute(final Vertex sourceVertex, final Messenger<Tuple> messenger, final Memory memory) {
-        try {
-            executeInternal(sourceVertex, messenger, memory);
-        } catch (Exception e) {
-            if (graph.features().graph().supportsTransactions()) {
-                graph.tx().rollback();
-            }
-            throw e;
-        }
-    }
-
-    private void executeInternal(final Vertex sourceVertex, final Messenger<Tuple> messenger, final Memory memory) {
-        if (memory.isInitialIteration()) {
-            this.listener.resetStats();
-            // get or create the vertex
-            final Vertex targetVertex = bulkLoader.getOrCreateVertex(sourceVertex, graph, g);
-            // write all the properties of the vertex to the newly created vertex
-            final Iterator<VertexProperty<Object>> vpi = sourceVertex.properties();
-            if (this.listener.isNewVertex()) {
-                vpi.forEachRemaining(vp -> bulkLoader.createVertexProperty(vp, targetVertex, graph, g));
-            } else {
-                vpi.forEachRemaining(vp -> bulkLoader.getOrCreateVertexProperty(vp, targetVertex, graph, g));
-            }
-            this.commit(false);
-            if (!bulkLoader.useUserSuppliedIds()) {
-                // create an id pair and send it to all the vertex's incoming adjacent vertices
-                sourceVertex.property(DEFAULT_BULK_LOADER_VERTEX_ID, targetVertex.id());
-                messenger.sendMessage(messageScope, Pair.with(sourceVertex.id(), targetVertex.id()));
-            }
-        } else if (memory.getIteration() == 1) {
-            if (bulkLoader.useUserSuppliedIds()) {
-                final Vertex outV = bulkLoader.getVertex(sourceVertex, graph, g);
-                final boolean incremental = outV.edges(Direction.OUT).hasNext();
-                sourceVertex.edges(Direction.OUT).forEachRemaining(edge -> {
-                    final Vertex inV = bulkLoader.getVertex(edge.inVertex(), graph, g);
-                    if (incremental) {
-                        bulkLoader.getOrCreateEdge(edge, outV, inV, graph, g);
-                    } else {
-                        bulkLoader.createEdge(edge, outV, inV, graph, g);
-                    }
-                    this.commit(false);
-                });
-            } else {
-                // create an id map and populate it with all the incoming messages
-                final Map<Object, Object> idPairs = new HashMap<>();
-                final Iterator<Tuple> idi = messenger.receiveMessages();
-                while (idi.hasNext()) {
-                    final Tuple idPair = idi.next();
-                    idPairs.put(idPair.getValue(0), idPair.getValue(1));
-                }
-                // get the vertex with given the dummy id property
-                final Object outVId = sourceVertex.value(DEFAULT_BULK_LOADER_VERTEX_ID);
-                final Vertex outV = bulkLoader.getVertexById(outVId, graph, g);
-                // for all the incoming edges of the vertex, get the incoming adjacent vertex and write the edge and its properties
-                sourceVertex.edges(Direction.OUT).forEachRemaining(edge -> {
-                    final Object inVId = idPairs.get(edge.inVertex().id());
-                    final Vertex inV = bulkLoader.getVertexById(inVId, graph, g);
-                    bulkLoader.getOrCreateEdge(edge, outV, inV, graph, g);
-                    this.commit(false);
-                });
-            }
-        } else if (memory.getIteration() == 2) {
-            final Object vertexId = sourceVertex.value(DEFAULT_BULK_LOADER_VERTEX_ID);
-            bulkLoader.getVertexById(vertexId, graph, g)
-                    .property(bulkLoader.getVertexIdProperty()).remove();
-            this.commit(false);
-        }
-    }
-
-    @Override
-    public boolean terminate(final Memory memory) {
-        switch (memory.getIteration()) {
-            case 1:
-                return bulkLoader.keepOriginalIds() || bulkLoader.getVertexIdProperty() == null;
-            case 2:
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Set<VertexComputeKey> getVertexComputeKeys() {
-        return elementComputeKeys;
-    }
-
-    @Override
-    public Set<MessageScope> getMessageScopes(final Memory memory) {
-        return Collections.singleton(messageScope);
-    }
-
-    @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"})
-    @Override
-    public VertexProgram<Tuple> clone() {
-        return this;
-    }
-
-    @Override
-    public GraphComputer.ResultGraph getPreferredResultGraph() {
-        return GraphComputer.ResultGraph.ORIGINAL;
-    }
-
-    @Override
-    public GraphComputer.Persist getPreferredPersist() {
-        return GraphComputer.Persist.NOTHING;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder();
-        if (bulkLoader != null) {
-            sb.append("bulkLoader=").append(bulkLoader.getClass().getSimpleName()).append(", ");
-            sb.append("vertexIdProperty=").append(bulkLoader.getVertexIdProperty()).append(", ");
-            sb.append("userSuppliedIds=").append(bulkLoader.useUserSuppliedIds()).append(", ");
-            sb.append("keepOriginalIds=").append(bulkLoader.keepOriginalIds()).append(", ");
-        } else {
-            sb.append("bulkLoader=").append(bulkLoader).append(", ");
-        }
-        sb.append("batchSize=").append(intermediateBatchSize);
-        return StringFactory.vertexProgramString(this, sb.toString());
-    }
-
-    public static Builder build() {
-        return new Builder();
-    }
-
-    public static class Builder extends AbstractVertexProgramBuilder<Builder> {
-
-        private Builder() {
-            super(BulkLoaderVertexProgram.class);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public BulkLoaderVertexProgram create(final Graph graph) {
-            ConfigurationUtils.append(graph.configuration().subset(BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX), configuration);
-            return (BulkLoaderVertexProgram) VertexProgram.createVertexProgram(graph, configuration);
-        }
-
-        private void setGraphConfigurationProperty(final String key, final Object value) {
-            configuration.setProperty(String.join(".", WRITE_GRAPH_CFG_KEY, key), value);
-        }
-
-        /**
-         * Sets the class name of the BulkLoader implementation to be used.
-         */
-        public Builder bulkLoader(final String className) {
-            configuration.setProperty(BULK_LOADER_CLASS_CFG_KEY, className);
-            return this;
-        }
-
-        /**
-         * Sets the class of the BulkLoader implementation to be used.
-         */
-        public Builder bulkLoader(final Class<? extends BulkLoader> clazz) {
-            return bulkLoader(clazz.getCanonicalName());
-        }
-
-        /**
-         * Sets the name of the property that is used to store the original vertex identifiers in the target graph.
-         */
-        public Builder vertexIdProperty(final String name) {
-            configuration.setProperty(BULK_LOADER_VERTEX_ID_CFG_KEY, name);
-            return this;
-        }
-
-        /**
-         * Specifies whether user supplied identifiers should be used when the bulk loader creates vertices in the
-         * target graph.
-         */
-        public Builder userSuppliedIds(final boolean useUserSuppliedIds) {
-            configuration.setProperty(USER_SUPPLIED_IDS_CFG_KEY, useUserSuppliedIds);
-            return this;
-        }
-
-        /**
-         * Specifies whether the original vertex identifiers should be kept in the target graph or not. In case of false
-         * BulkLoaderVertexProgram will add another iteration to remove the properties and it won't be possible to use
-         * the data for further incremental bulk loads.
-         */
-        public Builder keepOriginalIds(final boolean keepOriginalIds) {
-            configuration.setProperty(KEEP_ORIGINAL_IDS_CFG_KEY, keepOriginalIds);
-            return this;
-        }
-
-        /**
-         * The batch size for a single transaction (number of vertices in the vertex loading stage; number of edges in
-         * the edge loading stage).
-         */
-        public Builder intermediateBatchSize(final int batchSize) {
-            configuration.setProperty(INTERMEDIATE_BATCH_SIZE_CFG_KEY, batchSize);
-            return this;
-        }
-
-        /**
-         * A configuration for the target graph that can be passed to GraphFactory.open().
-         */
-        public Builder writeGraph(final String configurationFile) throws ConfigurationException {
-            return writeGraph(new PropertiesConfiguration(configurationFile));
-        }
-
-        /**
-         * A configuration for the target graph that can be passed to GraphFactory.open().
-         */
-        public Builder writeGraph(final Configuration configuration) {
-            configuration.getKeys().forEachRemaining(key -> setGraphConfigurationProperty(key, configuration.getProperty(key)));
-            return this;
-        }
-    }
-
-    @Override
-    public Features getFeatures() {
-        return new Features() {
-            @Override
-            public boolean requiresLocalMessageScopes() {
-                return true;
-            }
-
-            @Override
-            public boolean requiresVertexPropertyAddition() {
-                return true;
-            }
-        };
-    }
-
-    static class BulkLoadingListener implements MutationListener {
-
-        private long counter;
-        private boolean isNewVertex;
-
-        public BulkLoadingListener() {
-            this.counter = 0L;
-            this.isNewVertex = false;
-        }
-
-        public boolean isNewVertex() {
-            return this.isNewVertex;
-        }
-
-        public long mutations() {
-            return this.counter;
-        }
-
-        public void resetStats() {
-            this.isNewVertex = false;
-        }
-
-        public void resetCounter() {
-            this.counter = 0L;
-        }
-
-        @Override
-        public void vertexAdded(final Vertex vertex) {
-            this.isNewVertex = true;
-            this.counter++;
-        }
-
-        @Override
-        public void vertexRemoved(final Vertex vertex) {
-            this.counter++;
-        }
-
-        @Override
-        public void vertexPropertyChanged(final Vertex element, final VertexProperty oldValue, final Object setValue,
-                                          final Object... vertexPropertyKeyValues) {
-            this.counter++;
-        }
-
-        @Override
-        public void vertexPropertyRemoved(final VertexProperty vertexProperty) {
-            this.counter++;
-        }
-
-        @Override
-        public void edgeAdded(final Edge edge) {
-            this.counter++;
-        }
-
-        @Override
-        public void edgeRemoved(final Edge edge) {
-            this.counter++;
-        }
-
-        @Override
-        public void edgePropertyChanged(final Edge element, final Property oldValue, final Object setValue) {
-            this.counter++;
-        }
-
-        @Override
-        public void edgePropertyRemoved(final Edge element, final Property property) {
-            this.counter++;
-        }
-
-        @Override
-        public void vertexPropertyPropertyChanged(final VertexProperty element, final Property oldValue, final Object setValue) {
-            this.counter++;
-        }
-
-        @Override
-        public void vertexPropertyPropertyRemoved(final VertexProperty element, final Property property) {
-            this.counter++;
-        }
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/IncrementalBulkLoader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/IncrementalBulkLoader.java
deleted file mode 100644
index 5713773..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/IncrementalBulkLoader.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.computer.bulkloading;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-
-import java.util.Iterator;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @deprecated As of release 3.2.10, not directly replaced - consider graph provider specific bulk loading methods
- */
-@Deprecated
-public class IncrementalBulkLoader implements BulkLoader {
-
-    private String bulkLoaderVertexId = BulkLoaderVertexProgram.DEFAULT_BULK_LOADER_VERTEX_ID;
-    private boolean keepOriginalIds = true;
-    private boolean userSuppliedIds = false;
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Vertex getOrCreateVertex(final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        final Iterator<Vertex> iterator = useUserSuppliedIds()
-                ? g.V().hasId(vertex.id())
-                : g.V().has(vertex.label(), bulkLoaderVertexId, vertex.id().toString());
-        return iterator.hasNext()
-                ? iterator.next()
-                : useUserSuppliedIds()
-                ? g.addV(vertex.label()).property(T.id, vertex.id()).next()
-                : g.addV(vertex.label()).property(bulkLoaderVertexId, vertex.id().toString()).next();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Edge getOrCreateEdge(final Edge edge, final Vertex outVertex, final Vertex inVertex, final Graph graph, final GraphTraversalSource g) {
-        final Edge e;
-        final Traversal<Vertex, Edge> t = g.V(outVertex).outE(edge.label()).filter(__.inV().is(inVertex));
-        if (t.hasNext()) {
-            e = t.next();
-            edge.properties().forEachRemaining(property -> {
-                final Property<?> existing = e.property(property.key());
-                if (!existing.isPresent() || !existing.value().equals(property.value())) {
-                    e.property(property.key(), property.value());
-                }
-            });
-        } else {
-            e = createEdge(edge, outVertex, inVertex, graph, g);
-        }
-        return e;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public VertexProperty getOrCreateVertexProperty(final VertexProperty<?> property, final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        final VertexProperty<?> vp;
-        final VertexProperty<?> existing = vertex.property(property.key());
-        if (!existing.isPresent()) {
-            return createVertexProperty(property, vertex, graph, g);
-        }
-        if (!existing.value().equals(property.value())) {
-            vp = vertex.property(property.key(), property.value());
-        } else {
-            vp = existing;
-        }
-        property.properties().forEachRemaining(metaProperty -> {
-            final Property<?> existing2 = vp.property(metaProperty.key());
-            if (!existing2.isPresent() || !existing2.value().equals(metaProperty.value())) {
-                vp.property(metaProperty.key(), metaProperty.value());
-            }
-        });
-        return vp;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Vertex getVertex(final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        return useUserSuppliedIds()
-                ? getVertexById(vertex.id(), graph, g)
-                : g.V().has(vertex.label(), bulkLoaderVertexId, vertex.id().toString()).next();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean useUserSuppliedIds() {
-        return userSuppliedIds;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean keepOriginalIds() {
-        return keepOriginalIds;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String getVertexIdProperty() {
-        return bulkLoaderVertexId;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void configure(final Configuration configuration) {
-        if (configuration.containsKey(BulkLoaderVertexProgram.BULK_LOADER_VERTEX_ID_CFG_KEY)) {
-            bulkLoaderVertexId = configuration.getString(BulkLoaderVertexProgram.BULK_LOADER_VERTEX_ID_CFG_KEY);
-        }
-        if (configuration.containsKey(BulkLoaderVertexProgram.USER_SUPPLIED_IDS_CFG_KEY)) {
-            userSuppliedIds = configuration.getBoolean(BulkLoaderVertexProgram.USER_SUPPLIED_IDS_CFG_KEY);
-        }
-        if (configuration.containsKey(BulkLoaderVertexProgram.KEEP_ORIGINAL_IDS_CFG_KEY)) {
-            keepOriginalIds = configuration.getBoolean(BulkLoaderVertexProgram.KEEP_ORIGINAL_IDS_CFG_KEY);
-        }
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/OneTimeBulkLoader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/OneTimeBulkLoader.java
deleted file mode 100644
index c918c7f..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/OneTimeBulkLoader.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.computer.bulkloading;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-
-/**
- * {@link OneTimeBulkLoader} is a {@link BulkLoader} implementation that should be used for initial bulk loads. In
- * contrast to {@link IncrementalBulkLoader} it doesn't store temporary identifiers in the write graph nor does it
- * attempt to find existing elements, instead it  only clones each element from the source graph.
- *
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @deprecated As of release 3.2.10, not directly replaced - consider graph provider specific bulk loading methods
- */
-@Deprecated
-public class OneTimeBulkLoader implements BulkLoader {
-
-    private boolean userSuppliedIds = false;
-
-    /**
-     * Creates a clone of the given vertex in the given graph.
-     */
-    @Override
-    public Vertex getOrCreateVertex(final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        final GraphTraversal<Vertex, Vertex> t = g.addV(vertex.label());
-        return (useUserSuppliedIds() ? t.property(T.id, vertex.id()) : t).next();
-    }
-
-    /**
-     * Creates a clone of the given edge between the given in- and out-vertices.
-     */
-    @Override
-    public Edge getOrCreateEdge(final Edge edge, final Vertex outVertex, final Vertex inVertex, final Graph graph, final GraphTraversalSource g) {
-        return createEdge(edge, outVertex, inVertex, graph, g);
-    }
-
-    /**
-     * Creates a clone of the given property for the given vertex.
-     */
-    @Override
-    public VertexProperty getOrCreateVertexProperty(final VertexProperty<?> property, final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        return createVertexProperty(property, vertex, graph, g);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Vertex getVertex(final Vertex vertex, final Graph graph, final GraphTraversalSource g) {
-        return getVertexById(vertex.id(), graph, g);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean useUserSuppliedIds() {
-        return userSuppliedIds;
-    }
-
-    /**
-     * Always returns false.
-     */
-    @Override
-    public boolean keepOriginalIds() {
-        return false;
-    }
-
-    /**
-     * Always returns null.
-     */
-    @Override
-    public String getVertexIdProperty() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void configure(final Configuration configuration) {
-        if (configuration.containsKey(BulkLoaderVertexProgram.USER_SUPPLIED_IDS_CFG_KEY)) {
-            userSuppliedIds = configuration.getBoolean(BulkLoaderVertexProgram.USER_SUPPLIED_IDS_CFG_KEY);
-        }
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/connected/ConnectedComponentVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/connected/ConnectedComponentVertexProgram.java
index acc8f3c..ca81abf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/connected/ConnectedComponentVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/connected/ConnectedComponentVertexProgram.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.clustering.connected;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationUtils;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ConfigurationUtils;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterCountMapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterCountMapReduce.java
index d343e8e..fcf15cb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterCountMapReduce.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterCountMapReduce.java
@@ -25,7 +25,7 @@
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 
 import java.io.Serializable;
 import java.util.HashSet;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterPopulationMapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterPopulationMapReduce.java
index 0318ad6..301fba1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterPopulationMapReduce.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/ClusterPopulationMapReduce.java
@@ -24,7 +24,7 @@
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 
 import java.io.Serializable;
 import java.util.HashMap;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
index b681807..2ead42e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
@@ -243,23 +243,6 @@
             PureTraversal.storeState(this.configuration, INITIAL_VOTE_STRENGTH_TRAVERSAL, initialVoteStrengthTraversal);
             return this;
         }
-
-        /**
-         * @deprecated As of release 3.2.0, replaced by {@link PeerPressureVertexProgram.Builder#edges(Traversal.Admin)}
-         */
-        @Deprecated
-        public Builder traversal(final TraversalSource traversalSource, final String scriptEngine, final String traversalScript, final Object... bindings) {
-            return this.edges(new ScriptTraversal<>(traversalSource, scriptEngine, traversalScript, bindings));
-        }
-
-        /**
-         * @deprecated As of release 3.2.0, replaced by {@link PeerPressureVertexProgram.Builder#edges(Traversal.Admin)}
-         */
-        @Deprecated
-        public Builder traversal(final Traversal.Admin<Vertex, Edge> edgeTraversal) {
-            return this.edges(edgeTraversal);
-        }
-
     }
 
     ////////////////////////////
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankMapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankMapReduce.java
index cff5e39..b2523b4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankMapReduce.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankMapReduce.java
@@ -24,7 +24,7 @@
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 
 import java.util.Iterator;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
index ce0b5f2..247b1ea 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
@@ -257,31 +257,6 @@
             PureTraversal.storeState(this.configuration, INITIAL_RANK_TRAVERSAL, initialRankTraversal);
             return this;
         }
-
-        /**
-         * @deprecated As of release 3.2.0, replaced by {@link org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram.Builder#initialRank(Traversal.Admin)}
-         */
-        @Deprecated
-        public Builder vertexCount(final long vertexCount) {
-            this.configuration.setProperty(VERTEX_COUNT, (double) vertexCount);
-            return this;
-        }
-
-        /**
-         * @deprecated As of release 3.2.0, replaced by {@link org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram.Builder#edges(Traversal.Admin)}
-         */
-        @Deprecated
-        public Builder traversal(final TraversalSource traversalSource, final String scriptEngine, final String traversalScript, final Object... bindings) {
-            return this.edges(new ScriptTraversal<>(traversalSource, scriptEngine, traversalScript, bindings));
-        }
-
-        /**
-         * @deprecated As of release 3.2.0, replaced by {@link org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram.Builder#edges(Traversal.Admin)}
-         */
-        @Deprecated
-        public Builder traversal(final Traversal.Admin<Vertex, Edge> traversal) {
-            return this.edges(traversal);
-        }
     }
 
     ////////////////////////////
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/search/path/ShortestPathVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/search/path/ShortestPathVertexProgram.java
index 1949c53..88875b1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/search/path/ShortestPathVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/search/path/ShortestPathVertexProgram.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.search.path;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
index eb56484..a5f9dfe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.traversal;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
@@ -178,7 +178,7 @@
                                 this.traversal.get().getParent().asStep().getNextStep().getNextStep() instanceof ComputerResultStep));
 
         // determine how to store halted traversers
-        final Iterator<?> itty = IteratorUtils.filter(this.traversal.get().getStrategies().toList(), strategy -> strategy instanceof HaltedTraverserStrategy).iterator();
+        final Iterator<?> itty = IteratorUtils.filter(this.traversal.get().getStrategies(), strategy -> strategy instanceof HaltedTraverserStrategy).iterator();
         this.haltedTraverserStrategy = itty.hasNext() ? (HaltedTraverserStrategy) itty.next() : HaltedTraverserStrategy.reference();
 
         // register traversal side-effects in memory
@@ -368,7 +368,7 @@
     public void workerIterationEnd(final Memory memory) {
         // store profile metrics in proper ProfileStep metrics
         if (this.profile) {
-            List<ProfileStep> profileSteps = TraversalHelper.getStepsOfAssignableClassRecursively(ProfileStep.class, this.traversal.get());
+            final List<ProfileStep> profileSteps = TraversalHelper.getStepsOfAssignableClassRecursively(ProfileStep.class, this.traversal.get());
             // guess the profile step to store data
             int profileStepIndex = memory.getIteration();
             // if we guess wrongly write timing into last step
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
index 277b4c6..c265927 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
@@ -27,8 +27,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TimesModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
@@ -46,8 +44,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
-public final class PageRankVertexProgramStep extends VertexProgramStep
-        implements TraversalParent, ByModulating, TimesModulating, Configuring {
+public final class PageRankVertexProgramStep extends VertexProgramStep implements TraversalParent, Configuring {
 
     private Parameters parameters = new Parameters();
     private PureTraversal<Vertex, Edge> edgeTraversal;
@@ -76,7 +73,7 @@
             if (!(keyValues[1] instanceof Integer))
                 throw new IllegalArgumentException("PageRank.times requires an Integer as its argument");
             this.times = (int) keyValues[1];
-        }else {
+        } else {
             this.parameters.set(this, keyValues);
         }
     }
@@ -86,33 +83,6 @@
         return parameters;
     }
 
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #configure(Object...)}
-     */
-    @Deprecated
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> edgeTraversal) {
-        configure(PageRank.edges, edgeTraversal);
-    }
-
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #configure(Object...)}
-     */
-    @Deprecated
-    @Override
-    public void modulateBy(final String pageRankProperty) {
-        configure(PageRank.propertyName, pageRankProperty);
-    }
-
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #configure(Object...)}
-     */
-    @Deprecated
-    @Override
-    public void modulateTimes(int times) {
-        configure(PageRank.times, times);
-    }
-
     @Override
     public List<Traversal.Admin<Vertex, Edge>> getLocalChildren() {
         return Collections.singletonList(this.edgeTraversal.get());
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java
index e1cba60..d98cf5e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java
@@ -26,9 +26,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TimesModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
@@ -46,8 +44,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
-public final class PeerPressureVertexProgramStep extends VertexProgramStep
-        implements TraversalParent, ByModulating, TimesModulating, Configuring {
+public final class PeerPressureVertexProgramStep extends VertexProgramStep implements TraversalParent, Configuring {
 
     private Parameters parameters = new Parameters();
     private PureTraversal<Vertex, Edge> edgeTraversal;
@@ -89,33 +86,6 @@
         return super.hashCode() ^ this.edgeTraversal.hashCode() ^ this.clusterProperty.hashCode() ^ this.times;
     }
 
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #configure(Object...)}
-     */
-    @Deprecated
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> edgeTraversal) {
-        configure(PeerPressure.edges, edgeTraversal);
-    }
-
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #configure(Object...)}
-     */
-    @Deprecated
-    @Override
-    public void modulateBy(final String clusterProperty) {
-        configure(PeerPressure.propertyName, clusterProperty);
-    }
-
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #configure(Object...)}
-     */
-    @Deprecated
-    @Override
-    public void modulateTimes(int times) {
-        configure(PeerPressure.times, times);
-    }
-
     @Override
     public List<Traversal.Admin<Vertex, Edge>> getLocalChildren() {
         return Collections.singletonList(this.edgeTraversal.get());
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java
index 49add72..025069e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
 import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
@@ -48,7 +48,6 @@
         super(traversal);
         this.configuration = new HashMap<>();
         final MapConfiguration base = new MapConfiguration(this.configuration);
-        base.setDelimiterParsingDisabled(true);
         vertexProgram.storeState(base);
         this.toStringOfVertexProgram = vertexProgram.toString();
         this.traverserRequirements = vertexProgram.getTraverserRequirements();
@@ -57,7 +56,6 @@
     @Override
     public VertexProgram generateProgram(final Graph graph, final Memory memory) {
         final MapConfiguration base = new MapConfiguration(this.configuration);
-        base.setDelimiterParsingDisabled(true);
         PureTraversal.storeState(base, ROOT_TRAVERSAL, TraversalHelper.getRootTraversal(this.getTraversal()).clone());
         base.setProperty(STEP_ID, this.getId());
         if (memory.exists(TraversalVertexProgram.HALTED_TRAVERSERS))
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
index 30cfee5..3fa36a9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
@@ -74,7 +74,7 @@
         final Traversal.Admin<?, ?> computerSpecificTraversal = this.computerTraversal.getPure();
         final TraversalStrategies computerSpecificStrategies = this.getTraversal().getStrategies().clone();
 
-        IteratorUtils.filter(TraversalStrategies.GlobalCache.getStrategies(graph.getClass()).toList(),
+        IteratorUtils.filter(TraversalStrategies.GlobalCache.getStrategies(graph.getClass()),
                 s -> s instanceof TraversalStrategy.ProviderOptimizationStrategy).forEach(computerSpecificStrategies::addStrategies);
 
         computerSpecificTraversal.setStrategies(computerSpecificStrategies);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
index fa6e23f..8c2e28a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.step.VertexComputing;
@@ -34,7 +34,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ReadWriting;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
@@ -71,7 +71,9 @@
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
         // VertexPrograms can only execute at the root level of a Traversal and should not be applied locally prior to RemoteStrategy
-        if (!(traversal.getParent() instanceof EmptyStep) || traversal.getStrategies().getStrategy(RemoteStrategy.class).isPresent())
+        if (!(traversal.isRoot())
+                || traversal instanceof AbstractLambdaTraversal
+                || traversal.getStrategies().getStrategy(RemoteStrategy.class).isPresent())
             return;
 
         // back propagate as()-labels off of vertex computing steps
@@ -160,8 +162,8 @@
     }
 
     public static Optional<Computer> getComputer(final TraversalStrategies strategies) {
-        final Optional<TraversalStrategy<?>> optional = strategies.toList().stream().filter(strategy -> strategy instanceof VertexProgramStrategy).findAny();
-        return optional.isPresent() ? Optional.of(((VertexProgramStrategy) optional.get()).computer) : Optional.empty();
+        final Optional<VertexProgramStrategy> optional = strategies.getStrategy(VertexProgramStrategy.class);
+        return optional.isPresent() ? Optional.of(optional.get().computer) : Optional.empty();
     }
 
     public void addGraphComputerStrategies(final TraversalSource traversalSource) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/MessagePassingReductionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/MessagePassingReductionStrategy.java
index cff152e..f32d376 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/MessagePassingReductionStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/MessagePassingReductionStrategy.java
@@ -40,6 +40,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ProfileSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
@@ -98,7 +99,26 @@
                         !(computerTraversal.getStartStep().getNextStep() instanceof Barrier) &&
                         TraversalHelper.hasStepOfAssignableClassRecursively(Arrays.asList(VertexStep.class, EdgeVertexStep.class), computerTraversal) &&
                         TraversalHelper.isLocalStarGraph(computerTraversal)) {
-                    final Step barrier = (Step) TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, computerTraversal).orElse(null);
+                    Step barrier = (Step) TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, computerTraversal).orElse(null);
+
+                    // if the barrier isn't present gotta check for uncapped profile() which can happen if you do
+                    // profile("metrics") - see below for more worries
+                    if (null == barrier) {
+                        final ProfileSideEffectStep pses = TraversalHelper.getFirstStepOfAssignableClass(ProfileSideEffectStep.class, computerTraversal).orElse(null);
+                        if (pses != null)
+                            barrier = pses.getPreviousStep();
+                    }
+
+                    // if the barrier is a profile() then we'll mess stuff up if we wrap that in a local() as in:
+                    //    local(..., ProfileSideEffectStep)
+                    // which won't compute right on OLAP (or anything??). By stepping back we cut things off at
+                    // just before the ProfileSideEffectStep to go inside the local() so that ProfileSideEffectStep
+                    // shows up just after it
+                    //
+                    // why does this strategy need to know so much about profile!?!
+                    if (barrier != null && barrier.getPreviousStep() instanceof ProfileSideEffectStep)
+                        barrier = barrier.getPreviousStep().getPreviousStep();
+
                     if (MessagePassingReductionStrategy.insertElementId(barrier)) // out().count() -> out().id().count()
                         TraversalHelper.insertBeforeStep(new IdStep(computerTraversal), barrier, computerTraversal);
                     if (!(MessagePassingReductionStrategy.endsWithElement(null == barrier ? computerTraversal.getEndStep() : barrier))) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
index 3d8cedc..680dd79 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.util;
 
-import org.apache.commons.configuration.BaseConfiguration;
+import org.apache.commons.configuration2.BaseConfiguration;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
@@ -29,21 +29,10 @@
 
     protected final BaseConfiguration configuration = new BaseConfiguration();
 
-    public AbstractVertexProgramBuilder() {
-        this.configuration.setDelimiterParsingDisabled(true);
-    }
-
     public AbstractVertexProgramBuilder(final Class<? extends VertexProgram> vertexProgramClass) {
-        this();
         this.configuration.setProperty(VertexProgram.VERTEX_PROGRAM, vertexProgramClass.getName());
     }
 
-    /*@Override
-    public B graph(final Graph graph) {
-        this.configuration.setProperty(Graph.GRAPH, graph.getClass().getName());
-        return (B) this;
-    }*/
-
     /**
      * {@inheritDoc}
      */
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
index 2e4082c..77453fe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.util;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.VertexComputeKey;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticMapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticMapReduce.java
index ee90a53..30f2590 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticMapReduce.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticMapReduce.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.util;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticVertexProgram.java
index 87f975d..b4d097a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/StaticVertexProgram.java
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.process.computer.util;
 
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/VertexProgramHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/VertexProgramHelper.java
index 2297c90..ef497ff 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/VertexProgramHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/VertexProgramHelper.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer.util;
 
-import org.apache.commons.configuration.AbstractConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.VertexComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
@@ -61,8 +61,6 @@
     }
 
     public static void serialize(final Object object, final Configuration configuration, final String key) {
-        if (configuration instanceof AbstractConfiguration)
-            ((AbstractConfiguration) configuration).setDelimiterParsingDisabled(true);
         try {
             configuration.setProperty(key, Base64.getEncoder().encodeToString(Serializer.serializeObject(object)));
         } catch (final IOException e) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/RemoteConnection.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/RemoteConnection.java
index 0c124e7..c0daaa7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/RemoteConnection.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/RemoteConnection.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.remote;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
index b233a31..363de6e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
@@ -53,6 +53,11 @@
     public abstract Traverser.Admin<E> nextTraverser();
 
     @Override
+    public TraversalSideEffects getSideEffects() {
+        throw new UnsupportedOperationException("Remote traversals do not support this method");
+    }
+
+    @Override
     public Bytecode getBytecode() {
         throw new UnsupportedOperationException("Remote traversals do not support this method");
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversalSideEffects.java
deleted file mode 100644
index 3456848..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversalSideEffects.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.remote.traversal;
-
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-
-import java.util.Optional;
-import java.util.function.BinaryOperator;
-import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.8, not directly replaced, prefer use of {@link GraphTraversal#cap(String, String...)}
- * to return the result as part of the traversal iteration.
- */
-@Deprecated
-public abstract class AbstractRemoteTraversalSideEffects implements RemoteTraversalSideEffects {
-
-    @Override
-    public void set(final String key, final Object value) throws IllegalArgumentException {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public void remove(final String key) {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <V> void register(final String key, final Supplier<V> initialValue, BinaryOperator<V> reducer) {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <V> void registerIfAbsent(final String key, final Supplier<V> initialValue, BinaryOperator<V> reducer) {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <V> BinaryOperator<V> getReducer(final String key) throws IllegalArgumentException {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <V> Supplier<V> getSupplier(final String key) throws IllegalArgumentException {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public void add(final String key, final Object value) throws IllegalArgumentException {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <S> void setSack(final Supplier<S> initialValue, UnaryOperator<S> splitOperator, final BinaryOperator<S> mergeOperator) {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <S> Supplier<S> getSackInitialValue() {
-        return null;
-        // throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <S> UnaryOperator<S> getSackSplitter() {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public <S> BinaryOperator<S> getSackMerger() {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public TraversalSideEffects clone() {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-
-    @Override
-    public void mergeInto(final TraversalSideEffects sideEffects) {
-        throw new UnsupportedOperationException("Remote traversals do not support this method");
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java
index 10e27ae..9dc37e7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java
@@ -39,15 +39,6 @@
         return t.asAdmin().nextTraverser();
     }
 
-    /**
-     * @deprecated as of release 3.3.8, not directly replaced, see {@link Admin#getSideEffects()} for more information.
-     */
-    @Override
-    @Deprecated
-    public RemoteTraversalSideEffects getSideEffects() {
-        return new EmbeddedRemoteTraversalSideEffects(t.asAdmin().getSideEffects());
-    }
-
     @Override
     public boolean hasNext() {
         return t.hasNext();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java
deleted file mode 100644
index 06815fd..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.remote.traversal;
-
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-
-import java.util.Set;
-
-/**
- * Generated by the {@link EmbeddedRemoteTraversal} to help simulate a remote traversal side-effects within the same JVM.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.8, not directly replaced, prefer use of {@link GraphTraversal#cap(String, String...)}
- * to return the result as part of the traversal iteration.
- */
-@Deprecated
-public class EmbeddedRemoteTraversalSideEffects extends AbstractRemoteTraversalSideEffects {
-
-    private final TraversalSideEffects sideEffects;
-
-    public EmbeddedRemoteTraversalSideEffects(final TraversalSideEffects sideEffects) {
-        this.sideEffects = sideEffects;
-    }
-
-    @Override
-    public <V> V get(final String key) throws IllegalArgumentException {
-        return sideEffects.get(key);
-    }
-
-    @Override
-    public Set<String> keys() {
-        return sideEffects.keys();
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
index ed4b1eb..69db6c5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
@@ -37,14 +37,4 @@
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public interface RemoteTraversal<S,E> extends Traversal.Admin<S,E> {
-
-    /**
-     * Returns remote side-effects generated by the traversal so that they can be accessible to the client. Note that
-     * "side-effect" refers to the value in "a" in the traversal {@code g.V().aggregate('a').values('name')}.
-     *
-     * @deprecated as of release 3.3.8, not directly replaced, see {@link Admin#getSideEffects()} for more information.
-     */
-    @Override
-    @Deprecated
-    public RemoteTraversalSideEffects getSideEffects();
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java
deleted file mode 100644
index 0d1a510..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.remote.traversal;
-
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalSideEffects;
-
-/**
- * When a traversal is executed remotely, the ability to retrieve those side-effects (i.e. the value in "a" in the
- * traversal {@code g.V().aggregate('a').values('name')}) can be exposed through this interface. As an example,
- * with TinkerPop's {@code DriverRemoteConnection} that connects to Gremlin Server as a "remote", the side-effects
- * are left on the server. The {@code RemoteTraversalSideEffects} implementation, in that case, lazily loads those
- * side-effects when requested. Implementations should attempt to match the features of the locally processed
- * {@link DefaultTraversalSideEffects} to keep consistency.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.8, not directly replaced, prefer use of {@link GraphTraversal#cap(String, String...)}
- * to return the result as part of the traversal iteration.
- */
-@Deprecated
-public interface RemoteTraversalSideEffects extends TraversalSideEffects, AutoCloseable {
-
-    /**
-     * If the "remote" that actually executed the traversal maintained resources that can be released, when the user
-     * is done with the side-effects, then this method can be used to trigger that release.
-     */
-    @Override
-    public default void close() throws Exception {
-        //  do nothing
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
index a103f6a..be623cd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
@@ -88,7 +88,6 @@
             if (null == traversalFuture.get()) {
                 traversalFuture.set(this.remoteConnection.submitAsync(this.traversal.getBytecode()).<Traversal<?, E>>thenApply(t -> {
                     this.remoteTraversal = (RemoteTraversal<?, E>) t;
-                    this.traversal.setSideEffects(this.remoteTraversal.getSideEffects());
                     return traversal;
                 }));
             }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/strategy/decoration/RemoteStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/strategy/decoration/RemoteStrategy.java
index 79855d0..fcd514e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/strategy/decoration/RemoteStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/strategy/decoration/RemoteStrategy.java
@@ -82,7 +82,7 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!(traversal.getParent() instanceof EmptyStep))
+        if (!(traversal.isRoot()))
             return;
 
         // remote step wraps the traversal and emits the results from the remote connection.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/AnonymousTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/AnonymousTraversalSource.java
index b0be46f..f067451 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/AnonymousTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/AnonymousTraversalSource.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -62,7 +62,8 @@
      * @param configFile a path to a file that would normally be provided to configure a {@link RemoteConnection}
      */
     public T withRemote(final String configFile) throws Exception {
-        return withRemote(new PropertiesConfiguration(configFile));
+        final Configurations configs = new Configurations();
+        return withRemote(configs.properties((configFile)));
     }
 
     /**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
index a406c57..ffe6390 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
@@ -137,6 +137,10 @@
         return bindingsMap;
     }
 
+    public boolean isEmpty() {
+        return this.sourceInstructions.isEmpty() && this.stepInstructions.isEmpty();
+    }
+
     private static final void addArgumentBinding(final Map<String, Object> bindingsMap, final Object argument) {
         if (argument instanceof Binding)
             bindingsMap.put(((Binding) argument).key, ((Binding) argument).value);
@@ -287,9 +291,14 @@
                 return new Binding<>(variable, convertArgument(argument, false));
         }
         //
-        if (argument instanceof Traversal)
+        if (argument instanceof Traversal) {
+            // prevent use of "g" to spawn child traversals
+            if (((Traversal) argument).asAdmin().getTraversalSource().isPresent())
+                throw new IllegalStateException(String.format(
+                        "The child traversal of %s was not spawned anonymously - use the __ class rather than a TraversalSource to construct the child traversal", argument));
+
             return ((Traversal) argument).asAdmin().getBytecode();
-        else if (argument instanceof Map) {
+        } else if (argument instanceof Map) {
             final Map<Object, Object> map = new LinkedHashMap<>(((Map) argument).size());
             for (final Map.Entry<?, ?> entry : ((Map<?, ?>) argument).entrySet()) {
                 map.put(convertArgument(entry.getKey(), true), convertArgument(entry.getValue(), true));
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Order.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Order.java
index 2b50a0c..d4d55b0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Order.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Order.java
@@ -32,52 +32,16 @@
 public enum Order implements Comparator<Object> {
 
     /**
-     * Order in ascending fashion
-     *
-     * @since 3.0.0-incubating
-     * @deprecated As of release 3.3.4, replaced by {@link #asc}.
-     */
-    @Deprecated
-    incr {
-        @Override
-        public int compare(final Object first, final Object second) {
-            return asc.compare(first, second);
-        }
-
-        @Override
-        public Order reversed() {
-            return decr;
-        }
-    },
-
-    /**
-     * Order in descending fashion.
-     *
-     * @since 3.0.0-incubating
-     * @deprecated As of release 3.3.4, replaced by {@link #desc}.
-     */
-    @Deprecated
-    decr {
-        @Override
-        public int compare(final Object first, final Object second) {
-            return desc.compare(first, second);
-        }
-
-        @Override
-        public Order reversed() {
-            return incr;
-        }
-    },
-
-    /**
-     * Order in a random fashion.
+     * Order in a random fashion. While this enum implements {@code Comparator}, the {@code compare(a,b)} method is not
+     * supported as a direct call. This change to the implementation of {@code compare(a,b)} occurred at 3.5.0 but
+     * this implementation was never used directly within the TinkerPop code base.
      *
      * @since 3.0.0-incubating
      */
     shuffle {
         @Override
         public int compare(final Object first, final Object second) {
-            return RANDOM.nextBoolean() ? -1 : 1;
+            throw new UnsupportedOperationException("Order.shuffle should not be used as an actual Comparator - it is a marker only");
         }
 
         @Override
@@ -87,11 +51,13 @@
     },
 
     /**
-     * Order in ascending fashion
+     * Order in ascending fashion.
      *
      * @since 3.3.4
      */
     asc {
+        private final Comparator<Comparable> ascendingComparator = Comparator.nullsFirst(Comparator.<Comparable>naturalOrder());
+
         @Override
         public int compare(final Object first, final Object second) {
             // need to convert enum to string representations for comparison or else you can get cast exceptions.
@@ -100,7 +66,7 @@
             final Object s = second instanceof Enum<?> ? ((Enum<?>) second).name() : second;
             return f instanceof Number && s instanceof Number
                     ? NumberHelper.compare((Number) f, (Number) s)
-                    : Comparator.<Comparable>naturalOrder().compare((Comparable) f, (Comparable) s);
+                    : ascendingComparator.compare((Comparable) f, (Comparable) s);
         }
 
         @Override
@@ -115,6 +81,8 @@
      * @since 3.3.4
      */
     desc {
+        private final Comparator<Comparable> descendingComparator = Comparator.nullsLast(Comparator.<Comparable>reverseOrder());
+
         @Override
         public int compare(final Object first, final Object second) {
             // need to convert enum to string representations for comparison or else you can get cast exceptions.
@@ -123,7 +91,7 @@
             final Object s = second instanceof Enum<?> ? ((Enum<?>) second).name() : second;
             return f instanceof Number && s instanceof Number
                     ? NumberHelper.compare((Number) s, (Number) f)
-                    : Comparator.<Comparable>reverseOrder().compare((Comparable) f, (Comparable) s);
+                    : descendingComparator.compare((Comparable) f, (Comparable) s);
         }
 
         @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Script.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Script.java
new file mode 100644
index 0000000..ff227df
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Script.java
@@ -0,0 +1,105 @@
+/*
+ *  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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * General representation of script
+ *
+ * @author Stark Arya (sandszhou.zj@alibaba-inc.com)
+ */
+public final class Script {
+    private static final String KEY_PREFIX = "_args_";
+    private final StringBuilder  scriptBuilder;
+    private final Map<Object, String> parameters;
+
+    public Script() {
+        scriptBuilder = new StringBuilder();
+        parameters = new HashMap<>();
+    }
+
+    public void init() {
+        scriptBuilder.setLength(0);
+        parameters.clear();
+    }
+
+    public Script append(final String script) {
+       scriptBuilder.append(script);
+       return this;
+    }
+
+    public Script setCharAtEnd(final char ch) {
+        scriptBuilder.setCharAt(scriptBuilder.length() - 1, ch);
+        return this;
+    }
+
+    public <V> Script getBoundKeyOrAssign(final boolean withParameters, final V value) {
+        if (withParameters) {
+            if (!parameters.containsKey(value)) {
+                parameters.put(value, getNextBoundKey());
+            }
+            append(parameters.get(value));
+        } else {
+            append(value.toString());
+        }
+        return this;
+    }
+
+    public String getScript() {
+        return scriptBuilder.toString();
+    }
+
+    public Optional<Map<String,Object>> getParameters() {
+        return Optional.ofNullable(parameters.isEmpty() ? null : parameters.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)));
+    }
+
+    /**
+     * @return  a monotonically increasing key
+     */
+    private String getNextBoundKey() {
+        return KEY_PREFIX + parameters.size();
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        final List<String> strings = Stream.of(new Object[]{getScript(), getParameters()})
+                .filter(o -> null != o)
+                .filter(o -> {
+                    if (o instanceof Map) {
+                        return !((Map) o).isEmpty();
+                    } else {
+                        return !o.toString().isEmpty();
+                    }
+                })
+                .map(Object::toString).collect(Collectors.toList());
+        if (!strings.isEmpty()) {
+            builder.append('(');
+            builder.append(String.join(",", strings));
+            builder.append(')');
+        }
+        return "Script[" + builder.toString() + "]";
+    }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
index 8cdd84d..796f63f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
@@ -27,6 +27,7 @@
  * The parameterization of Translator is S (traversal source) and T (full translation).
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stark Arya (sandszhou.zj@alibaba-inc.com)
  */
 public interface Translator<S, T> {
 
@@ -58,15 +59,15 @@
     ///
 
     /**
-     * Translates bytecode to a string representation.
+     * Translates bytecode to a Script representation.
      */
-    public interface ScriptTranslator extends Translator<String, String> {
+    public interface ScriptTranslator extends Translator<String, Script> {
 
         /**
          * Provides a way for the {@link ScriptTranslator} to convert various data types to their string
          * representations in their target language.
          */
-        public interface TypeTranslator extends BiFunction<String, Object, Object> { }
+        public interface TypeTranslator extends BiFunction<String, Object, Script> { }
     }
 
     /**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
index 11c12c3..efed87b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.step.map.RemoteStep;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
@@ -153,7 +153,7 @@
     /**
      * Starts a promise to execute a function on the current {@code Traversal} that will be completed in the future.
      * Note that this method can only be used if the {@code Traversal} is constructed using
-     * {@link TraversalSource#withRemote(Configuration)}. Calling this method otherwise will yield an
+     * {@link AnonymousTraversalSource#withRemote(Configuration)}. Calling this method otherwise will yield an
      * {@code IllegalStateException}.
      */
     public default <T> CompletableFuture<T> promise(final Function<Traversal<S, E>, T> traversalFunction) {
@@ -417,15 +417,17 @@
         /**
          * Apply the registered {@link TraversalStrategies} to the traversal.
          * Once the strategies are applied, the traversal is "locked" and can no longer have steps added to it.
-         * The order of operations for strategy applications should be: globally id steps, apply strategies to root traversal, then to nested traversals.
+         * The order of operations for strategy applications should be: globally id steps, apply each strategy in turn
+         * to root traversal, then recursively to nested traversals.
          *
          * @throws IllegalStateException if the {@link TraversalStrategies} have already been applied
          */
         public void applyStrategies() throws IllegalStateException;
 
         /**
-         * Get the {@link TraverserGenerator} associated with this traversal. The traversal generator creates
-         * {@link Traverser} instances that are respective of the traversal's {@link TraverserRequirement}.
+         * Get the {@link TraverserGenerator} associated with this traversal.
+         * The traversal generator creates {@link Traverser} instances that are respective of the traversal's
+         * {@link TraverserRequirement}.
          *
          * @return the generator of traversers
          */
@@ -488,22 +490,30 @@
         public TraversalStrategies getStrategies();
 
         /**
-         * Set the {@link TraversalParent} {@link Step} that is the parent of this traversal.
-         * Traversals can be nested and this is the means by which the traversal tree is connected.
+         * Set the {@link TraversalParent} {@link Step} that is the parent of this traversal. Traversals can be nested
+         * and this is the means by which the traversal tree is connected. If there is no parent, then it should be a
+         * {@link EmptyStep}.
          *
-         * @param step the traversal holder parent step
+         * @param step the traversal holder parent step or {@link EmptyStep} if it has no parent
          */
         public void setParent(final TraversalParent step);
 
         /**
-         * Get the {@link TraversalParent} {@link Step} that is the parent of this traversal.
-         * Traversals can be nested and this is the means by which the traversal tree is walked.
+         * Get the {@link TraversalParent} {@link Step} that is the parent of this traversal. Traversals can be nested
+         * and this is the means by which the traversal tree is walked.
          *
-         * @return the traversal holder parent step
+         * @return the traversal holder parent step or {@link EmptyStep} if it has no parent.
          */
         public TraversalParent getParent();
 
         /**
+         * Determines if the traversal is at the root level.
+         */
+        public default boolean isRoot() {
+            return getParent() instanceof EmptyStep;
+        }
+
+        /**
          * Cloning is used to duplicate the traversal typically in OLAP environments.
          *
          * @return The cloned traversal
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
index 04fdf01..fafef6c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
@@ -18,26 +18,20 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
-import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SackStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SideEffectStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
-import java.lang.reflect.Constructor;
 import java.util.Optional;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 
-import static org.apache.tinkerpop.gremlin.process.remote.RemoteConnection.GREMLIN_REMOTE_CONNECTION_CLASS;
-
 /**
  * A {@code TraversalSource} is used to create {@link Traversal} instances.
  * A traversal source can generate any number of {@link Traversal} instances.
@@ -373,52 +367,6 @@
         return clone;
     }
 
-    /**
-     * Configures the {@code TraversalSource} as a "remote" to issue the {@link Traversal} for execution elsewhere.
-     * Expects key for {@link RemoteConnection#GREMLIN_REMOTE_CONNECTION_CLASS} as well as any configuration required by
-     * the underlying {@link RemoteConnection} which will be instantiated. Note that the {@code Configuration} object
-     * is passed down without change to the creation of the {@link RemoteConnection} instance.
-     *
-     * @deprecated As of release 3.3.5, replaced by {@link AnonymousTraversalSource#withRemote(Configuration)}.
-     * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-2078">TINKERPOP-2078</a>
-     */
-    @Deprecated
-    public default TraversalSource withRemote(final Configuration conf) {
-        if (!conf.containsKey(GREMLIN_REMOTE_CONNECTION_CLASS))
-            throw new IllegalArgumentException("Configuration must contain the '" + GREMLIN_REMOTE_CONNECTION_CLASS + "' key");
-        final RemoteConnection remoteConnection;
-        try {
-            final Class<? extends RemoteConnection> clazz = Class.forName(conf.getString(GREMLIN_REMOTE_CONNECTION_CLASS)).asSubclass(RemoteConnection.class);
-            final Constructor<? extends RemoteConnection> ctor = clazz.getConstructor(Configuration.class);
-            remoteConnection = ctor.newInstance(conf);
-        } catch (Exception ex) {
-            throw new IllegalStateException(ex);
-        }
-        return withRemote(remoteConnection);
-    }
-    /**
-     * Configures the {@code TraversalSource} as a "remote" to issue the {@link Traversal} for execution elsewhere.
-     * Calls {@link #withRemote(Configuration)} after reading the properties file specified.
-     *
-     * @deprecated As of release 3.3.5, replaced by {@link AnonymousTraversalSource#withRemote(String)}.
-     * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-2078">TINKERPOP-2078</a>
-     */
-    @Deprecated
-    public default TraversalSource withRemote(final String configFile) throws Exception {
-        return withRemote(new PropertiesConfiguration(configFile));
-    }
-    /**
-     * Configures the {@code TraversalSource} as a "remote" to issue the {@link Traversal} for execution elsewhere.
-     * Implementations should track {@link RemoteConnection} instances that are created and call
-     * {@link RemoteConnection#close()} on them when the {@code TraversalSource} itself is closed.
-     *
-     * @param connection the {@link RemoteConnection} instance to use to submit the {@link Traversal}.
-     * @deprecated As of release 3.3.5, replaced by {@link AnonymousTraversalSource#withRemote(RemoteConnection)}.
-     * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-2078">TINKERPOP-2078</a>
-     */
-    @Deprecated
-    public TraversalSource withRemote(final RemoteConnection connection);
-
     public default Optional<Class> getAnonymousTraversalClass() {
         return Optional.empty();
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 6c2c2f3..63842b0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -27,6 +27,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.InlineFilterStrategy;
@@ -41,6 +42,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.apache.tinkerpop.gremlin.util.tools.MultiMap;
 
 import java.io.Serializable;
@@ -49,6 +51,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -64,14 +67,22 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Matthias Broecheler (me@matthiasb.com)
  */
-public interface TraversalStrategies extends Serializable, Cloneable {
+public interface TraversalStrategies extends Serializable, Cloneable, Iterable<TraversalStrategy<?>> {
 
     static List<Class<? extends TraversalStrategy>> STRATEGY_CATEGORIES = Collections.unmodifiableList(Arrays.asList(TraversalStrategy.DecorationStrategy.class, TraversalStrategy.OptimizationStrategy.class, TraversalStrategy.ProviderOptimizationStrategy.class, TraversalStrategy.FinalizationStrategy.class, TraversalStrategy.VerificationStrategy.class));
 
     /**
-     * Return all the {@link TraversalStrategy} singleton instances associated with this {@link TraversalStrategies}.
+     * Return an immutable list of the {@link TraversalStrategy} instances.
      */
-    public List<TraversalStrategy<?>> toList();
+    public default List<TraversalStrategy<?>> toList() {
+        return Collections.unmodifiableList(IteratorUtils.list(iterator()));
+    }
+
+    /**
+     * Return an {@code Iterator} of the {@link TraversalStrategy} instances.
+     */
+    @Override
+    public Iterator<TraversalStrategy<?>> iterator();
 
     /**
      * Return the {@link TraversalStrategy} instance associated with the provided class.
@@ -81,21 +92,11 @@
      * @return an optional containing the strategy instance or not
      */
     public default <T extends TraversalStrategy> Optional<T> getStrategy(final Class<T> traversalStrategyClass) {
-        return (Optional) toList().stream().filter(s -> traversalStrategyClass.isAssignableFrom(s.getClass())).findAny();
+        return (Optional<T>) IteratorUtils.stream(iterator()).
+                filter(s -> traversalStrategyClass.isAssignableFrom(s.getClass())).findAny();
     }
 
     /**
-     * Apply all the {@link TraversalStrategy} optimizers to the {@link Traversal}. This method must ensure that the
-     * strategies are sorted prior to application.
-     *
-     * @param traversal the traversal to apply the strategies to
-     * @deprecated As of release 3.3.10, not directly replaced as this mode of strategy application has not been
-     * utilized since early days of 3.x
-     */
-    @Deprecated
-    public void applyStrategies(final Traversal.Admin<?, ?> traversal);
-
-    /**
      * Add all the provided {@link TraversalStrategy} instances to the current collection.
      * When all the provided strategies have been added, the collection is resorted.
      *
@@ -221,6 +222,7 @@
                     InlineFilterStrategy.instance(),
                     IncidentToAdjacentStrategy.instance(),
                     AdjacentToIncidentStrategy.instance(),
+                    ByModulatorOptimizationStrategy.instance(),
                     FilterRankingStrategy.instance(),
                     MatchPredicateStrategy.instance(),
                     RepeatUnrollStrategy.instance(),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
index 03c31ab..9860c36 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
index e07bec1..fc58c62 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
@@ -18,9 +18,11 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal;
 
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.LoopsStep;
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
 
 import java.io.Serializable;
+import java.util.Comparator;
 import java.util.Set;
 import java.util.function.Function;
 
@@ -134,7 +136,12 @@
      */
     @Override
     public default int compareTo(final Traverser<T> other) throws ClassCastException {
-        return ((Comparable) this.get()).compareTo(other.get());
+        final Object thisObj = this.get();
+        final Object otherObj = other.get();
+        if (thisObj == otherObj) return 0;
+        if (null == thisObj) return -1;
+        if (null == otherObj) return 1;
+        return ((Comparable) thisObj).compareTo(otherObj);
     }
 
     /**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 482a9ac..56e3d33 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -124,7 +124,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
@@ -135,12 +135,13 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectCapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StoreStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
@@ -154,7 +155,6 @@
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.util.ArrayList;
@@ -550,7 +550,7 @@
      */
     public default <E2> GraphTraversal<S, Map<String, E2>> propertyMap(final String... propertyKeys) {
         this.asAdmin().getBytecode().addStep(Symbols.propertyMap, propertyKeys);
-        return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), false, PropertyType.PROPERTY, propertyKeys));
+        return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), WithOptions.none, PropertyType.PROPERTY, propertyKeys));
     }
 
     /**
@@ -584,7 +584,7 @@
      */
     public default <E2> GraphTraversal<S, Map<Object, E2>> valueMap(final String... propertyKeys) {
         this.asAdmin().getBytecode().addStep(Symbols.valueMap, propertyKeys);
-        return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), false, PropertyType.VALUE, propertyKeys));
+        return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), WithOptions.none, PropertyType.VALUE, propertyKeys));
     }
 
     /**
@@ -603,7 +603,7 @@
     @Deprecated
     public default <E2> GraphTraversal<S, Map<Object, E2>> valueMap(final boolean includeTokens, final String... propertyKeys) {
         this.asAdmin().getBytecode().addStep(Symbols.valueMap, includeTokens, propertyKeys);
-        return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), includeTokens, PropertyType.VALUE, propertyKeys));
+        return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), WithOptions.all, PropertyType.VALUE, propertyKeys));
     }
 
     /**
@@ -1046,7 +1046,7 @@
      */
     public default GraphTraversal<S, Vertex> addV(final Traversal<?, String> vertexLabelTraversal) {
         this.asAdmin().getBytecode().addStep(Symbols.addV, vertexLabelTraversal);
-        return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabelTraversal.asAdmin()));
+        return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), null == vertexLabelTraversal ? null : vertexLabelTraversal.asAdmin()));
     }
 
     /**
@@ -1083,7 +1083,7 @@
      */
     public default GraphTraversal<S, Edge> addE(final Traversal<?, String> edgeLabelTraversal) {
         this.asAdmin().getBytecode().addStep(Symbols.addE, edgeLabelTraversal);
-        return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabelTraversal.asAdmin()));
+        return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), null == edgeLabelTraversal ? null : edgeLabelTraversal.asAdmin()));
     }
 
     /**
@@ -2007,13 +2007,13 @@
      * with a {@link Scope#local}.
      *
      * @param sideEffectKey the name of the side-effect key that will hold the aggregated objects
-     * @return the traversal with an appended {@link AggregateStep}
+     * @return the traversal with an appended {@link AggregateGlobalStep}
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#aggregate-step" target="_blank">Reference Documentation - Aggregate Step</a>
      * @since 3.0.0-incubating
      */
     public default GraphTraversal<S, E> aggregate(final String sideEffectKey) {
         this.asAdmin().getBytecode().addStep(Symbols.aggregate, sideEffectKey);
-        return this.asAdmin().addStep(new AggregateStep<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new AggregateGlobalStep<>(this.asAdmin(), sideEffectKey));
     }
 
     /**
@@ -2021,14 +2021,14 @@
      * {@link Scope#local} or eager ({@link Scope#global} while gathering those objects.
      *
      * @param sideEffectKey the name of the side-effect key that will hold the aggregated objects
-     * @return the traversal with an appended {@link AggregateStep}
+     * @return the traversal with an appended {@link AggregateGlobalStep}
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#aggregate-step" target="_blank">Reference Documentation - Aggregate Step</a>
      * @since 3.4.3
      */
     public default GraphTraversal<S, E> aggregate(final Scope scope, final String sideEffectKey) {
         this.asAdmin().getBytecode().addStep(Symbols.aggregate, scope, sideEffectKey);
         return this.asAdmin().addStep(scope == Scope.global ?
-                new AggregateStep<>(this.asAdmin(), sideEffectKey) : new StoreStep<>(this.asAdmin(), sideEffectKey));
+                new AggregateGlobalStep<>(this.asAdmin(), sideEffectKey) : new AggregateLocalStep<>(this.asAdmin(), sideEffectKey));
     }
 
     /**
@@ -2089,14 +2089,14 @@
      * Lazily aggregates objects in the stream into a side-effect collection.
      *
      * @param sideEffectKey the name of the side-effect key that will hold the aggregate
-     * @return the traversal with an appended {@link StoreStep}
+     * @return the traversal with an appended {@link AggregateLocalStep}
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#store-step" target="_blank">Reference Documentation - Store Step</a>
      * @since 3.0.0-incubating
      * @deprecated As of release 3.4.3, replaced by {@link #aggregate(Scope, String)} using {@link Scope#local}.
      */
     public default GraphTraversal<S, E> store(final String sideEffectKey) {
         this.asAdmin().getBytecode().addStep(Symbols.store, sideEffectKey);
-        return this.asAdmin().addStep(new StoreStep<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new AggregateLocalStep<>(this.asAdmin(), sideEffectKey));
     }
 
     /**
@@ -2202,8 +2202,7 @@
      * {@link VertexProperty.Cardinality} is defaulted to {@code null} which  means that the default cardinality for
      * the {@link Graph} will be used.
      * <p/>
-     * This method is effectively calls
-     * {@link #property(org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality, Object, Object, Object...)}
+     * This method is effectively calls {@link #property(VertexProperty.Cardinality, Object, Object, Object...)}
      * as {@code property(null, key, value, keyValues}.
      *
      * @param key       the key for the property
@@ -2215,8 +2214,8 @@
      */
     public default GraphTraversal<S, E> property(final Object key, final Object value, final Object... keyValues) {
         return key instanceof VertexProperty.Cardinality ?
-                this.property((VertexProperty.Cardinality) key, value, keyValues[0],
-                        keyValues.length > 1 ?
+                this.property((VertexProperty.Cardinality) key, value, null == keyValues ? null : keyValues[0],
+                        keyValues != null && keyValues.length > 1 ?
                                 Arrays.copyOfRange(keyValues, 1, keyValues.length) :
                                 new Object[]{}) :
                 this.property(null, key, value, keyValues);
@@ -2645,13 +2644,13 @@
      * Indexes all items of the current collection. The indexing format can be configured using the {@link GraphTraversal#with(String, Object)}
      * and {@link org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions#indexer}.
      *
-     * Indexed as list: ["a","b","c"] => [["a",0],["b",1],["c",2]]
-     * Indexed as map:  ["a","b","c"] => {0:"a",1:"b",2:"c"}
+     * Indexed as list: ["a","b","c"] =&gt; [["a",0],["b",1],["c",2]]
+     * Indexed as map:  ["a","b","c"] =&gt; {0:"a",1:"b",2:"c"}
      *
      * If the current object is not a collection, this step will map the object to a single item collection/map:
      *
-     * Indexed as list: "a" => ["a",0]
-     * Indexed as map:  "a" => {0:"a"}
+     * Indexed as list: "a" =&gt; ["a",0]
+     * Indexed as map:  "a" =&gt; {0:"a"}
      *
      * @return the traversal with an appended {@link IndexStep}
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#index-step" target="_blank">Reference Documentation - Index Step</a>
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index f5c5c09..011bae7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -18,12 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.dsl.graph;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.strategy.decoration.RemoteStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -295,54 +293,12 @@
         return clone;
     }
 
-    /**
-     * {@inheritDoc}
-     *
-     * @deprecated As of release 3.3.5, replaced by {@link AnonymousTraversalSource#withRemote(Configuration)}.
-     * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-2078">TINKERPOP-2078</a>
-     */
-    @Override
-    @Deprecated
-    public GraphTraversalSource withRemote(final Configuration conf) {
-        return (GraphTraversalSource) TraversalSource.super.withRemote(conf);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @deprecated As of release 3.3.5, replaced by {@link AnonymousTraversalSource#withRemote(String)}.
-     * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-2078">TINKERPOP-2078</a>
-     */
-    @Override
-    @Deprecated
-    public GraphTraversalSource withRemote(final String configFile) throws Exception {
-        return (GraphTraversalSource) TraversalSource.super.withRemote(configFile);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @deprecated As of release 3.3.5, replaced by {@link AnonymousTraversalSource#withRemote(RemoteConnection)}.
-     * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-2078">TINKERPOP-2078</a>
-     */
-    @Override
-    @Deprecated
-    public GraphTraversalSource withRemote(final RemoteConnection connection) {
-        // check if someone called withRemote() more than once, so just release resources on the initial
-        // connection as you can't have more than one. maybe better to toss IllegalStateException??
-        if (this.connection != null)
-            throw new IllegalStateException(String.format("TraversalSource already configured with a RemoteConnection [%s]", connection));
-        final GraphTraversalSource clone = this.clone();
-        clone.connection = connection;
-        clone.getStrategies().addStrategies(new RemoteStrategy(connection));
-        return clone;
-    }
-
     //// SPAWNS
 
 
     /**
-     * Spawns a {@link GraphTraversal} by adding a vertex with the specified label.
+     * Spawns a {@link GraphTraversal} by adding a vertex with the specified label. If the {@code label} is
+     * {@code null} then it will default to {@link Vertex#DEFAULT_LABEL}.
      */
     public GraphTraversal<Vertex, Vertex> addV(final String label) {
         final GraphTraversalSource clone = this.clone();
@@ -352,7 +308,8 @@
     }
 
     /**
-     * Spawns a {@link GraphTraversal} by adding a vertex with the label as determined by a {@link Traversal}.
+     * Spawns a {@link GraphTraversal} by adding a vertex with the label as determined by a {@link Traversal}. If the
+     * {@code vertexLabelTraversal} is {@code null} then it will default to {@link Vertex#DEFAULT_LABEL}.
      */
     public GraphTraversal<Vertex, Vertex> addV(final Traversal<?, String> vertexLabelTraversal) {
         final GraphTraversalSource clone = this.clone();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ElementValueTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ElementValueTraversal.java
deleted file mode 100644
index 73f73a6..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ElementValueTraversal.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.lambda;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.Element;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * More efficiently extracts a value from an {@link Element} or {@code Map} to avoid strategy application costs. Note
- * that as of 3.4.5 this class is now poorly named as it was originally designed to work with {@link Element} only.
- * In future 3.5.0 this class will likely be renamed but to ensure that we get this revised functionality for
- * {@code Map} without introducing a breaking change this name will remain the same.
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class ElementValueTraversal<V> extends AbstractLambdaTraversal<Element, V> {
-
-    private final String propertyKey;
-    private V value;
-
-    public ElementValueTraversal(final String propertyKey) {
-        this.propertyKey = propertyKey;
-    }
-
-    @Override
-    public V next() {
-        return this.value;
-    }
-
-    @Override
-    public boolean hasNext() {
-        return true;
-    }
-
-    @Override
-    public void addStart(final Traverser.Admin<Element> start) {
-        if (null == this.bypassTraversal) {
-            // playing a game of type erasure here.....technically we can process either Map or Element here in this
-            // case after 3.4.5. and obviously users get weird errors along those lines here anyway. will fix up the
-            // generics in 3.5.0 when we can take some breaking changes. seemed like this feature would make Gremlin
-            // a lot nicer and given the small footprint of the change this seemed like a good hack to take.
-            final Object o = start.get();
-            if (o instanceof Element)
-                this.value = ((Element) o).value(propertyKey);
-            else if (o instanceof Map)
-                this.value = (V) ((Map) o).get(propertyKey);
-            else
-                throw new IllegalStateException(String.format(
-                        "The by(\"%s\") modulator can only be applied to a traverser that is an Element or a Map - it is being applied to [%s] a %s class instead",
-                        propertyKey, o, o.getClass().getSimpleName()));
-        } else {
-            this.value = TraversalUtil.apply(start, this.bypassTraversal);
-        }
-    }
-
-    public String getPropertyKey() {
-        return this.propertyKey;
-    }
-
-    @Override
-    public String toString() {
-        return "value(" + (null == this.bypassTraversal ? this.propertyKey : this.bypassTraversal) + ')';
-    }
-
-    @Override
-    public int hashCode() {
-        return super.hashCode() ^ this.propertyKey.hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object other) {
-        return other instanceof ElementValueTraversal
-                && Objects.equals(((ElementValueTraversal) other).propertyKey, this.propertyKey);
-    }
-}
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversal.java
index d41c402..e272ccf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversal.java
@@ -20,6 +20,7 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.T;
 
 import java.util.Objects;
@@ -27,7 +28,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class TokenTraversal<S extends Element, E> extends AbstractLambdaTraversal<S, E> {
+public final class TokenTraversal<S, E> extends AbstractLambdaTraversal<S, E> {
 
     private E e;
     private final T t;
@@ -43,7 +44,21 @@
 
     @Override
     public void addStart(final Traverser.Admin<S> start) {
-        this.e = (E) this.t.apply(start.get());
+        final S s = start.get();
+        if (s instanceof Element)
+            this.e = (E) this.t.apply((Element) start.get());
+        else if (s instanceof Property) {
+            // T.apply() doesn't work on Property because the inheritance hierarchy doesn't make it an Element. have
+            // to special case it here. only T.key/value make any sense for it.
+            if (t == T.key)
+                this.e = (E) ((Property) s).key();
+            else if (t == T.value)
+                this.e = ((Property<E>) s).value();
+            else
+                throw new IllegalStateException(String.format("TokenTraversal support of Property does not allow selection by %s", t));
+        } else
+            throw new IllegalStateException(String.format("TokenTraversal support of %s does not allow selection by %s", s.getClass().getName(), t));
+
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ValueTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ValueTraversal.java
new file mode 100644
index 0000000..fa5d90d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ValueTraversal.java
@@ -0,0 +1,91 @@
+/*
+ * 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.lambda;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyProperty;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * More efficiently extracts a value from an {@link Element} or {@code Map} to avoid strategy application costs.
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class ValueTraversal<T, V> extends AbstractLambdaTraversal<T, V> {
+
+    private final String propertyKey;
+    private V value;
+
+    public ValueTraversal(final String propertyKey) {
+        this.propertyKey = propertyKey;
+    }
+
+    @Override
+    public V next() {
+        return this.value;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return true;
+    }
+
+    @Override
+    public void addStart(final Traverser.Admin<T> start) {
+        if (null == this.bypassTraversal) {
+            final T o = start.get();
+            if (o instanceof Element)
+                this.value = (V)((Element) o).property(propertyKey).orElse(null);
+            else if (o instanceof Map)
+                this.value = (V) ((Map) o).get(propertyKey);
+            else
+                throw new IllegalStateException(String.format(
+                        "The by(\"%s\") modulator can only be applied to a traverser that is an Element or a Map - it is being applied to [%s] a %s class instead",
+                        propertyKey, o, o.getClass().getSimpleName()));
+        } else {
+            this.value = TraversalUtil.apply(start, this.bypassTraversal);
+        }
+    }
+
+    public String getPropertyKey() {
+        return this.propertyKey;
+    }
+
+    @Override
+    public String toString() {
+        return "value(" + (null == this.bypassTraversal ? this.propertyKey : this.bypassTraversal) + ')';
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() ^ this.propertyKey.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        return other instanceof ValueTraversal
+                && Objects.equals(((ValueTraversal) other).propertyKey, this.propertyKey);
+    }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ByModulating.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ByModulating.java
index 01841fa..b808bf6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ByModulating.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ByModulating.java
@@ -23,7 +23,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.ColumnTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
@@ -47,7 +47,7 @@
     }
 
     public default void modulateBy(final String string) throws UnsupportedOperationException {
-        this.modulateBy(new ElementValueTraversal(string));
+        this.modulateBy(new ValueTraversal(string));
     }
 
     public default void modulateBy(final T token) throws UnsupportedOperationException {
@@ -74,7 +74,7 @@
     }
 
     public default void modulateBy(final String key, final Comparator comparator) {
-        this.modulateBy(new ElementValueTraversal<>(key), comparator);
+        this.modulateBy(new ValueTraversal<>(key), comparator);
     }
 
     public default void modulateBy(final Comparator comparator) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Grouping.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Grouping.java
new file mode 100644
index 0000000..1e15758
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Grouping.java
@@ -0,0 +1,100 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ColumnTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An interface for common functionality of {@link GroupStep} and {@link GroupSideEffectStep}.
+ */
+public interface Grouping<S, K, V> {
+
+    /**
+     * Determines if the provided traversal is equal to the key traversal that the {@code Grouping} has.
+     */
+    public Traversal.Admin<S, K> getKeyTraversal();
+
+    /**
+     * Determines if the provided traversal is equal to the value traversal that the {@code Grouping} has.
+     */
+    public Traversal.Admin<S, V> getValueTraversal();
+
+    /**
+     * Determines the first (non-local) barrier step in the provided traversal. This method is used by {@link GroupStep}
+     * and {@link GroupSideEffectStep} to ultimately determine the reducing bi-operator.
+     *
+     * @param traversal The traversal to inspect.
+     * @return The first non-local barrier step or {@code null} if no such step was found.
+     */
+    public default Barrier determineBarrierStep(final Traversal.Admin<S, V> traversal) {
+        final List<Step> steps = traversal.getSteps();
+        for (int ix = 0; ix < steps.size(); ix++) {
+            final Step step = steps.get(ix);
+            if (step instanceof Barrier && !(step instanceof LocalBarrier)) {
+                final Barrier b = (Barrier) step;
+
+                // when profile() is enabled the step needs to be wrapped up with the barrier so that the timer on
+                // the ProfileStep is properly triggered
+                if (ix < steps.size() - 1 && steps.get(ix + 1) instanceof ProfileStep)
+                    return new ProfilingAware.ProfiledBarrier(b, (ProfileStep) steps.get(ix + 1));
+                else
+                    return b;
+            }
+        }
+        return null;
+    }
+
+    public default Traversal.Admin<S, V> convertValueTraversal(final Traversal.Admin<S, V> valueTraversal) {
+        if (valueTraversal instanceof ValueTraversal ||
+                valueTraversal instanceof TokenTraversal ||
+                valueTraversal instanceof IdentityTraversal ||
+                valueTraversal instanceof ColumnTraversal ||
+                valueTraversal.getStartStep() instanceof LambdaMapStep && ((LambdaMapStep) valueTraversal.getStartStep()).getMapFunction() instanceof FunctionTraverser) {
+            return (Traversal.Admin<S, V>) __.map(valueTraversal).fold();
+        } else
+            return valueTraversal;
+    }
+
+    public default Map<K, V> doFinalReduction(final Map<K, Object> map, final Traversal.Admin<S, V> valueTraversal) {
+        final Barrier barrierStep = determineBarrierStep(valueTraversal);
+        if (barrierStep != null) {
+            for (final K key : map.keySet()) {
+                valueTraversal.reset();
+                barrierStep.addBarrier(map.get(key));
+                if (valueTraversal.hasNext())
+                    map.put(key, valueTraversal.next());
+            }
+        }
+        return (Map<K, V>) map;
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
index 8a5843a..f0b7e20 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
@@ -20,7 +20,7 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -49,7 +49,7 @@
                 } else if (traversal instanceof TokenTraversal && ((TokenTraversal) traversal).getToken().equals(T.label)) {
                     if (max.compareTo(ElementRequirement.LABEL) < 0)
                         max = ElementRequirement.LABEL;
-                } else if (traversal instanceof ElementValueTraversal) {
+                } else if (traversal instanceof ValueTraversal) {
                     if (max.compareTo(ElementRequirement.PROPERTIES) < 0)
                         max = ElementRequirement.PROPERTIES;
                 } else {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
index 36e7493..e2c0e17 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
@@ -109,26 +109,54 @@
 
     public enum Variable {START, END}
 
-    public default <S> S getScopeValue(final Pop pop, final String key, final Traverser.Admin<?> traverser) throws IllegalArgumentException {
-        final S o = getNullableScopeValue(pop, key, traverser);
-        if (null == o)
-            throw new IllegalArgumentException("Neither the sideEffects, map, nor path has a " + key + "-key: " + this);
-        return o;
+    /**
+     * Finds the object with the specified key for the current traverser and throws an exception if the key cannot
+     * be found.
+     *
+     * @throws KeyNotFoundException if the key does not exist
+     */
+    public default <S> S getScopeValue(final Pop pop, final Object key, final Traverser.Admin<?> traverser) throws KeyNotFoundException {
+        final Object object = traverser.get();
+        if (object instanceof Map && ((Map) object).containsKey(key))
+            return (S) ((Map) object).get(key);
+
+        if (key instanceof String) {
+            final String k = (String) key;
+            if (traverser.getSideEffects().exists(k))
+                return traverser.getSideEffects().get(k);
+
+            final Path path = traverser.path();
+            if (path.hasLabel(k))
+                return null == pop ? path.get(k) : path.get(pop, k);
+        }
+
+        throw new KeyNotFoundException(key, this);
     }
 
+    /**
+     * Calls {@link #getScopeValue(Pop, Object, Traverser.Admin)} but throws an unchecked {@code IllegalStateException}
+     * if the key cannot be found.
+     */
+    public default <S> S getSafeScopeValue(final Pop pop, final Object key, final Traverser.Admin<?> traverser) {
+        try {
+            return getScopeValue(pop, key, traverser);
+        } catch (KeyNotFoundException nfe) {
+            throw new IllegalArgumentException(nfe.getMessage(), nfe);
+        }
+    }
+
+    /**
+     * Calls {@link #getScopeValue(Pop, Object, Traverser.Admin)} and returns {@code null} if the key is not found.
+     * Use this method with caution as {@code null} has one of two meanings as a return value. It could be that the
+     * key was found and its value was {@code null} or it might mean that the key was not found and {@code null} was
+     * simply returned.
+     */
     public default <S> S getNullableScopeValue(final Pop pop, final String key, final Traverser.Admin<?> traverser) {
-        final Object object = traverser.get();
-        if (object instanceof Map && ((Map<String, S>) object).containsKey(key))
-            return ((Map<String, S>) object).get(key);
-
-        if (traverser.getSideEffects().exists(key))
-            return traverser.getSideEffects().get(key);
-
-        final Path path = traverser.path();
-        if (path.hasLabel(key))
-            return path.get(pop, key);
-
-        return null;
+        try {
+            return getScopeValue(pop, key, traverser);
+        } catch (KeyNotFoundException nfe) {
+            return null;
+        }
     }
 
     /**
@@ -137,4 +165,24 @@
      * @return the accessed labels of the scoping step
      */
     public Set<String> getScopeKeys();
+
+    public static class KeyNotFoundException extends Exception {
+
+        private final Object key;
+        private final Scoping step;
+
+        public KeyNotFoundException(final Object key, final Scoping current) {
+            super("Neither the map, sideEffects, nor path has a " + key + "-key: " + current);
+            this.key = key;
+            this.step = current;
+        }
+
+        public Object getKey() {
+            return key;
+        }
+
+        public Scoping getStep() {
+            return step;
+        }
+    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Seedable.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Seedable.java
new file mode 100644
index 0000000..29d1cb5
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Seedable.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy;
+
+/**
+ * An interface implemented by steps that have some form of {@code Random} usage that can be configured by way of a
+ * {@code seed} to allow for deterministic behavior of the step.
+ *
+ * @see SeedStrategy
+ */
+public interface Seedable {
+
+    public void resetSeed(final long seed);
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
index 10df950..695d297 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
@@ -20,7 +20,6 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 
 import java.util.Collections;
@@ -57,6 +56,10 @@
         throw new IllegalStateException("This traversal parent does not support the removal of global traversals: " + this.getClass().getCanonicalName());
     }
 
+    public default void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        throw new IllegalStateException("This traversal parent does not support the replacement of local traversals: " + this.getClass().getCanonicalName());
+    }
+
     public default Set<TraverserRequirement> getSelfAndChildRequirements(final TraverserRequirement... selfRequirements) {
         final Set<TraverserRequirement> requirements = EnumSet.noneOf(TraverserRequirement.class);
         Collections.addAll(requirements, selfRequirements);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
index db2480d..a7d86cb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
@@ -20,6 +20,7 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
@@ -30,9 +31,9 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class CoinStep<S> extends FilterStep<S> {
+public final class CoinStep<S> extends FilterStep<S> implements Seedable {
 
-    private static final Random RANDOM = new Random();
+    private final Random random = new Random();
     private final double probability;
 
     public CoinStep(final Traversal.Admin traversal, final double probability) {
@@ -41,19 +42,18 @@
     }
 
     @Override
+    public void resetSeed(final long seed) {
+        random.setSeed(seed);
+    }
+
+    @Override
     protected boolean filter(final Traverser.Admin<S> traverser) {
         long newBulk = 0l;
         if (traverser.bulk() < 100) {
             for (int i = 0; i < traverser.bulk(); i++) {
-                if (this.probability >= RANDOM.nextDouble())
+                if (this.probability >= random.nextDouble())
                     newBulk++;
             }
-        /*} else if (traverser.bulk() < 1000000) {
-            final double cumulative = RANDOM.nextDouble();
-            final long current = Double.valueOf(traverser.bulk() / 2.0d).longValue();
-            final double next = choose(traverser.bulk(), current) * Math.pow(this.probability,current) * Math.pow(1.0d - this.probability,traverser.bulk() - current);
-            if()
-            */
         } else {
             newBulk = Math.round(this.probability * traverser.bulk());
         }
@@ -76,22 +76,4 @@
     public Set<TraverserRequirement> getRequirements() {
         return Collections.singleton(TraverserRequirement.BULK);
     }
-
-    //////
-
-    private static double choose(long x, long y) {
-        if (y < 0 || y > x) return 0;
-        if (y > x / 2) {
-            // choose(n,k) == choose(n,n-k),
-            // so this could save a little effort
-            y = x - y;
-        }
-
-        double denominator = 1.0, numerator = 1.0;
-        for (long i = 1; i <= y; i++) {
-            denominator *= i;
-            numerator *= (x + 1 - i);
-        }
-        return numerator / denominator;
-    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
index b4f70d9..bbde296 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
@@ -32,8 +32,10 @@
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory;
+import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -74,7 +76,7 @@
             return this.duplicateSet.add(TraversalUtil.applyNullable(traverser, this.dedupTraversal));
         } else {
             final List<Object> objects = new ArrayList<>(this.dedupLabels.size());
-            this.dedupLabels.forEach(label -> objects.add(TraversalUtil.applyNullable((S) this.getScopeValue(Pop.last, label, traverser), this.dedupTraversal)));
+            this.dedupLabels.forEach(label -> objects.add(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal)));
             return this.duplicateSet.add(objects);
         }
     }
@@ -116,6 +118,12 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.dedupTraversal && this.dedupTraversal.equals(oldTraversal))
+            this.dedupTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
     public DedupGlobalStep<S> clone() {
         final DedupGlobalStep<S> clone = (DedupGlobalStep<S>) super.clone();
         clone.duplicateSet = new HashSet<>();
@@ -189,15 +197,26 @@
             if (null != this.dedupLabels) {
                 object = new ArrayList<>(this.dedupLabels.size());
                 for (final String label : this.dedupLabels) {
-                    ((List) object).add(TraversalUtil.applyNullable((S) this.getScopeValue(Pop.last, label, traverser), this.dedupTraversal));
+                    ((List) object).add(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal));
                 }
             } else {
                 object = TraversalUtil.applyNullable(traverser, this.dedupTraversal);
             }
             if (!map.containsKey(object)) {
                 traverser.setBulk(1L);
-                // traverser.detach();
-                traverser.set(DetachedFactory.detach(traverser.get(), true)); // TODO: detect required detachment accordingly
+
+                // DetachedProperty and DetachedVertexProperty both have a transient for the Host element. that causes
+                // trouble for olap which ends up requiring the Host later. can't change the transient without some
+                // consequences: (1) we break gryo formatting and io tests start failing (2) storing the element with
+                // the property has the potential to bloat detached Element instances as it basically stores that data
+                // twice. Not sure if it's smart to change that at least in 3.4.x and not without some considerable
+                // thought as to what might be major changes. To work around the problem we will detach properties as
+                // references so that the parent element goes with it. Also, given TINKERPOP-2318 property comparisons
+                // have changed in such a way that allows this to work properly
+                if (traverser.get() instanceof Property)
+                    traverser.set(ReferenceFactory.detach(traverser.get()));
+                else
+                    traverser.set(DetachedFactory.detach(traverser.get(), true));
                 map.put(object, traverser);
             }
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
index 16e3f0f..6b77a36 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
@@ -109,6 +109,13 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin<Object, Object>) oldTraversal,
+                (Traversal.Admin<Object, Object>) newTraversal);
+    }
+
+    @Override
     public void reset() {
         super.reset();
         this.traversalRing.reset();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
index e4ca430..b342100 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -22,6 +22,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
@@ -38,11 +39,11 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implements TraversalParent, ByModulating {
+public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implements TraversalParent, ByModulating, Seedable {
 
     private Traversal.Admin<S, Number> probabilityTraversal = new ConstantTraversal<>(1.0d);
     private final int amountToSample;
-    private static final Random RANDOM = new Random();
+    private final Random random = new Random();
 
     public SampleGlobalStep(final Traversal.Admin traversal, final int amountToSample) {
         super(traversal);
@@ -50,6 +51,11 @@
     }
 
     @Override
+    public void resetSeed(final long seed) {
+        random.setSeed(seed);
+    }
+
+    @Override
     public List<Traversal.Admin<S, Number>> getLocalChildren() {
         return Collections.singletonList(this.probabilityTraversal);
     }
@@ -60,6 +66,12 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.probabilityTraversal && this.probabilityTraversal.equals(oldTraversal))
+            this.probabilityTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
     public String toString() {
         return StringFactory.stepString(this, this.amountToSample, this.probabilityTraversal);
     }
@@ -92,7 +104,7 @@
                 if (sampleBulk < s.bulk()) {
                     final double currentWeight = ((ProjectedTraverser<S, Number>) s).getProjections().get(0).doubleValue();
                     for (int i = 0; i < (s.bulk() - sampleBulk); i++) {
-                        if (RANDOM.nextDouble() <= ((currentWeight / runningTotalWeight))) {
+                        if (random.nextDouble() <= ((currentWeight / runningTotalWeight))) {
                             final Traverser.Admin<S> split = s.split();
                             split.setBulk(1L);
                             sampledSet.add(split);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
index 240a4cc..306fb25 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
@@ -28,7 +28,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -79,7 +78,7 @@
         if (predicate instanceof ConnectiveP)
             ((ConnectiveP<Object>) predicate).getPredicates().forEach(p -> this.setPredicateValues(p, traverser, selectKeysIterator));
         else
-            predicate.setValue(TraversalUtil.applyNullable((S) this.getScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next()));
+            predicate.setValue(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next()));
     }
 
     public Optional<P<?>> getPredicate() {
@@ -99,7 +98,7 @@
     protected boolean filter(final Traverser.Admin<S> traverser) {
         final Object value = null == this.startKey ?
                 TraversalUtil.applyNullable(traverser, this.traversalRing.next()) :
-                TraversalUtil.applyNullable((S) this.getScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next());
+                TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next());
         this.setPredicateValues(this.predicate, traverser, this.selectKeys.iterator());
         this.traversalRing.reset();
         return this.predicate.test(value);
@@ -164,4 +163,11 @@
     public void modulateBy(final Traversal.Admin<?, ?> traversal) throws UnsupportedOperationException {
         this.traversalRing.addTraversal(this.integrateChild(traversal));
     }
+
+    @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin) oldTraversal,
+                (Traversal.Admin) newTraversal);
+    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
index 384bbce..264575d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
@@ -25,7 +25,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ScalarMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
@@ -149,7 +149,7 @@
 
     //////////////////////////////
 
-    public static class WhereStartStep<S> extends MapStep<S, Object> implements Scoping {
+    public static class WhereStartStep<S> extends ScalarMapStep<S, Object> implements Scoping {
 
         private String selectKey;
 
@@ -164,7 +164,7 @@
                 ((WhereEndStep) this.getTraversal().getEndStep()).processStartTraverser(traverser);
             else if (this.getTraversal().getEndStep() instanceof ProfileStep && this.getTraversal().getEndStep().getPreviousStep() instanceof WhereEndStep)     // TOTAL SUCKY HACK!
                 ((WhereEndStep) this.getTraversal().getEndStep().getPreviousStep()).processStartTraverser(traverser);
-            return null == this.selectKey ? traverser.get() : this.getScopeValue(Pop.last, this.selectKey, traverser);
+            return null == this.selectKey ? traverser.get() : this.getSafeScopeValue(Pop.last, this.selectKey, traverser);
         }
 
         @Override
@@ -199,7 +199,7 @@
 
         public void processStartTraverser(final Traverser.Admin traverser) {
             if (null != this.matchKey)
-                this.matchValue = this.getScopeValue(Pop.last, this.matchKey, traverser);
+                this.matchValue = this.getSafeScopeValue(Pop.last, this.matchKey, traverser);
         }
 
         @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
index 55d0866..14faa2c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
@@ -45,7 +45,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
-public class AddEdgeStep<S> extends MapStep<S, Edge>
+public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
         implements Mutating<Event.EdgeAddedEvent>, TraversalParent, Scoping, FromToModulating {
 
     private static final String FROM = Graph.Hidden.hide("from");
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
index 2182921..54ce962 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
@@ -53,12 +53,12 @@
 
     public AddVertexStartStep(final Traversal.Admin traversal, final String label) {
         super(traversal);
-        this.parameters.set(this, T.label, label);
+        this.parameters.set(this, T.label, null == label ? Vertex.DEFAULT_LABEL : label);
     }
 
     public AddVertexStartStep(final Traversal.Admin traversal, final Traversal<?, String> vertexLabelTraversal) {
         super(traversal);
-        this.parameters.set(this, T.label, vertexLabelTraversal);
+        this.parameters.set(this, T.label, null == vertexLabelTraversal ? Vertex.DEFAULT_LABEL : vertexLabelTraversal);
     }
 
     @Override
@@ -78,7 +78,20 @@
 
     @Override
     public void configure(final Object... keyValues) {
-        this.parameters.set(this, keyValues);
+        if (keyValues[0] == T.label && this.parameters.contains(T.label)) {
+            if (this.parameters.contains(T.label, Vertex.DEFAULT_LABEL)) {
+                this.parameters.remove(T.label);
+                this.parameters.set(this, keyValues);
+            } else {
+                throw new IllegalArgumentException(String.format("Vertex T.label has already been set to [%s] and cannot be overridden with [%s]",
+                        this.parameters.getRaw().get(T.label).get(0), keyValues[1]));
+            }
+        } else if (keyValues[0] == T.id && this.parameters.contains(T.id)) {
+            throw new IllegalArgumentException(String.format("Vertex T.id has already been set to [%s] and cannot be overridden with [%s]",
+                    this.parameters.getRaw().get(T.id).get(0), keyValues[1]));
+        } else {
+            this.parameters.set(this, keyValues);
+        }
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
index a609422..343c44b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
@@ -40,7 +40,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
-public class AddVertexStep<S> extends MapStep<S, Vertex>
+public class AddVertexStep<S> extends ScalarMapStep<S, Vertex>
         implements Mutating<Event.VertexAddedEvent>, TraversalParent, Scoping {
 
     private Parameters parameters = new Parameters();
@@ -48,12 +48,12 @@
 
     public AddVertexStep(final Traversal.Admin traversal, final String label) {
         super(traversal);
-        this.parameters.set(this, T.label, label);
+        this.parameters.set(this, T.label, null == label ? Vertex.DEFAULT_LABEL : label);
     }
 
     public AddVertexStep(final Traversal.Admin traversal, final Traversal.Admin<S,String> vertexLabelTraversal) {
         super(traversal);
-        this.parameters.set(this, T.label, vertexLabelTraversal);
+        this.parameters.set(this, T.label, null == vertexLabelTraversal ? Vertex.DEFAULT_LABEL : vertexLabelTraversal);
     }
 
     @Override
@@ -73,7 +73,20 @@
 
     @Override
     public void configure(final Object... keyValues) {
-        this.parameters.set(this, keyValues);
+        if (keyValues[0] == T.label && this.parameters.contains(T.label)) {
+            if (this.parameters.contains(T.label, Vertex.DEFAULT_LABEL)) {
+                this.parameters.remove(T.label);
+                this.parameters.set(this, keyValues);
+            } else {
+                throw new IllegalArgumentException(String.format("Vertex T.label has already been set to [%s] and cannot be overridden with [%s]",
+                        this.parameters.getRaw().get(T.label).get(0), keyValues[1]));
+            }
+        } else if (keyValues[0] == T.id && this.parameters.contains(T.id)) {
+            throw new IllegalArgumentException(String.format("Vertex T.id has already been set to [%s] and cannot be overridden with [%s]",
+                    this.parameters.getRaw().get(T.id).get(0), keyValues[1]));
+        } else {
+            this.parameters.set(this, keyValues);
+        }
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
index 749de31..9434cc3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
@@ -27,7 +27,7 @@
 import java.util.Objects;
 import java.util.Set;
 
-public class ConstantStep<S, E> extends MapStep<S, E> {
+public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
 
     private final E constant;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java
index 87b699d..25e75e4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java
@@ -32,7 +32,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class CountLocalStep<S> extends MapStep<S, Long> {
+public final class CountLocalStep<S> extends ScalarMapStep<S, Long> {
 
     public CountLocalStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java
index 59c66c7..4d75270 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java
@@ -29,7 +29,7 @@
 /**
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class DedupLocalStep<E, S extends Iterable<E>> extends MapStep<S, Set<E>> {
+public final class DedupLocalStep<E, S extends Iterable<E>> extends ScalarMapStep<S, Set<E>> {
 
     public DedupLocalStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java
index a53dd50..0d151d0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java
@@ -34,7 +34,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class EdgeOtherVertexStep extends MapStep<Edge, Vertex> implements Configuring {
+public class EdgeOtherVertexStep extends ScalarMapStep<Edge, Vertex> implements Configuring {
     protected Parameters parameters = new Parameters();
 
     public EdgeOtherVertexStep(final Traversal.Admin traversal) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
index 2f1db43..1654aa1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
@@ -45,7 +45,7 @@
  * @author Daniel Kuppitz (http://gremlin.guru)
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
-public class ElementMapStep<K,E> extends MapStep<Element, Map<K, E>> implements TraversalParent, GraphComputing {
+public class ElementMapStep<K,E> extends ScalarMapStep<Element, Map<K, E>> implements TraversalParent, GraphComputing {
 
     protected final String[] propertyKeys;
     private boolean onGraphComputer = false;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
index a0c02fd..e679240 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
@@ -79,6 +79,12 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.keyTraversal && this.keyTraversal.equals(oldTraversal))
+            this.keyTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
     public GroupCountStep<S, E> clone() {
         final GroupCountStep<S, E> clone = (GroupCountStep<S, E>) super.clone();
         if (null != this.keyTraversal)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
index fb0bf3a..2213b2e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
@@ -20,21 +20,14 @@
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ColumnTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Grouping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ProfilingAware;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.LocalBarrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
@@ -53,7 +46,8 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>> implements ByModulating, TraversalParent, ProfilingAware {
+public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
+        implements ByModulating, TraversalParent, ProfilingAware, Grouping<S, K, V> {
 
     private char state = 'k';
     private Traversal.Admin<S, K> keyTraversal;
@@ -70,31 +64,6 @@
     }
 
     /**
-     * Determines the first (non-local) barrier step in the provided traversal. This method is used by {@link GroupStep}
-     * and {@link GroupSideEffectStep} to ultimately determine the reducing bi-operator.
-     *
-     * @param traversal The traversal to inspect.
-     * @return The first non-local barrier step or {@code null} if no such step was found.
-     */
-    public static <S, V> Barrier determineBarrierStep(final Traversal.Admin<S, V> traversal) {
-        final List<Step> steps = traversal.getSteps();
-        for (int ix = 0; ix < steps.size(); ix++) {
-            final Step step = steps.get(ix);
-            if (step instanceof Barrier && !(step instanceof LocalBarrier)) {
-                final Barrier b = (Barrier) step;
-
-                // when profile() is enabled the step needs to be wrapped up with the barrier so that the timer on
-                // the ProfileStep is properly triggered
-                if (ix < steps.size() - 1 && steps.get(ix + 1) instanceof ProfileStep)
-                    return new ProfilingAware.ProfiledBarrier(b, (ProfileStep) steps.get(ix + 1));
-                else
-                    return b;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Reset the {@link Barrier} on the step to be wrapped in a {@link ProfiledBarrier} which can properly start/stop
      * the timer on the associated {@link ProfileStep}.
      */
@@ -104,14 +73,28 @@
     }
 
     @Override
+    public Traversal.Admin<S, K> getKeyTraversal() {
+        return this.keyTraversal;
+    }
+
+    @Override
+    public Traversal.Admin<S, V> getValueTraversal() {
+        return this.valueTraversal;
+    }
+
+    private void setValueTraversal(final Traversal.Admin kvTraversal) {
+        this.valueTraversal = this.integrateChild(convertValueTraversal(kvTraversal));
+        this.barrierStep = determineBarrierStep(this.valueTraversal);
+        this.setReducingBiOperator(new GroupBiOperator<>(null == this.barrierStep ? Operator.assign : this.barrierStep.getMemoryComputeKey().getReducer()));
+    }
+
+    @Override
     public void modulateBy(final Traversal.Admin<?, ?> kvTraversal) {
         if ('k' == this.state) {
             this.keyTraversal = this.integrateChild(kvTraversal);
             this.state = 'v';
         } else if ('v' == this.state) {
-            this.valueTraversal = this.integrateChild(convertValueTraversal(kvTraversal));
-            this.barrierStep = determineBarrierStep(this.valueTraversal);
-            this.setReducingBiOperator(new GroupBiOperator<>(null == this.barrierStep ? Operator.assign : this.barrierStep.getMemoryComputeKey().getReducer()));
+            this.setValueTraversal(kvTraversal);
             this.state = 'x';
         } else {
             throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
@@ -119,6 +102,14 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.keyTraversal && this.keyTraversal.equals(oldTraversal))
+            this.keyTraversal = this.integrateChild(newTraversal);
+        else if (null != this.valueTraversal && this.valueTraversal.equals(oldTraversal))
+            this.setValueTraversal(newTraversal);
+    }
+
+    @Override
     public Map<K, V> projectTraverser(final Traverser.Admin<S> traverser) {
         final Map<K, V> map = new HashMap<>(1);
         this.valueTraversal.reset();
@@ -187,7 +178,7 @@
 
     @Override
     public Map<K, V> generateFinalResult(final Map<K, V> object) {
-        return GroupStep.doFinalReduction((Map<K, Object>) object, this.valueTraversal);
+        return doFinalReduction((Map<K, Object>) object, this.valueTraversal);
     }
 
     ///////////////////////
@@ -218,31 +209,4 @@
             return mapA;
         }
     }
-
-
-    ///////////////////////
-
-    public static <S, E> Traversal.Admin<S, E> convertValueTraversal(final Traversal.Admin<S, E> valueTraversal) {
-        if (valueTraversal instanceof ElementValueTraversal ||
-                valueTraversal instanceof TokenTraversal ||
-                valueTraversal instanceof IdentityTraversal ||
-                valueTraversal instanceof ColumnTraversal ||
-                valueTraversal.getStartStep() instanceof LambdaMapStep && ((LambdaMapStep) valueTraversal.getStartStep()).getMapFunction() instanceof FunctionTraverser) {
-            return (Traversal.Admin<S, E>) __.map(valueTraversal).fold();
-        } else
-            return valueTraversal;
-    }
-
-    public static <K, V> Map<K, V> doFinalReduction(final Map<K, Object> map, final Traversal.Admin<?, V> valueTraversal) {
-        final Barrier barrierStep = determineBarrierStep(valueTraversal);
-        if (barrierStep != null) {
-            for (final K key : map.keySet()) {
-                valueTraversal.reset();
-                barrierStep.addBarrier(map.get(key));
-                if (valueTraversal.hasNext())
-                    map.put(key, valueTraversal.next());
-            }
-        }
-        return (Map<K, V>) map;
-    }
 }
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IdStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IdStep.java
index 018c91e..c5eb7c4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IdStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IdStep.java
@@ -29,7 +29,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class IdStep<S extends Element> extends MapStep<S, Object> {
+public final class IdStep<S extends Element> extends ScalarMapStep<S, Object> {
 
     public IdStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java
index b903c15..314e751 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java
@@ -40,7 +40,7 @@
 /**
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public class IndexStep<S, E> extends MapStep<S, E> implements TraversalParent, Configuring {
+public class IndexStep<S, E> extends ScalarMapStep<S, E> implements TraversalParent, Configuring {
 
     private final static IllegalArgumentException INVALID_CONFIGURATION_EXCEPTION =
             new IllegalArgumentException("WithOptions.indexer requires a single Integer argument (possible " + "" +
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelStep.java
index 2b2313f..060dc68 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelStep.java
@@ -29,7 +29,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class LabelStep<S extends Element> extends MapStep<S, String> {
+public final class LabelStep<S extends Element> extends ScalarMapStep<S, String> {
 
     public LabelStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LambdaMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LambdaMapStep.java
index b2024f8..ce6a1bd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LambdaMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LambdaMapStep.java
@@ -28,7 +28,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class LambdaMapStep<S, E> extends MapStep<S, E> implements LambdaHolder {
+public final class LambdaMapStep<S, E> extends ScalarMapStep<S, E> implements LambdaHolder {
 
     private final Function<Traverser<S>, E> function;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
index 11d8729..c3d2ac8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
@@ -24,7 +24,7 @@
 /**
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class LoopsStep<S> extends MapStep<S, Integer> {
+public final class LoopsStep<S> extends ScalarMapStep<S, Integer> {
 
     private String loopName;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapStep.java
index 03e544e..5d5103c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapStep.java
@@ -18,26 +18,23 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 
 /**
+ * A marker base class that designates an extending {@link Step} as a "Map" step which will transform the object of one
+ * {@link Traverser} into another. In many cases, it may be easier to simply extend from {@link ScalarMapStep} which
+ * has a straightforward implementation pattern.
+ *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public abstract class MapStep<S, E> extends AbstractStep<S, E> {
 
     public MapStep(final Traversal.Admin traversal) {
         super(traversal);
     }
-
-    @Override
-    protected Traverser.Admin<E> processNextStart() {
-        final Traverser.Admin<S> traverser = this.starts.next();
-        return traverser.split(this.map(traverser), this);
-    }
-
-    protected abstract E map(final Traverser.Admin<S> traverser);
-
 }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
index 7a483a1..149f67a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
@@ -45,7 +45,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class MathStep<S> extends MapStep<S, Double> implements ByModulating, TraversalParent, Scoping, PathProcessor {
+public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByModulating, TraversalParent, Scoping, PathProcessor {
 
     private static final String CURRENT = "_";
     private final String equation;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxLocalStep.java
index 3ad326f..187ad39 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxLocalStep.java
@@ -33,7 +33,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class MaxLocalStep<E extends Comparable, S extends Iterable<E>> extends MapStep<S, E> {
+public final class MaxLocalStep<E extends Comparable, S extends Iterable<E>> extends ScalarMapStep<S, E> {
 
     public MaxLocalStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanLocalStep.java
index 91447fd..5ffb1a6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanLocalStep.java
@@ -32,7 +32,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class MeanLocalStep<E extends Number, S extends Iterable<E>> extends MapStep<S, Number> {
+public final class MeanLocalStep<E extends Number, S extends Iterable<E>> extends ScalarMapStep<S, Number> {
 
     public MeanLocalStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinLocalStep.java
index 4139a7d..3bdb969 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinLocalStep.java
@@ -33,7 +33,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class MinLocalStep<E extends Comparable, S extends Iterable<E>> extends MapStep<S, E> {
+public final class MinLocalStep<E extends Comparable, S extends Iterable<E>> extends ScalarMapStep<S, E> {
 
     public MinLocalStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index cc7cec6..a7f7892 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -25,6 +25,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
@@ -41,6 +42,7 @@
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Random;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 import java.util.stream.Collectors;
@@ -48,22 +50,28 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBarrierStep<S> implements ComparatorHolder<S, C>, TraversalParent, ByModulating {
+public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBarrierStep<S> implements ComparatorHolder<S, C>, TraversalParent, ByModulating, Seedable {
 
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
     private MultiComparator<C> multiComparator = null;
     private long limit = Long.MAX_VALUE;
+    private final Random random = new Random();
 
     public OrderGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
     }
 
     @Override
+    public void resetSeed(long seed) {
+        this.random.setSeed(seed);
+    }
+
+    @Override
     public void barrierConsumer(final TraverserSet<S> traverserSet) {
         if (null == this.multiComparator) this.multiComparator = this.createMultiComparator();
         //
         if (this.multiComparator.isShuffle())
-            traverserSet.shuffle();
+            traverserSet.shuffle(random);
         else
             traverserSet.sort((Comparator) this.multiComparator);
     }
@@ -99,6 +107,19 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        int i = 0;
+        for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
+            final Traversal.Admin<S, C> traversal = pair.getValue0();
+            if (null != traversal && traversal.equals(oldTraversal)) {
+                this.comparators.set(i, Pair.with(this.integrateChild(newTraversal), pair.getValue1()));
+                break;
+            }
+            i++;
+        }
+    }
+
+    @Override
     public List<Pair<Traversal.Admin<S, C>, Comparator<C>>> getComparators() {
         return this.comparators.isEmpty() ? Collections.singletonList(new Pair<>(new IdentityTraversal(), (Comparator) Order.asc)) : Collections.unmodifiableList(this.comparators);
     }
@@ -146,15 +167,19 @@
     @Override
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
         if (null == this.multiComparator) this.multiComparator = this.createMultiComparator();
-        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.multiComparator), false, true);
+        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.multiComparator, this.random), false, true);
     }
 
     private final ProjectedTraverser<S, Object> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+        // this was ProjectedTraverser<S, C> but the projection may not be C in the case of a lambda where a
+        // Comparable may not be expected but rather an object that can be compared in any way given a lambda.
+        // not sure why this is suddenly an issue but Intellij would not let certain tests pass without this
+        // adjustment here.
         final List<Object> projections = new ArrayList<>(this.comparators.size());
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
             projections.add(TraversalUtil.apply(traverser, pair.getValue0()));
         }
-        return new ProjectedTraverser<>(traverser, projections);
+        return new ProjectedTraverser(traverser, projections);
     }
 
     private final MultiComparator<C> createMultiComparator() {
@@ -171,14 +196,16 @@
 
         private long limit;
         private MultiComparator comparator;
+        private Random random;
 
         private OrderBiOperator() {
             // for serializers that need a no-arg constructor
         }
 
-        public OrderBiOperator(final long limit, final MultiComparator multiComparator) {
+        public OrderBiOperator(final long limit, final MultiComparator multiComparator, final Random random) {
             this.limit = limit;
             this.comparator = multiComparator;
+            this.random = random;
         }
 
         @Override
@@ -186,7 +213,7 @@
             setA.addAll(setB);
             if (this.limit != -1 && setA.bulkSize() > this.limit) {
                 if (this.comparator.isShuffle())
-                    setA.shuffle();
+                    setA.shuffle(random);
                 else
                     setA.sort(this.comparator);
                 long counter = 0L;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
index 95cb6db..eb3a5f8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
@@ -24,6 +24,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -37,30 +38,37 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class OrderLocalStep<S, C extends Comparable> extends MapStep<S, S> implements ComparatorHolder<S, C>, ByModulating, TraversalParent {
+public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep<S, S> implements ComparatorHolder<S, C>, ByModulating, TraversalParent, Seedable {
 
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
     private ChainedComparator<S, C> chainedComparator = null;
+    private final Random random = new Random();
 
     public OrderLocalStep(final Traversal.Admin traversal) {
         super(traversal);
     }
 
     @Override
+    public void resetSeed(long seed) {
+        this.random.setSeed(seed);
+    }
+
+    @Override
     protected S map(final Traverser.Admin<S> traverser) {
         if (null == this.chainedComparator)
             this.chainedComparator = new ChainedComparator<>(false, this.comparators);
         final S start = traverser.get();
         if (start instanceof Collection)
-            return (S) OrderLocalStep.sortCollection((Collection) start, this.chainedComparator);
+            return (S) sortCollection((Collection) start, this.chainedComparator);
         else if (start instanceof Map)
-            return (S) OrderLocalStep.sortMap((Map) start, this.chainedComparator);
+            return (S) sortMap((Map) start, this.chainedComparator);
         else
             return start;
     }
@@ -81,6 +89,19 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        int i = 0;
+        for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
+            final Traversal.Admin<S, C> traversal = pair.getValue0();
+            if (null != traversal && traversal.equals(oldTraversal)) {
+                this.comparators.set(i, Pair.with(this.integrateChild(newTraversal), pair.getValue1()));
+                break;
+            }
+            i++;
+        }
+    }
+
+    @Override
     public List<Pair<Traversal.Admin<S, C>, Comparator<C>>> getComparators() {
         return this.comparators.isEmpty() ? Collections.singletonList(new Pair<>(new IdentityTraversal(), (Comparator) Order.asc)) : Collections.unmodifiableList(this.comparators);
     }
@@ -129,10 +150,10 @@
 
     /////////////
 
-    private static final <A> List<A> sortCollection(final Collection<A> collection, final ChainedComparator comparator) {
+    private <A> List<A> sortCollection(final Collection<A> collection, final ChainedComparator comparator) {
         if (collection instanceof List) {
             if (comparator.isShuffle())
-                Collections.shuffle((List) collection);
+                Collections.shuffle((List) collection, random);
             else
                 Collections.sort((List) collection, comparator);
             return (List<A>) collection;
@@ -141,10 +162,10 @@
         }
     }
 
-    private static final <K, V> Map<K, V> sortMap(final Map<K, V> map, final ChainedComparator comparator) {
+    private <K, V> Map<K, V> sortMap(final Map<K, V> map, final ChainedComparator comparator) {
         final List<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
         if (comparator.isShuffle())
-            Collections.shuffle(entries);
+            Collections.shuffle(entries, random);
         else
             Collections.sort(entries, comparator);
         final LinkedHashMap<K, V> sortedMap = new LinkedHashMap<>();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
index b49a1e4..cb616ce 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
@@ -38,7 +38,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class PathStep<S> extends MapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating {
+public final class PathStep<S> extends ScalarMapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating {
 
     private TraversalRing<Object, Object> traversalRing;
     private Set<String> keepLabels;
@@ -99,6 +99,13 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin<Object, Object>) oldTraversal,
+                (Traversal.Admin<Object, Object>) newTraversal);
+    }
+
+    @Override
     public String toString() {
         return StringFactory.stepString(this, this.traversalRing);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
index 3ddd4a6..b97c8d6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
@@ -37,7 +37,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class ProjectStep<S, E> extends MapStep<S, Map<String, E>> implements TraversalParent, ByModulating {
+public final class ProjectStep<S, E> extends ScalarMapStep<S, Map<String, E>> implements TraversalParent, ByModulating {
 
     private final List<String> projectKeys;
     private TraversalRing<S, E> traversalRing;
@@ -97,6 +97,13 @@
         this.traversalRing.addTraversal(this.integrateChild(selectTraversal));
     }
 
+    @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin<S, E>) oldTraversal,
+                (Traversal.Admin<S, E>) newTraversal);
+    }
+
     public List<String> getProjectKeys() {
         return this.projectKeys;
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyKeyStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyKeyStep.java
index ea1db27..9e7a0ab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyKeyStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyKeyStep.java
@@ -29,7 +29,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class PropertyKeyStep extends MapStep<Property, String> {
+public final class PropertyKeyStep extends ScalarMapStep<Property, String> {
 
     public PropertyKeyStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
index 98a284b..ecc82f9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
@@ -49,7 +49,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>>
+public class PropertyMapStep<K,E> extends ScalarMapStep<Element, Map<K, E>>
         implements TraversalParent, ByModulating, Configuring {
 
     protected final String[] propertyKeys;
@@ -61,15 +61,6 @@
     private Parameters parameters = new Parameters();
     private TraversalRing<K, E> traversalRing;
 
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #PropertyMapStep(Traversal.Admin, PropertyType, String...)}.
-     */
-    @Deprecated
-    public PropertyMapStep(final Traversal.Admin traversal, final boolean includeTokens, final PropertyType propertyType, final String... propertyKeys) {
-        this(traversal, propertyType, propertyKeys);
-        this.configure(WithOptions.tokens, includeTokens ? WithOptions.all : WithOptions.none);
-    }
-
     public PropertyMapStep(final Traversal.Admin traversal, final PropertyType propertyType, final String... propertyKeys) {
         super(traversal);
         this.propertyKeys = propertyKeys;
@@ -78,6 +69,11 @@
         this.traversalRing = new TraversalRing<>();
     }
 
+    public PropertyMapStep(final Traversal.Admin traversal, final int options, final PropertyType propertyType, final String... propertyKeys) {
+        this(traversal, propertyType, propertyKeys);
+        this.configure(WithOptions.tokens, options);
+    }
+
     @Override
     protected Map<K, E> map(final Traverser.Admin<Element> traverser) {
         final Map<Object, Object> map = new LinkedHashMap<>();
@@ -167,14 +163,6 @@
         return propertyKeys;
     }
 
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #getIncludedTokens()}.
-     */
-    @Deprecated
-    public boolean isIncludeTokens() {
-        return this.tokens != WithOptions.none;
-    }
-
     public String toString() {
         return StringFactory.stepString(this, Arrays.asList(this.propertyKeys),
                 this.traversalRing, this.returnType.name().toLowerCase());
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyValueStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyValueStep.java
index eab0ea6..6f41010 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyValueStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyValueStep.java
@@ -29,7 +29,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class PropertyValueStep<E> extends MapStep<Property<E>, E> {
+public final class PropertyValueStep<E> extends ScalarMapStep<Property<E>, E> {
 
     public PropertyValueStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
index 905a80c..f72a0cb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
@@ -36,7 +36,7 @@
 /**
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class RangeLocalStep<S> extends MapStep<S, S> {
+public final class RangeLocalStep<S> extends ScalarMapStep<S, S> {
 
     private final long low;
     private final long high;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SackStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SackStep.java
index 3e0385b..7f12a00 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SackStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SackStep.java
@@ -28,7 +28,7 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class SackStep<S, E> extends MapStep<S, E> {
+public final class SackStep<S, E> extends ScalarMapStep<S, E> {
 
     public SackStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SampleLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SampleLocalStep.java
index 5f83c53..052ca15 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SampleLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SampleLocalStep.java
@@ -21,6 +21,7 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 
 import java.util.ArrayList;
@@ -36,9 +37,9 @@
  * @author Daniel Kuppitz (http://gremlin.guru)
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class SampleLocalStep<S> extends MapStep<S, S> {
+public final class SampleLocalStep<S> extends ScalarMapStep<S, S> implements Seedable {
 
-    private static final Random RANDOM = new Random();
+    private final Random random = new Random();
 
     private final int amountToSample;
 
@@ -48,6 +49,11 @@
     }
 
     @Override
+    public void resetSeed(final long seed) {
+        this.random.setSeed(seed);
+    }
+
+    @Override
     protected S map(final Traverser.Admin<S> traverser) {
         final S start = traverser.get();
         if (start instanceof Map) {
@@ -66,7 +72,7 @@
         final List<S> original = new ArrayList<>(collection);
         final List<S> target = new ArrayList<>();
         while (target.size() < this.amountToSample) {
-            target.add(original.remove(RANDOM.nextInt(original.size())));
+            target.add(original.remove(random.nextInt(original.size())));
         }
         return (S) target;
     }
@@ -78,7 +84,7 @@
         final List<Map.Entry> original = new ArrayList<>(map.entrySet());
         final Map target = new LinkedHashMap<>(this.amountToSample);
         while (target.size() < this.amountToSample) {
-            final Map.Entry entry = original.remove(RANDOM.nextInt(original.size()));
+            final Map.Entry entry = original.remove(random.nextInt(original.size()));
             target.put(entry.getKey(), entry.getValue());
         }
         return (S) target;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ScalarMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ScalarMapStep.java
new file mode 100644
index 0000000..78e0766
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ScalarMapStep.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+
+/**
+ * A type of {@link MapStep} class which will transform the object of one {@link Traverser} into another. This class
+ * simply requires the implementation of the {@link #map(Traverser.Admin)} method to extract the object of the given
+ * {@link Traverser} and return the transformation of that object as {@code E}.
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class ScalarMapStep<S, E> extends MapStep<S,E> {
+    public ScalarMapStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    protected Traverser.Admin<E> processNextStart() {
+        final Traverser.Admin<S> traverser = this.starts.next();
+        return traverser.split(this.map(traverser), this);
+    }
+
+    protected abstract E map(final Traverser.Admin<S> traverser);
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
index 2c7aa82..976c512 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
@@ -26,13 +26,14 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
@@ -52,9 +53,19 @@
     }
 
     @Override
-    protected E map(final Traverser.Admin<S> traverser) {
-        final E end = this.getNullableScopeValue(this.pop, this.selectKey, traverser);
-        return null != end ? TraversalUtil.applyNullable((S) end, this.selectTraversal) : null;
+    protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
+        final Traverser.Admin<S> traverser = this.starts.next();
+
+        try {
+            final S o = getScopeValue(pop, selectKey, traverser);
+            if (null == o) return traverser.split(null, this);
+            final Traverser.Admin<E> outTraverser = traverser.split(TraversalUtil.applyNullable(o, this.selectTraversal), this);
+            if (!(this.getTraversal().getParent() instanceof MatchStep))
+                PathProcessor.processTraverserPathLabels(outTraverser, this.keepLabels);
+            return outTraverser;
+        } catch (KeyNotFoundException nfe) {
+            return EmptyTraverser.instance();
+        }
     }
 
     @Override
@@ -103,6 +114,12 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.selectTraversal && this.selectTraversal.equals(oldTraversal))
+            this.selectTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
     }
@@ -126,14 +143,6 @@
         return this.keepLabels;
     }
 
-    @Override
-    protected Traverser.Admin<E> processNextStart() {
-        final Traverser.Admin<E> traverser = super.processNextStart();
-        if (!(this.getTraversal().getParent() instanceof MatchStep)) {
-            PathProcessor.processTraverserPathLabels(traverser, this.keepLabels);
-        }
-        return traverser;
-    }
 }
 
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
index 875cf93..9edde9d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
@@ -26,7 +26,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -38,10 +38,12 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class SelectStep<S, E> extends MapStep<S, Map<String, E>> implements Scoping, TraversalParent, PathProcessor, ByModulating {
 
@@ -61,19 +63,21 @@
     }
 
     @Override
-    protected Map<String, E> map(final Traverser.Admin<S> traverser) {
+    protected Traverser.Admin<Map<String, E>> processNextStart() throws NoSuchElementException {
+        final Traverser.Admin<S> traverser = this.starts.next();
         final Map<String, E> bindings = new LinkedHashMap<>(this.selectKeys.size(), 1.0f);
-        for (final String selectKey : this.selectKeys) {
-            final E end = this.getNullableScopeValue(this.pop, selectKey, traverser);
-            if (null != end)
+        try {
+            for (final String selectKey : this.selectKeys) {
+                final E end = this.getScopeValue(this.pop, selectKey, traverser);
                 bindings.put(selectKey, TraversalUtil.applyNullable(end, this.traversalRing.next()));
-            else {
-                this.traversalRing.reset();
-                return null;
             }
+        } catch (KeyNotFoundException nfe) {
+            return EmptyTraverser.instance();
+        } finally {
+            this.traversalRing.reset();
         }
-        this.traversalRing.reset();
-        return bindings;
+
+        return PathProcessor.processTraverserPathLabels(traverser.split(bindings, this), this.keepLabels);
     }
 
     @Override
@@ -119,6 +123,13 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin<Object, E>) oldTraversal,
+                (Traversal.Admin<Object, E>) newTraversal);
+    }
+
+    @Override
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
     }
@@ -150,9 +161,4 @@
     public Set<String> getKeepLabels() {
         return this.keepLabels;
     }
-
-    @Override
-    protected Traverser.Admin<Map<String, E>> processNextStart() {
-        return PathProcessor.processTraverserPathLabels(super.processNextStart(), this.keepLabels);
-    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumLocalStep.java
index 72e6539..3249e31 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumLocalStep.java
@@ -32,7 +32,7 @@
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class SumLocalStep<E extends Number, S extends Iterable<E>> extends MapStep<S, E> {
+public final class SumLocalStep<E extends Number, S extends Iterable<E>> extends ScalarMapStep<S, E> {
 
     public SumLocalStep(final Traversal.Admin traversal) {
         super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
index ea678a5..336323e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
@@ -34,7 +34,7 @@
 /**
  * @author Matt Frantz (http://github.com/mhfrantz)
  */
-public final class TailLocalStep<S> extends MapStep<S, S> {
+public final class TailLocalStep<S> extends ScalarMapStep<S, S> {
 
     private final long limit;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMapStep.java
index 896b833..7dc82d7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMapStep.java
@@ -22,16 +22,19 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class TraversalMapStep<S, E> extends MapStep<S, E> implements TraversalParent {
 
@@ -43,9 +46,10 @@
     }
 
     @Override
-    protected E map(final Traverser.Admin<S> traverser) {
+    protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
+        final Traverser.Admin<S> traverser = this.starts.next();
         final Iterator<E> iterator = TraversalUtil.applyAll(traverser, this.mapTraversal);
-        return iterator.hasNext() ? iterator.next() : null;
+        return  iterator.hasNext() ? traverser.split(iterator.next(), this) : EmptyTraverser.instance();
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java
index 1d5ecd1..ff9f099 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java
@@ -18,14 +18,15 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
-import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
@@ -34,14 +35,12 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
-
 /**
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public final class TraversalSelectStep<S, E> extends MapStep<S, E> implements TraversalParent, PathProcessor, ByModulating {
+public final class TraversalSelectStep<S, E> extends MapStep<S, E> implements TraversalParent, PathProcessor, ByModulating, Scoping {
 
     private final Pop pop;
     private Traversal.Admin<S, E> keyTraversal;
@@ -55,26 +54,35 @@
     }
 
     @Override
-    protected E map(final Traverser.Admin<S> traverser) {
-        E end = null;
+    protected Traverser.Admin<E> processNextStart() {
+        final Traverser.Admin<S> traverser = this.starts.next();
         final Iterator<E> keyIterator = TraversalUtil.applyAll(traverser, this.keyTraversal);
         if (keyIterator.hasNext()) {
             final E key = keyIterator.next();
-            final Object object = traverser.get();
-            if (object instanceof Map && ((Map) object).containsKey(key))
-                end = (E) ((Map) object).get(key);
-            else if (key instanceof String) {
-                final String skey = (String) key;
-                if (traverser.getSideEffects().exists(skey)) {
-                    end = traverser.getSideEffects().get((String) key);
-                } else {
-                    final Path path = traverser.path();
-                    if (path.hasLabel(skey))
-                        end = null == pop ? path.get(skey) : path.get(pop, skey);
+            try {
+                final E end = getScopeValue(pop, key, traverser);
+                final Traverser.Admin<E> outTraverser = traverser.split(null == end ? null : TraversalUtil.applyNullable(end, this.selectTraversal), this);
+                if (!(this.getTraversal().getParent() instanceof MatchStep)) {
+                    PathProcessor.processTraverserPathLabels(outTraverser, this.keepLabels);
                 }
+                return outTraverser;
+            } catch (KeyNotFoundException nfe) {
+                return EmptyTraverser.instance();
             }
+        } else {
+            return EmptyTraverser.instance();
         }
-        return null != end ? TraversalUtil.applyNullable(end, this.selectTraversal) : null;
+    }
+
+    @Override
+    public Set<String> getScopeKeys() {
+        // can't return scope keys here because they aren't known prior to traversal execution and this method is
+        // used at strategy application time. not getting any test failures as a result of returning empty. assuming
+        // that strategies don't use Scoping in a way that requires the keys to be known and if they aren't doesn't
+        // hose the whole traversal. in the worst case, strategies will hopefully just leave steps alone rather than
+        // make their own assumptions that the step is not selecting anything. if that is happening somehow we might
+        // need to modify Scoping to better suite this runtime evaluation of the key.
+        return Collections.emptySet();
     }
 
     @Override
@@ -155,15 +163,6 @@
     public Set<String> getKeepLabels() {
         return this.keepLabels;
     }
-
-    @Override
-    protected Traverser.Admin<E> processNextStart() {
-        final Traverser.Admin<E> traverser = super.processNextStart();
-        if (!(this.getTraversal().getParent() instanceof MatchStep)) {
-            PathProcessor.processTraverserPathLabels(traverser, this.keepLabels);
-        }
-        return traverser;
-    }
 }
 
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
index 41310aa..1904859 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
@@ -64,6 +64,13 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin<Object, Object>) oldTraversal,
+                (Traversal.Admin<Object, Object>) newTraversal);
+    }
+
+    @Override
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS);
     }
@@ -83,7 +90,6 @@
         return topTree;
     }
 
-
     @Override
     public TreeStep<S> clone() {
         final TreeStep<S> clone = (TreeStep<S>) super.clone();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
new file mode 100644
index 0000000..0f75963
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
@@ -0,0 +1,168 @@
+/*
+ * 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.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.LocalBarrier;
+import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class AggregateGlobalStep<S> extends AbstractStep<S, S> implements SideEffectCapable<Collection, Collection>, TraversalParent, ByModulating, LocalBarrier<S> {
+
+    private Traversal.Admin<S, Object> aggregateTraversal = null;
+    private String sideEffectKey;
+    private TraverserSet<S> barrier;
+
+    public AggregateGlobalStep(final Traversal.Admin traversal, final String sideEffectKey) {
+        super(traversal);
+        this.sideEffectKey = sideEffectKey;
+        this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get();
+        this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, (Supplier) BulkSetSupplier.instance(), Operator.addAll);
+    }
+
+    @Override
+    public String getSideEffectKey() {
+        return this.sideEffectKey;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.sideEffectKey, this.aggregateTraversal);
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> aggregateTraversal) {
+        this.aggregateTraversal = this.integrateChild(aggregateTraversal);
+    }
+
+    @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.aggregateTraversal && this.aggregateTraversal.equals(oldTraversal))
+            this.aggregateTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
+    public List<Traversal.Admin<S, Object>> getLocalChildren() {
+        return null == this.aggregateTraversal ? Collections.emptyList() : Collections.singletonList(this.aggregateTraversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
+    }
+
+    @Override
+    public AggregateGlobalStep<S> clone() {
+        final AggregateGlobalStep<S> clone = (AggregateGlobalStep<S>) super.clone();
+        clone.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get();
+        if (null != this.aggregateTraversal)
+            clone.aggregateTraversal = this.aggregateTraversal.clone();
+        return clone;
+    }
+
+    @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.integrateChild(this.aggregateTraversal);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
+        if (this.aggregateTraversal != null)
+            result ^= this.aggregateTraversal.hashCode();
+        return result;
+    }
+
+    @Override
+    protected Traverser.Admin<S> processNextStart() {
+        if (this.barrier.isEmpty()) {
+            this.processAllStarts();
+        }
+        return this.barrier.remove();
+    }
+
+    @Override
+    public void processAllStarts() {
+        if (this.starts.hasNext()) {
+            final BulkSet<Object> bulkSet = new BulkSet<>();
+            while (this.starts.hasNext()) {
+                final Traverser.Admin<S> traverser = this.starts.next();
+                bulkSet.add(TraversalUtil.applyNullable(traverser, this.aggregateTraversal), traverser.bulk());
+                traverser.setStepId(this.getNextStep().getId()); // when barrier is reloaded, the traversers should be at the next step
+                this.barrier.add(traverser);
+            }
+            this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
+        }
+    }
+
+    @Override
+    public boolean hasNextBarrier() {
+        if (this.barrier.isEmpty()) {
+            this.processAllStarts();
+        }
+        return !this.barrier.isEmpty();
+    }
+
+    @Override
+    public TraverserSet<S> nextBarrier() throws NoSuchElementException {
+        if (this.barrier.isEmpty()) {
+            this.processAllStarts();
+        }
+        if (this.barrier.isEmpty())
+            throw FastNoSuchElementException.instance();
+        else {
+            final TraverserSet<S> temp = this.barrier;
+            this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get();
+            return temp;
+        }
+    }
+
+    @Override
+    public void addBarrier(final TraverserSet<S> barrier) {
+        this.barrier.addAll(barrier);
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        this.barrier.clear();
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
new file mode 100644
index 0000000..3c7c0fa
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
@@ -0,0 +1,112 @@
+/*
+ * 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.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class AggregateLocalStep<S> extends SideEffectStep<S> implements SideEffectCapable<Collection, Collection>, TraversalParent, ByModulating {
+
+    private Traversal.Admin<S, Object> storeTraversal = null;
+    private String sideEffectKey;
+
+    public AggregateLocalStep(final Traversal.Admin traversal, final String sideEffectKey) {
+        super(traversal);
+        this.sideEffectKey = sideEffectKey;
+        this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, (Supplier) BulkSetSupplier.instance(), Operator.addAll);
+    }
+
+    @Override
+    protected void sideEffect(final Traverser.Admin<S> traverser) {
+        final BulkSet<Object> bulkSet = new BulkSet<>();
+        bulkSet.add(TraversalUtil.applyNullable(traverser, this.storeTraversal), traverser.bulk());
+        this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
+    }
+
+    @Override
+    public String getSideEffectKey() {
+        return this.sideEffectKey;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.sideEffectKey, this.storeTraversal);
+    }
+
+    @Override
+    public List<Traversal.Admin<S, Object>> getLocalChildren() {
+        return null == this.storeTraversal ? Collections.emptyList() : Collections.singletonList(this.storeTraversal);
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> storeTraversal) {
+        this.storeTraversal = this.integrateChild(storeTraversal);
+    }
+
+    @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.storeTraversal && this.storeTraversal.equals(oldTraversal))
+            this.storeTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.SIDE_EFFECTS, TraverserRequirement.BULK);
+    }
+
+    @Override
+    public AggregateLocalStep<S> clone() {
+        final AggregateLocalStep<S> clone = (AggregateLocalStep<S>) super.clone();
+        if (null != this.storeTraversal)
+            clone.storeTraversal = this.storeTraversal.clone();
+        return clone;
+    }
+
+    @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.integrateChild(this.storeTraversal);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
+        if (this.storeTraversal != null)
+            result ^= this.storeTraversal.hashCode();
+        return result;
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java
deleted file mode 100644
index 9c2ea48..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Operator;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.LocalBarrier;
-import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class AggregateStep<S> extends AbstractStep<S, S> implements SideEffectCapable<Collection, Collection>, TraversalParent, ByModulating, LocalBarrier<S> {
-
-    private Traversal.Admin<S, Object> aggregateTraversal = null;
-    private String sideEffectKey;
-    private TraverserSet<S> barrier;
-
-    public AggregateStep(final Traversal.Admin traversal, final String sideEffectKey) {
-        super(traversal);
-        this.sideEffectKey = sideEffectKey;
-        this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get();
-        this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, (Supplier) BulkSetSupplier.instance(), Operator.addAll);
-    }
-
-    @Override
-    public String getSideEffectKey() {
-        return this.sideEffectKey;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.sideEffectKey, this.aggregateTraversal);
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> aggregateTraversal) {
-        this.aggregateTraversal = this.integrateChild(aggregateTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<S, Object>> getLocalChildren() {
-        return null == this.aggregateTraversal ? Collections.emptyList() : Collections.singletonList(this.aggregateTraversal);
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
-    }
-
-    @Override
-    public AggregateStep<S> clone() {
-        final AggregateStep<S> clone = (AggregateStep<S>) super.clone();
-        clone.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get();
-        if (null != this.aggregateTraversal)
-            clone.aggregateTraversal = this.aggregateTraversal.clone();
-        return clone;
-    }
-
-    @Override
-    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
-        super.setTraversal(parentTraversal);
-        this.integrateChild(this.aggregateTraversal);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
-        if (this.aggregateTraversal != null)
-            result ^= this.aggregateTraversal.hashCode();
-        return result;
-    }
-
-    @Override
-    protected Traverser.Admin<S> processNextStart() {
-        if (this.barrier.isEmpty()) {
-            this.processAllStarts();
-        }
-        return this.barrier.remove();
-    }
-
-    @Override
-    public void processAllStarts() {
-        if (this.starts.hasNext()) {
-            final BulkSet<Object> bulkSet = new BulkSet<>();
-            while (this.starts.hasNext()) {
-                final Traverser.Admin<S> traverser = this.starts.next();
-                bulkSet.add(TraversalUtil.applyNullable(traverser, this.aggregateTraversal), traverser.bulk());
-                traverser.setStepId(this.getNextStep().getId()); // when barrier is reloaded, the traversers should be at the next step
-                this.barrier.add(traverser);
-            }
-            this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
-        }
-    }
-
-    @Override
-    public boolean hasNextBarrier() {
-        if (this.barrier.isEmpty()) {
-            this.processAllStarts();
-        }
-        return !this.barrier.isEmpty();
-    }
-
-    @Override
-    public TraverserSet<S> nextBarrier() throws NoSuchElementException {
-        if (this.barrier.isEmpty()) {
-            this.processAllStarts();
-        }
-        if (this.barrier.isEmpty())
-            throw FastNoSuchElementException.instance();
-        else {
-            final TraverserSet<S> temp = this.barrier;
-            this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get();
-            return temp;
-        }
-    }
-
-    @Override
-    public void addBarrier(final TraverserSet<S> barrier) {
-        this.barrier.addAll(barrier);
-    }
-
-    @Override
-    public void reset() {
-        super.reset();
-        this.barrier.clear();
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
index 88a1cb7..41ddeef 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
@@ -106,4 +106,10 @@
     public void modulateBy(final Traversal.Admin<?, ?> keyTraversal) throws UnsupportedOperationException {
         this.keyTraversal = this.integrateChild(keyTraversal);
     }
+
+    @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.keyTraversal && this.keyTraversal.equals(oldTraversal))
+            this.keyTraversal = this.integrateChild(newTraversal);
+    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
index fd31bc3..9467467 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
@@ -24,13 +24,13 @@
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Grouping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ProfilingAware;
 import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
@@ -44,7 +44,8 @@
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implements SideEffectCapable<Map<K, ?>, Map<K, V>>, TraversalParent, ByModulating, ProfilingAware {
+public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S>
+        implements SideEffectCapable<Map<K, ?>, Map<K, V>>, TraversalParent, ByModulating, ProfilingAware, Grouping<S, K, V> {
 
     private char state = 'k';
     private Traversal.Admin<S, K> keyTraversal;
@@ -58,7 +59,7 @@
         super(traversal);
         this.sideEffectKey = sideEffectKey;
         this.valueTraversal = this.integrateChild(__.fold().asAdmin());
-        this.barrierStep = GroupStep.determineBarrierStep(this.valueTraversal);
+        this.barrierStep = determineBarrierStep(this.valueTraversal);
         this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, HashMapSupplier.instance(),
                 new GroupStep.GroupBiOperator<>(null == this.barrierStep ?
                         Operator.assign :
@@ -75,17 +76,31 @@
     }
 
     @Override
+    public Traversal.Admin<S, K> getKeyTraversal() {
+        return this.keyTraversal;
+    }
+
+    @Override
+    public Traversal.Admin<S, V> getValueTraversal() {
+        return this.valueTraversal;
+    }
+
+    private void setValueTraversal(final Traversal.Admin valueTraversal) {
+        this.valueTraversal = this.integrateChild(convertValueTraversal(valueTraversal));
+        this.barrierStep = determineBarrierStep(this.valueTraversal);
+        this.getTraversal().getSideEffects().register(this.sideEffectKey, null,
+                new GroupStep.GroupBiOperator<>(null == this.barrierStep ?
+                        Operator.assign :
+                        this.barrierStep.getMemoryComputeKey().getReducer()));
+    }
+
+    @Override
     public void modulateBy(final Traversal.Admin<?, ?> kvTraversal) {
         if ('k' == this.state) {
             this.keyTraversal = this.integrateChild(kvTraversal);
             this.state = 'v';
         } else if ('v' == this.state) {
-            this.valueTraversal = this.integrateChild(GroupStep.convertValueTraversal(kvTraversal));
-            this.barrierStep = GroupStep.determineBarrierStep(this.valueTraversal);
-            this.getTraversal().getSideEffects().register(this.sideEffectKey, null,
-                    new GroupStep.GroupBiOperator<>(null == this.barrierStep ?
-                            Operator.assign :
-                            this.barrierStep.getMemoryComputeKey().getReducer()));
+            this.setValueTraversal(kvTraversal);
             this.state = 'x';
         } else {
             throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
@@ -93,6 +108,14 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.keyTraversal && this.keyTraversal.equals(oldTraversal))
+            this.keyTraversal = this.integrateChild(newTraversal);
+        else if (null != this.valueTraversal && this.valueTraversal.equals(oldTraversal))
+            this.setValueTraversal(newTraversal);
+    }
+
+    @Override
     protected void sideEffect(final Traverser.Admin<S> traverser) {
         final Map<K, V> map = new HashMap<>(1);
         this.valueTraversal.reset();
@@ -101,7 +124,7 @@
         // reset the barrierStep as there are now ProfileStep instances present and the timers won't start right
         // without specific configuration through wrapping both the Barrier and ProfileStep in ProfiledBarrier
         if (resetBarrierForProfiling) {
-            barrierStep = GroupStep.determineBarrierStep(valueTraversal);
+            barrierStep = determineBarrierStep(valueTraversal);
 
             // the barrier only needs to be reset once
             resetBarrierForProfiling = false;
@@ -146,7 +169,7 @@
         if (null != this.keyTraversal)
             clone.keyTraversal = this.keyTraversal.clone();
         clone.valueTraversal = this.valueTraversal.clone();
-        clone.barrierStep = GroupStep.determineBarrierStep(clone.valueTraversal);
+        clone.barrierStep = determineBarrierStep(clone.valueTraversal);
         return clone;
     }
 
@@ -167,6 +190,6 @@
 
     @Override
     public Map<K, V> generateFinalResult(final Map<K, ?> object) {
-        return GroupStep.doFinalReduction((Map<K, Object>) object, this.valueTraversal);
+        return doFinalReduction((Map<K, Object>) object, this.valueTraversal);
     }
 }
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/IoStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/IoStep.java
index 64a9035..dc5f040 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/IoStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/IoStep.java
@@ -188,7 +188,7 @@
                 final GryoMapper.Builder builder = GryoMapper.build();
                 detectRegistries().forEach(builder::addRegistry);
                 return GryoWriter.build().mapper(builder.create()).create();
-            }else if (objectOrClass.equals(IO.graphml))
+            } else if (objectOrClass.equals(IO.graphml))
                 return GraphMLWriter.build().create();
             else {
                 try {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
index 650140e..bd0e828 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
@@ -52,6 +52,12 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        if (null != this.sackTraversal && this.sackTraversal.equals(oldTraversal))
+            this.sackTraversal = this.integrateChild(newTraversal);
+    }
+
+    @Override
     public List<Traversal.Admin<S, B>> getLocalChildren() {
         return null == this.sackTraversal ? Collections.emptyList() : Collections.singletonList(this.sackTraversal);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/StoreStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/StoreStep.java
deleted file mode 100644
index ac5b0c6..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/StoreStep.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Operator;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class StoreStep<S> extends SideEffectStep<S> implements SideEffectCapable<Collection, Collection>, TraversalParent, ByModulating {
-
-    private Traversal.Admin<S, Object> storeTraversal = null;
-    private String sideEffectKey;
-
-    public StoreStep(final Traversal.Admin traversal, final String sideEffectKey) {
-        super(traversal);
-        this.sideEffectKey = sideEffectKey;
-        this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, (Supplier) BulkSetSupplier.instance(), Operator.addAll);
-    }
-
-    @Override
-    protected void sideEffect(final Traverser.Admin<S> traverser) {
-        final BulkSet<Object> bulkSet = new BulkSet<>();
-        bulkSet.add(TraversalUtil.applyNullable(traverser, this.storeTraversal), traverser.bulk());
-        this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
-    }
-
-    @Override
-    public String getSideEffectKey() {
-        return this.sideEffectKey;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.sideEffectKey, this.storeTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<S, Object>> getLocalChildren() {
-        return null == this.storeTraversal ? Collections.emptyList() : Collections.singletonList(this.storeTraversal);
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> storeTraversal) {
-        this.storeTraversal = this.integrateChild(storeTraversal);
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.SIDE_EFFECTS, TraverserRequirement.BULK);
-    }
-
-    @Override
-    public StoreStep<S> clone() {
-        final StoreStep<S> clone = (StoreStep<S>) super.clone();
-        if (null != this.storeTraversal)
-            clone.storeTraversal = this.storeTraversal.clone();
-        return clone;
-    }
-
-    @Override
-    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
-        super.setTraversal(parentTraversal);
-        this.integrateChild(this.storeTraversal);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
-        if (this.storeTraversal != null)
-            result ^= this.storeTraversal.hashCode();
-        return result;
-    }
-}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
index 2d43ddc..c3f0fbd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
@@ -119,6 +119,13 @@
     }
 
     @Override
+    public void replaceLocalChild(final Traversal.Admin<?, ?> oldTraversal, final Traversal.Admin<?, ?> newTraversal) {
+        this.traversalRing.replaceTraversal(
+                (Traversal.Admin<Object, Object>) oldTraversal,
+                (Traversal.Admin<Object, Object>) newTraversal);
+    }
+
+    @Override
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index 32d77e8..7903721 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -21,6 +21,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
@@ -43,7 +44,7 @@
     protected String id = Traverser.Admin.HALT;
     protected Traversal.Admin traversal;
     protected ExpandableStepIterator<S> starts;
-    protected Traverser.Admin<E> nextEnd = null;
+    protected Traverser.Admin<E> nextEnd = EmptyTraverser.instance();
     protected boolean traverserStepIdAndLabelsSetByChild = false;
 
     protected Step<?, S> previousStep = EmptyStep.instance();
@@ -83,7 +84,7 @@
     @Override
     public void reset() {
         this.starts.clear();
-        this.nextEnd = null;
+        this.nextEnd = EmptyTraverser.instance();
     }
 
     @Override
@@ -118,17 +119,17 @@
 
     @Override
     public Traverser.Admin<E> next() {
-        if (null != this.nextEnd) {
+        if (EmptyTraverser.instance() != this.nextEnd) {
             try {
                 return this.prepareTraversalForNextStep(this.nextEnd);
             } finally {
-                this.nextEnd = null;
+                this.nextEnd = EmptyTraverser.instance();
             }
         } else {
             while (true) {
                 if (Thread.interrupted()) throw new TraversalInterruptedException();
                 final Traverser.Admin<E> traverser = this.processNextStart();
-                if (null != traverser.get() && 0 != traverser.bulk())
+                if (traverser.bulk() > 0)
                     return this.prepareTraversalForNextStep(traverser);
             }
         }
@@ -136,17 +137,17 @@
 
     @Override
     public boolean hasNext() {
-        if (null != this.nextEnd)
+        if (EmptyTraverser.instance() != this.nextEnd)
             return true;
         else {
             try {
                 while (true) {
                     if (Thread.interrupted()) throw new TraversalInterruptedException();
                     this.nextEnd = this.processNextStart();
-                    if (null != this.nextEnd.get() && 0 != this.nextEnd.bulk())
+                    if (this.nextEnd.bulk() > 0)
                         return true;
                     else
-                        this.nextEnd = null;
+                        this.nextEnd = EmptyTraverser.instance();
                 }
             } catch (final NoSuchElementException e) {
                 return false;
@@ -179,7 +180,7 @@
             clone.starts = new ExpandableStepIterator<>(clone, (TraverserSet<S>) traversal.getTraverserSetSupplier().get());
             clone.previousStep = EmptyStep.instance();
             clone.nextStep = EmptyStep.instance();
-            clone.nextEnd = null;
+            clone.nextEnd = EmptyTraverser.instance();
             clone.traversal = EmptyTraversal.instance();
             clone.labels = new LinkedHashSet<>(this.labels);
             clone.reset();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
index 623b810..1b5e562 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
@@ -28,6 +28,7 @@
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -35,7 +36,8 @@
  */
 public class ImmutablePath implements Path, Serializable, Cloneable {
 
-    private static final ImmutablePath TAIL_PATH = new ImmutablePath(null, null, null);
+    private static final Object END = EmptyPath.instance();
+    private static final ImmutablePath TAIL_PATH = new ImmutablePath(null, END, null);
 
     private ImmutablePath previousPath;
     private Object currentObject;
@@ -58,7 +60,7 @@
     }
 
     private final boolean isTail() {
-        return null == this.currentObject;
+        return END.equals(this.currentObject);
     }
 
     @Override
@@ -230,7 +232,7 @@
         while (true) {
             if (currentPath.isTail())
                 break;
-            hashCodes[index] = currentPath.currentObject.hashCode();
+            hashCodes[index] = Objects.hashCode(currentPath.currentObject);
             currentPath = currentPath.previousPath;
             index--;
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
index 5c86ad9..f16fd70 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
@@ -37,6 +37,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.Supplier;
 
@@ -73,6 +74,17 @@
     }
 
     /**
+     * Checks for existence of a key and value in a parameter set.
+     *
+     * @param key the key to check
+     * @param value the value to check
+     * @return {@code true} if the key and value are present and {@code false} otherwise
+     */
+    public boolean contains(final Object key, final Object value) {
+        return this.contains(key) && this.parameters.get(key).contains(value);
+    }
+
+    /**
      * Renames a key in the parameter set.
      *
      * @param oldKey the key to rename
@@ -180,27 +192,24 @@
             if (!(keyValues[ix] instanceof String) && !(keyValues[ix] instanceof T) && !(keyValues[ix] instanceof Traversal))
                 throw new IllegalArgumentException("The provided key/value array must have a String, T, or Traversal on even array indices");
 
-            if (keyValues[ix + 1] != null) {
-
-                // check both key and value for traversal instances. track the list of traversals that are present so
-                // that elsewhere in Parameters there is no need to iterate all values to not find any. also grab
-                // available labels in traversal values
-                for (int iy = 0; iy < 2; iy++) {
-                    if (keyValues[ix + iy] instanceof Traversal.Admin) {
-                        final Traversal.Admin t = (Traversal.Admin) keyValues[ix + iy];
-                        addTraversal(t);
-                        if (parent != null) parent.integrateChild(t);
-                    }
+            // check both key and value for traversal instances. track the list of traversals that are present so
+            // that elsewhere in Parameters there is no need to iterate all values to not find any. also grab
+            // available labels in traversal values
+            for (int iy = 0; iy < 2; iy++) {
+                if (keyValues[ix + iy] instanceof Traversal.Admin) {
+                    final Traversal.Admin t = (Traversal.Admin) keyValues[ix + iy];
+                    addTraversal(t);
+                    if (parent != null) parent.integrateChild(t);
                 }
+            }
 
-                List<Object> values = this.parameters.get(keyValues[ix]);
-                if (null == values) {
-                    values = new ArrayList<>();
-                    values.add(keyValues[ix + 1]);
-                    this.parameters.put(keyValues[ix], values);
-                } else {
-                    values.add(keyValues[ix + 1]);
-                }
+            List<Object> values = this.parameters.get(keyValues[ix]);
+            if (null == values) {
+                values = new ArrayList<>();
+                values.add(keyValues[ix + 1]);
+                this.parameters.put(keyValues[ix], values);
+            } else {
+                values.add(keyValues[ix + 1]);
             }
         }
     }
@@ -254,7 +263,7 @@
         for (final Map.Entry<Object, List<Object>> entry : this.parameters.entrySet()) {
             result ^= entry.getKey().hashCode();
             for (final Object value : entry.getValue()) {
-                result ^= Integer.rotateLeft(value.hashCode(), entry.getKey().hashCode());
+                result ^= Integer.rotateLeft(Objects.hashCode(value), entry.getKey().hashCode());
             }
         }
         return result;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java
index 8c9c29a..17e392e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.strategy;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
index 25a2833..903ea3a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Parameterizing;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/HaltedTraverserStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/HaltedTraverserStrategy.java
index 3f02c40..988d818 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/HaltedTraverserStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/HaltedTraverserStrategy.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/OptionsStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/OptionsStrategy.java
index fd64d7f..1a7a81f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/OptionsStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/OptionsStrategy.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
index 111609b..2103bf5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Parameterizing;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/RequirementsStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/RequirementsStrategy.java
index 78c48b8..cd9d663 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/RequirementsStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/RequirementsStrategy.java
@@ -44,12 +44,12 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (traversal.getParent() instanceof EmptyStep && !this.requirements.isEmpty())
+        if (traversal.isRoot() && !this.requirements.isEmpty())
             traversal.addStep(new RequirementsStep<>(traversal, this.requirements));
     }
 
     public static void addRequirements(final TraversalStrategies traversalStrategies, final TraverserRequirement... requirements) {
-        RequirementsStrategy strategy = (RequirementsStrategy) traversalStrategies.toList().stream().filter(s -> s instanceof RequirementsStrategy).findAny().orElse(null);
+        RequirementsStrategy strategy = (RequirementsStrategy) traversalStrategies.getStrategy(RequirementsStrategy.class).orElse(null);
         if (null == strategy) {
             strategy = new RequirementsStrategy();
             traversalStrategies.addStrategies(strategy);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java
index 0598d17..e321f8c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java
@@ -47,7 +47,7 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (traversal.getParent() instanceof EmptyStep)
+        if (traversal.isRoot())
             traversal.getSideEffects().setSack(this.initialValue, this.splitOperator, this.mergeOperator);
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SeedStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SeedStrategy.java
new file mode 100644
index 0000000..dbf9324
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SeedStrategy.java
@@ -0,0 +1,79 @@
+/*
+ * 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.strategy.decoration;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A strategy that resets the specified {@code seed} value for {@link Seedable} steps, which in turn will produce
+ * deterministic results from those steps. It is important to note that when using this strategy that it only
+ * guarantees deterministic results from a step but not from an entire traversal. For example, if a graph does no
+ * guarantee iteration order for {@code g.V()} then repeated runs of {@code g.V().coin(0.5)} with this strategy
+ * will return the same number of results but not necessarily the same ones. The same problem can occur in OLAP-based
+ * traversals where iteration order is not explicitly guaranteed. The only way to ensure completely deterministic
+ * results in that sense is to apply some form of {@code order()} in these cases
+ */
+public class SeedStrategy extends AbstractTraversalStrategy<TraversalStrategy.DecorationStrategy>
+        implements TraversalStrategy.DecorationStrategy {
+
+    private final long seed;
+
+    public SeedStrategy(final long seed) {
+        this.seed = seed;
+    }
+
+    public long getSeed() {
+        return seed;
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        final List<Seedable> seedableSteps = TraversalHelper.getStepsOfAssignableClass(Seedable.class, traversal);
+        for (final Seedable seedableStepsToReset : seedableSteps) {
+            seedableStepsToReset.resetSeed(seed);
+        }
+    }
+
+    public static final String ID_SEED = "seed";
+
+    public static SeedStrategy create(final Configuration configuration) {
+        if (!configuration.containsKey(ID_SEED))
+            throw new IllegalArgumentException("SeedStrategy configuration requires a 'seed' value");
+
+        return new SeedStrategy(Long.parseLong(configuration.getProperty(ID_SEED).toString()));
+    }
+
+    @Override
+    public Configuration getConfiguration() {
+        final Map<String, Object> map = new HashMap<>();
+        map.put(STRATEGY, SeedStrategy.class.getCanonicalName());
+        map.put(ID_SEED, this.seed);
+        return new MapConfiguration(map);
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
index 5c99b5f..6be1cb4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
@@ -44,13 +44,13 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (traversal.getParent() instanceof EmptyStep) {
+        if (traversal.isRoot()) {
             this.sideEffects.forEach(triplet -> traversal.getSideEffects().register(triplet.getValue0(), triplet.getValue1(), triplet.getValue2()));
         }
     }
 
     public static <A> void addSideEffect(final TraversalStrategies traversalStrategies, final String key, final A value, final BinaryOperator<A> reducer) {
-        SideEffectStrategy strategy = (SideEffectStrategy) traversalStrategies.toList().stream().filter(s -> s instanceof SideEffectStrategy).findAny().orElse(null);
+        SideEffectStrategy strategy = traversalStrategies.getStrategy(SideEffectStrategy.class).orElse(null);
         if (null == strategy) {
             strategy = new SideEffectStrategy();
             traversalStrategies.addStrategies(strategy);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java
index a57a7d3..5333d2b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java
@@ -18,13 +18,13 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.ClassFilterStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
@@ -150,18 +150,7 @@
             traversal.getStartStep().removeLabel(MARKER);
             return;
         }
-        for (final Step step : traversal.getSteps()) {
-            if (step instanceof TraversalParent) {
-                for (final Traversal.Admin t : ((TraversalParent) step).getLocalChildren()) {
-                    this.apply(t);
-                    t.getStartStep().addLabel(MARKER);
-                }
-                for (final Traversal.Admin t : ((TraversalParent) step).getGlobalChildren()) {
-                    this.apply(t);
-                    t.getStartStep().addLabel(MARKER);
-                }
-            }
-        }
+
         //
         final List<GraphStep> graphSteps = TraversalHelper.getStepsOfAssignableClass(GraphStep.class, traversal);
         final List<VertexStep> vertexSteps = TraversalHelper.getStepsOfAssignableClass(VertexStep.class, traversal);
@@ -231,19 +220,19 @@
                         }
                     } else {
                         Stream.concat(((TraversalParent) step).getGlobalChildren().stream(), ((TraversalParent) step).getLocalChildren().stream())
-                                .filter(t -> t instanceof ElementValueTraversal)
+                                .filter(t -> t instanceof ValueTraversal)
                                 .forEach(t -> {
                                     final char propertyType = processesPropertyType(step.getPreviousStep());
                                     if ('p' != propertyType) {
                                         final Traversal.Admin<?, ?> temp = new DefaultTraversal<>();
-                                        temp.addStep(new PropertiesStep<>(temp, PropertyType.PROPERTY, ((ElementValueTraversal) t).getPropertyKey()));
+                                        temp.addStep(new PropertiesStep<>(temp, PropertyType.PROPERTY, ((ValueTraversal) t).getPropertyKey()));
                                         if ('v' == propertyType)
                                             TraversalHelper.insertTraversal(0, nonCheckPropertyCriterion.clone(), temp);
                                         else
                                             temp.addStep(checkPropertyCriterion.clone());
                                         temp.addStep(new PropertyValueStep<>(temp));
                                         temp.setParent((TraversalParent) step);
-                                        ((ElementValueTraversal) t).setBypassTraversal(temp);
+                                        ((ValueTraversal) t).setBypassTraversal(temp);
                                     }
                                 });
                     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java
index a70e22a..a0577ef 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ProfileStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ProfileStrategy.java
index ceedb38..dedd567 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ProfileStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ProfileStrategy.java
@@ -45,9 +45,11 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if ((traversal.getParent() instanceof EmptyStep || traversal.getParent() instanceof VertexProgramStep) &&
+        if (!traversal.getEndStep().getLabels().contains(MARKER) &&
+                (traversal.isRoot() || traversal.getParent() instanceof VertexProgramStep) &&
                 TraversalHelper.hasStepOfAssignableClassRecursively(ProfileSideEffectStep.class, traversal))
             TraversalHelper.applyTraversalRecursively(t -> t.getEndStep().addLabel(MARKER), traversal);
+
         if (traversal.getEndStep().getLabels().contains(MARKER)) {
             traversal.getEndStep().removeLabel(MARKER);
             // Add .profile() step after every pre-existing step.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategy.java
index 41e1325..ebb0423 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategy.java
@@ -21,7 +21,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ScalarMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ProfileSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
@@ -56,7 +56,7 @@
         return INSTANCE;
     }
 
-    public static class ReferenceElementStep<S, E> extends MapStep<S, E> {
+    public static class ReferenceElementStep<S, E> extends ScalarMapStep<S, E> {
 
         public ReferenceElementStep(final Traversal.Admin traversal) {
             super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/ByModulatorOptimizationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/ByModulatorOptimizationStrategy.java
new file mode 100644
index 0000000..0faaef9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/ByModulatorOptimizationStrategy.java
@@ -0,0 +1,139 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Grouping;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyKeyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.structure.PropertyType;
+import org.apache.tinkerpop.gremlin.structure.T;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This strategy looks for standard traversals in by-modulators and replaces them with more optimized traversals
+ * (e.g. {@code TokenTraversal}) if possible.
+ * <p/>
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @example <pre>
+ * __.path().by(id())                        // is replaced by __.path().by(id)
+ * __.dedup().by(label())                    // is replaced by __.dedup().by(label)
+ * __.order().by(values("name"))             // is replaced by __.order().by("name")
+ * __.group().by().by(values("name").fold()) // is replaced by __.group().by("name")
+ * </pre>
+ */
+public final class ByModulatorOptimizationStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy>
+        implements TraversalStrategy.OptimizationStrategy {
+
+    private static final ByModulatorOptimizationStrategy INSTANCE = new ByModulatorOptimizationStrategy();
+
+    // when PathProcessorStrategy is present for withComputer() you need to ensure it always executes first because
+    // it does some manipulation to select().by(t) in some cases to turn it to select().map(t) in which case this
+    // strategy has nothing to do. if it were to occur first then that optimization wouldn't work as expected.
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>(Arrays.asList(
+            PathProcessorStrategy.class, IdentityRemovalStrategy.class));
+
+    private ByModulatorOptimizationStrategy() {
+    }
+
+    public static ByModulatorOptimizationStrategy instance() {
+        return INSTANCE;
+    }
+
+    private void optimizeByModulatingTraversal(final TraversalParent step, final Traversal.Admin<?, ?> traversal) {
+        if (traversal == null) return;
+        final List<Step> steps = traversal.asAdmin().getSteps();
+        if (steps.size() == 1) {
+            final Step singleStep = steps.get(0);
+            optimizeForStep(step, traversal, singleStep);
+        }
+    }
+
+    private void optimizeForStep(final TraversalParent step, final Traversal.Admin<?, ?> traversal, final Step singleStep) {
+        if (singleStep instanceof PropertiesStep) {
+            final PropertiesStep ps = (PropertiesStep) singleStep;
+            if (ps.getReturnType().equals(PropertyType.VALUE) && ps.getPropertyKeys().length == 1) {
+                step.replaceLocalChild(traversal, new ValueTraversal<>(ps.getPropertyKeys()[0]));
+            }
+        } else if (singleStep instanceof IdStep) {
+            step.replaceLocalChild(traversal, new TokenTraversal<>(T.id));
+        } else if (singleStep instanceof LabelStep) {
+            step.replaceLocalChild(traversal, new TokenTraversal<>(T.label));
+        } else if (singleStep instanceof PropertyKeyStep) {
+            step.replaceLocalChild(traversal, new TokenTraversal<>(T.key));
+        } else if (singleStep instanceof PropertyValueStep) {
+            step.replaceLocalChild(traversal, new TokenTraversal<>(T.value));
+        } else if (singleStep instanceof IdentityStep) {
+            step.replaceLocalChild(traversal, new IdentityTraversal<>());
+        }
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        final Step step = traversal.getParent().asStep();
+        if (step instanceof ByModulating && step instanceof TraversalParent) {
+            final TraversalParent byModulatingStep = (TraversalParent) step;
+            if (step instanceof Grouping) {
+                final Grouping grouping = (Grouping) step;
+                optimizeByModulatingTraversal(byModulatingStep, grouping.getKeyTraversal());
+
+                // the value by() needs different handling because by(Traversal) only equals by(String) or by(T)
+                // if the traversal does a fold().
+                final Traversal.Admin<?, ?> currentValueTraversal = grouping.getValueTraversal();
+                final List<Step> stepsInCurrentValueTraversal = currentValueTraversal.getSteps();
+                if (stepsInCurrentValueTraversal.size() == 1 && stepsInCurrentValueTraversal.get(0) instanceof IdentityStep)
+                    optimizeForStep(byModulatingStep, currentValueTraversal, stepsInCurrentValueTraversal.get(0));
+                else if (stepsInCurrentValueTraversal.size() == 2 && stepsInCurrentValueTraversal.get(1) instanceof FoldStep)
+                    optimizeForStep(byModulatingStep, currentValueTraversal, stepsInCurrentValueTraversal.get(0));
+
+            } else {
+                for (final Traversal.Admin<?, ?> byModulatingTraversal : byModulatingStep.getLocalChildren()) {
+                    optimizeByModulatingTraversal(byModulatingStep, byModulatingTraversal);
+                }
+            }
+        }
+    }
+
+    @Override
+    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
+        return PRIORS;
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
index e70e54a..75d55ad 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
@@ -125,7 +125,7 @@
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
         // using a hidden label marker to denote whether the traversal should not be processed by this strategy
-        if ((traversal.getParent() instanceof EmptyStep || traversal.getParent() instanceof VertexProgramStep) &&
+        if ((traversal.isRoot() || traversal.getParent() instanceof VertexProgramStep) &&
                 TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEP_CLASSES, traversal))
             TraversalHelper.applyTraversalRecursively(t -> t.getStartStep().addLabel(MARKER), traversal);
         if (traversal.getStartStep().getLabels().contains(MARKER)) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index f5f980f..bec170d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -96,7 +96,7 @@
                         step instanceof OrStep && InlineFilterStrategy.processOrStep((OrStep) step, traversal) ||
                         step instanceof AndStep && InlineFilterStrategy.processAndStep((AndStep) step, traversal);
             }
-            if (!changed && traversal.getParent() instanceof EmptyStep) {
+            if (!changed && traversal.isRoot()) {
                 final Iterator<MatchStep> matchStepIterator = TraversalHelper.getStepsOfClass(MatchStep.class, traversal).iterator();
                 while (!changed && matchStepIterator.hasNext()) {
                     if (InlineFilterStrategy.processMatchStep(matchStepIterator.next(), traversal))
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
index d370c38..62ade2b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
@@ -79,7 +79,7 @@
         // do not apply this strategy if there are lambdas as you can't introspect to know what path information the lambdas are using
         // do not apply this strategy if a PATH requirement step is being used (in the future, we can do PATH requirement lookhead to be more intelligent about its usage)
         // do not apply this strategy if a VertexProgramStep is present with LABELED_PATH requirements
-        if (traversal.getParent() instanceof EmptyStep &&
+        if (traversal.isRoot() &&
                 TraversalHelper.anyStepRecursively(step -> step instanceof LambdaHolder ||
                         step.getRequirements().contains(TraverserRequirement.PATH) ||
                         (step instanceof VertexProgramStep &&
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java
index a7c5a3a..9a9391b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java
@@ -18,12 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java
index ff1e835..2d49ecb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
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 642d17a..71999c5 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
@@ -34,11 +34,11 @@
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @example <pre>
- * __.out().map(v -> v.get().value("name"))           // throws an IllegalStateException
- * __.out().filter(v -> v.bulk() > 2)                 // throws an IllegalStateException
- * __.choose(v -> v.sack() == 1,out(),in())           // throws an IllegalStateException
- * __.select().by(v -> v.get().id())                  // throws an IllegalStateException
- * __.order().by(a,b -> a > b)                        // throws an IllegalStateException
+ * __.out().map(v -&gt; v.get().value("name"))           // throws an IllegalStateException
+ * __.out().filter(v -&gt; v.bulk() &gt; 2)              // throws an IllegalStateException
+ * __.choose(v -&gt; v.sack() == 1,out(),in())           // throws an IllegalStateException
+ * __.select().by(v -&gt; v.get().id())                  // throws an IllegalStateException
+ * __.order().by(a,b -&gt; a &gt; b)                        // throws an IllegalStateException
  * </pre>
  */
 public final class LambdaRestrictionStrategy extends AbstractTraversalStrategy<TraversalStrategy.VerificationStrategy> implements TraversalStrategy.VerificationStrategy {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
index 8fe6424..d764693 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Parameterizing;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java
index fc33c69..5a41c92 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java
@@ -51,8 +51,8 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!traversal.getStrategies().toList().contains(ComputerFinalizationStrategy.instance()) &&
-                !traversal.getStrategies().toList().contains(ComputerVerificationStrategy.instance())) {
+        if (!traversal.getStrategies().getStrategy(ComputerFinalizationStrategy.class).isPresent() &&
+                !traversal.getStrategies().getStrategy(ComputerVerificationStrategy.class).isPresent()) {
             if (!TraversalHelper.getStepsOfAssignableClass(VertexComputing.class, traversal).isEmpty())
                 throw new VerificationException("VertexComputing steps must be executed with a GraphComputer: " + TraversalHelper.getStepsOfAssignableClass(VertexComputing.class, traversal), traversal);
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
index 33c5520..57fa47a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
@@ -136,7 +136,7 @@
 
     protected final boolean equals(final B_O_S_SE_SL_Traverser other) {
         return super.equals(other) && other.loops == this.loops
-                && (this.loopName != null ? this.loopName.equals(other.loopName) : other.loopName == null)
+                && Objects.equals(this.loopName, other.loopName)
                 && !carriesUnmergeableSack();
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
index 658ba4b..e76016a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
@@ -27,6 +27,7 @@
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
 
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.Function;
 
@@ -203,16 +204,16 @@
 
     @Override
     public int hashCode() {
-        return this.t.hashCode();
+        return Objects.hashCode(this.t);
     }
 
     @Override
     public boolean equals(final Object object) {
-        return object instanceof AbstractTraverser && ((AbstractTraverser) object).get().equals(this.t);
+        return object instanceof AbstractTraverser && Objects.equals(this.t, ((AbstractTraverser) object).t);
     }
 
     @Override
     public String toString() {
-        return this.t.toString();
+        return Objects.toString(this.t);
     }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
index 3aeafbd..c68fdc6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
@@ -20,6 +20,7 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyPath;
@@ -30,12 +31,18 @@
 import java.util.function.Function;
 
 /**
+ * A {@link Traverser} with no bulk which effectively means that it will no longer be propagated through a
+ * {@link Traversal}.
+ *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
 public final class EmptyTraverser<T> implements Traverser<T>, Traverser.Admin<T> {
 
     private static final EmptyTraverser INSTANCE = new EmptyTraverser();
 
+    /**
+     * The empty {@link Traverser} instance.
+     */
     public static <R> EmptyTraverser<R> instance() {
         return INSTANCE;
     }
@@ -95,7 +102,7 @@
     }
 
     @Override
-    public void setBulk(long count) {
+    public void setBulk(final long count) {
 
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/TraverserSet.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/TraverserSet.java
index 52bf4d8..e25bbb1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/TraverserSet.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/TraverserSet.java
@@ -32,6 +32,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
+import java.util.Random;
 import java.util.Set;
 import java.util.Spliterator;
 
@@ -41,6 +42,7 @@
 public class TraverserSet<S> extends AbstractSet<Traverser.Admin<S>> implements Set<Traverser.Admin<S>>, Queue<Traverser.Admin<S>>, Serializable {
 
     private final Map<Traverser.Admin<S>, Traverser.Admin<S>> map = Collections.synchronizedMap(new LinkedHashMap<>());
+    private static final Random RAND = new Random();
 
     public TraverserSet() {
 
@@ -153,10 +155,10 @@
         list.forEach(traverser -> this.map.put(traverser, traverser));
     }
 
-    public void shuffle() {
+    public void shuffle(final Random random) {
         final List<Traverser.Admin<S>> list = new ArrayList<>(this.map.size());
         IteratorUtils.removeOnNext(this.map.values().iterator()).forEachRemaining(list::add);
-        Collections.shuffle(list);
+        Collections.shuffle(list, random);
         this.map.clear();
         list.forEach(traverser -> this.map.put(traverser, traverser));
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
index 87c585a..9cefeec 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
@@ -18,12 +18,14 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
+import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.VertexProgramStep;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
@@ -88,8 +90,6 @@
         steps.addAll(traversal.getSteps());
     }
 
-    // TODO: clean up unused or redundant constructors
-
     public DefaultTraversal() {
         this(EmptyGraph.instance(), TraversalStrategies.GlobalCache.getStrategies(EmptyGraph.class), new Bytecode());
     }
@@ -110,7 +110,7 @@
     @Override
     public TraverserGenerator getTraverserGenerator() {
         if (null == this.generator)
-            this.generator = (this.parent instanceof EmptyStep) ?
+            this.generator = isRoot() ?
                     DefaultTraverserGeneratorFactory.instance().getTraverserGenerator(this.getTraverserRequirements()) :
                     TraversalHelper.getRootTraversal(this).getTraverserGenerator();
         return this.generator;
@@ -120,34 +120,54 @@
     public void applyStrategies() throws IllegalStateException {
         if (this.locked) throw Traversal.Exceptions.traversalIsLocked();
         TraversalHelper.reIdSteps(this.stepPosition, this);
-        this.strategies.applyStrategies(this);
-        boolean hasGraph = null != this.graph;
-        for (int i = 0, j = this.steps.size(); i < j; i++) { // "foreach" can lead to ConcurrentModificationExceptions
-            final Step step = this.steps.get(i);
-            if (step instanceof TraversalParent) {
-                for (final Traversal.Admin<?, ?> globalChild : ((TraversalParent) step).getGlobalChildren()) {
-                    globalChild.setStrategies(this.strategies);
-                    globalChild.setSideEffects(this.sideEffects);
-                    if (hasGraph) globalChild.setGraph(this.graph);
-                    globalChild.applyStrategies();
-                }
-                for (final Traversal.Admin<?, ?> localChild : ((TraversalParent) step).getLocalChildren()) {
-                    localChild.setStrategies(this.strategies);
-                    localChild.setSideEffects(this.sideEffects);
-                    if (hasGraph) localChild.setGraph(this.graph);
-                    localChild.applyStrategies();
-                }
+        final boolean hasGraph = null != this.graph;
+
+        // we only want to apply strategies on the top-level step or if we got some graphcomputer stuff going on.
+        // seems like in that case, the "top-level" of the traversal is really held by the VertexProgramStep which
+        // needs to have strategies applied on "pure" copies of the traversal it is holding (i think). it further
+        // seems that we need three recursions over the traversal hierarchy to ensure everything "works", where
+        // strategy application requires top-level strategies and side-effects pushed into each child and then after
+        // application of the strategies we need to call applyStrategies() on all the children to ensure that their
+        // steps get reId'd and traverser requirements are set.
+        if (isRoot() || this.getParent() instanceof VertexProgramStep) {
+
+            // note that prior to applying strategies to children we used to set side-effects and strategies of all
+            // children to that of the parent. under this revised model of strategy application from TINKERPOP-1568
+            // it doesn't appear to be necessary to do that (at least from the perspective of the test suite). by,
+            // moving side-effect setting after actual recursive strategy application we save a loop and by
+            // consequence also fix a problem where strategies might reset something in sideeffects which seems to
+            // happen in TranslationStrategy.
+            final Iterator<TraversalStrategy<?>> strategyIterator = this.strategies.iterator();
+            while (strategyIterator.hasNext()) {
+                final TraversalStrategy<?> strategy = strategyIterator.next();
+                TraversalHelper.applyTraversalRecursively(strategy::apply, this);
             }
+
+            // don't need to re-apply strategies to "this" - leads to endless recursion in GraphComputer.
+            TraversalHelper.applyTraversalRecursively(t -> {
+                if (hasGraph) t.setGraph(this.graph);
+                if(!(t.isRoot()) && t != this && !t.isLocked()) {
+                    t.setStrategies(new DefaultTraversalStrategies());
+                    t.setSideEffects(this.sideEffects);
+                    t.applyStrategies();
+                }
+            }, this);
         }
+        
         this.finalEndStep = this.getEndStep();
+
         // finalize requirements
-        if (this.getParent() instanceof EmptyStep) {
-            this.requirements = null;
-            this.getTraverserRequirements();
+        if (this.isRoot()) {
+            resetTraverserRequirements();
         }
         this.locked = true;
     }
 
+    private void resetTraverserRequirements() {
+        this.requirements = null;
+        this.getTraverserRequirements();
+    }
+
     @Override
     public Set<TraverserRequirement> getTraverserRequirements() {
         if (null == this.requirements) {
@@ -185,7 +205,7 @@
                 return this.finalEndStep.next();
             }
         } catch (final FastNoSuchElementException e) {
-            throw this.parent instanceof EmptyStep ? new NoSuchElementException() : e;
+            throw this.isRoot() ? new NoSuchElementException() : e;
         }
     }
 
@@ -208,7 +228,7 @@
             // and release the resources.
             CloseableIterator.closeIterator(this);
 
-            throw this.parent instanceof EmptyStep ? new NoSuchElementException() : e;
+            throw this.isRoot() ? new NoSuchElementException() : e;
         }
     }
 
@@ -325,7 +345,7 @@
 
     @Override
     public void setParent(final TraversalParent step) {
-        this.parent = step;
+        this.parent = null == step ? EmptyStep.instance() : step;
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalStrategies.java
index 9667137..3e39d1b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalStrategies.java
@@ -18,13 +18,13 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Optional;
@@ -70,6 +70,11 @@
     }
 
     @Override
+    public Iterator<TraversalStrategy<?>> iterator() {
+        return this.traversalStrategies.iterator();
+    }
+
+    @Override
     public <T extends TraversalStrategy> Optional<T> getStrategy(final Class<T> traversalStrategyClass) {
         for (final TraversalStrategy<?> traversalStrategy : this.traversalStrategies) {
             if (traversalStrategyClass.isAssignableFrom(traversalStrategy.getClass()))
@@ -77,17 +82,6 @@
         }
         return Optional.empty();
     }
-    /**
-     * @deprecated As of release 3.3.10, not directly replaced as this mode of strategy application has not been
-     * utilized since early days of 3.x
-     */
-    @Override
-    @Deprecated
-    public void applyStrategies(final Traversal.Admin<?, ?> traversal) {
-        for (final TraversalStrategy<?> traversalStrategy : this.traversalStrategies) {
-            traversalStrategy.apply(traversal);
-        }
-    }
 
     @Override
     public DefaultTraversalStrategies clone() {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalStrategies.java
index 127df4d..f99d4bc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalStrategies.java
@@ -18,14 +18,11 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
-import org.apache.tinkerpop.gremlin.process.traversal.Translator;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserGeneratorFactory;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.DefaultTraverserGeneratorFactory;
 
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -43,9 +40,10 @@
         return Collections.emptyList();
     }
 
-    @Override
-    public void applyStrategies(final Traversal.Admin<?, ?> traversal) {
 
+    @Override
+    public Iterator<TraversalStrategy<?>> iterator() {
+        return toList().iterator();
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java
index 682f0d2..e28bcd4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.util.VertexProgramHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
index c4fa057..c793a95 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
@@ -51,8 +51,8 @@
 
     public TraversalExplanation(final Traversal.Admin<?, ?> traversal) {
         this.traversal = traversal.clone();
-        TraversalStrategies mutatingStrategies = new DefaultTraversalStrategies();
-        for (final TraversalStrategy strategy : this.traversal.getStrategies().toList()) {
+        final TraversalStrategies mutatingStrategies = new DefaultTraversalStrategies();
+        for (final TraversalStrategy strategy : this.traversal.getStrategies()) {
             final Traversal.Admin<?, ?> mutatingTraversal = this.traversal.clone();
             mutatingStrategies.addStrategies(strategy);
             mutatingTraversal.setStrategies(mutatingStrategies);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index 21319f5..4e7eb92 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -23,7 +23,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
@@ -98,7 +98,7 @@
 
     private static char isLocalStarGraph(final Traversal.Admin<?, ?> traversal, char state) {
         if (state == 'u' &&
-                (traversal instanceof ElementValueTraversal ||
+                (traversal instanceof ValueTraversal ||
                         (traversal instanceof TokenTraversal && !((TokenTraversal) traversal).getToken().equals(T.id))))
             return 'x';
         for (final Step step : traversal.getSteps()) {
@@ -116,7 +116,7 @@
                 }
             } else if (step instanceof TraversalParent) {
                 final char currState = state;
-                Set<Character> states = new HashSet<>();
+                final Set<Character> states = new HashSet<>();
                 for (final Traversal.Admin<?, ?> local : ((TraversalParent) step).getLocalChildren()) {
                     final char s = isLocalStarGraph(local, currState);
                     if ('x' == s) return 'x';
@@ -290,7 +290,7 @@
     }
 
     public static boolean isGlobalChild(Traversal.Admin<?, ?> traversal) {
-        while (!(traversal.getParent() instanceof EmptyStep)) {
+        while (!(traversal.isRoot())) {
             if (traversal.getParent().getLocalChildren().contains(traversal))
                 return false;
             traversal = traversal.getParent().asStep().getTraversal();
@@ -465,7 +465,11 @@
      */
     public static void applyTraversalRecursively(final Consumer<Traversal.Admin<?, ?>> consumer, final Traversal.Admin<?, ?> traversal) {
         consumer.accept(traversal);
-        for (final Step<?, ?> step : traversal.getSteps()) {
+
+        // we get accused of concurrentmodification if we try a for(Iterable)
+        final List<Step> steps = traversal.getSteps();
+        for (int ix = 0; ix < steps.size(); ix++) {
+            final Step step = steps.get(ix);
             if (step instanceof TraversalParent) {
                 for (final Traversal.Admin<?, ?> local : ((TraversalParent) step).getLocalChildren()) {
                     applyTraversalRecursively(consumer, local);
@@ -629,7 +633,7 @@
     }
 
     public static boolean onGraphComputer(Traversal.Admin<?, ?> traversal) {
-        while (!(traversal.getParent() instanceof EmptyStep)) {
+        while (!(traversal.isRoot())) {
             if (traversal.getParent() instanceof TraversalVertexProgramStep)
                 return true;
             traversal = traversal.getParent().asStep().getTraversal();
@@ -683,7 +687,7 @@
         childTraversal.setStrategies(parentTraversal.getStrategies());
         childTraversal.setSideEffects(parentTraversal.getSideEffects());
         parentTraversal.getGraph().ifPresent(childTraversal::setGraph);
-        for (final TraversalStrategy<?> strategy : parentTraversal.getStrategies().toList()) {
+        for (final TraversalStrategy<?> strategy : parentTraversal.getStrategies()) {
             strategy.apply(childTraversal);
             if (null != stopAfterStrategy && stopAfterStrategy.isInstance(strategy))
                 break;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
index 09c362e..bbdf701 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
@@ -24,6 +24,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -62,6 +63,15 @@
         this.traversals.add(traversal);
     }
 
+    public void replaceTraversal(final Traversal.Admin<A, B> oldTraversal, final Traversal.Admin<A, B> newTraversal) {
+        for (int i = 0, j = this.traversals.size(); i < j; i++) {
+            if (Objects.equals(oldTraversal, this.traversals.get(i))) {
+                this.traversals.set(i, newTraversal);
+                break;
+            }
+        }
+    }
+
     public List<Traversal.Admin<A, B>> getTraversals() {
         return Collections.unmodifiableList(this.traversals);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Direction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Direction.java
index d412e24..11db13d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Direction.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Direction.java
@@ -23,7 +23,7 @@
  * {@link Edge}. For example:
  * <p/>
  * <pre>
- * gremlin--knows-->rexster
+ * gremlin--knows--&gt;rexster
  * </pre>
  * is an {@link Direction#OUT} {@link Edge} for Gremlin and an {@link Direction#IN} edge for Rexster. Moreover, given
  * that {@link Edge}, Gremlin is the {@link Direction#OUT} {@link Vertex} and Rexster is the {@link Direction#IN}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Edge.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Edge.java
index 6df38d2..fba9ae7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Edge.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Edge.java
@@ -29,7 +29,7 @@
  * <p/>
  * Diagrammatically:
  * <pre>
- * outVertex ---label---> inVertex.
+ * outVertex ---label---&gt; inVertex.
  * </pre>
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
index 5dd4ff5..b165cbd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -323,8 +323,8 @@
     public Variables variables();
 
     /**
-     * Get the {@code Configuration} associated with the construction of this graph.  Whatever configuration was
-     * passed to {@link GraphFactory#open(Configuration)} is what should be returned by this method.
+     * Get the {@code Configuration} associated with the construction of this graph. Whatever configuration was passed
+     * to {@link GraphFactory#open(Configuration)} is what should be returned by this method.
      *
      * @return the configuration used during graph construction.
      */
@@ -686,6 +686,17 @@
             public static final String FEATURE_ANY_IDS = "AnyIds";
             public static final String FEATURE_ADD_PROPERTY = "AddProperty";
             public static final String FEATURE_REMOVE_PROPERTY = "RemoveProperty";
+            public static final String FEATURE_NULL_PROPERTY_VALUES = "NullPropertyValues";
+
+            /**
+             * Determines if an {@link Element} allows properties with {@code null} property values. In the event that
+             * this value is {@code false}, the underlying graph must treat {@code null} as an indication to remove
+             * the property.
+             */
+            @FeatureDescriptor(name = FEATURE_NULL_PROPERTY_VALUES)
+            public default boolean supportsNullPropertyValues() {
+                return true;
+            }
 
             /**
              * Determines if an {@link Element} allows properties to be added.  This feature is set independently from
@@ -820,6 +831,15 @@
             public static final String FEATURE_UUID_IDS = "UuidIds";
             public static final String FEATURE_CUSTOM_IDS = "CustomIds";
             public static final String FEATURE_ANY_IDS = "AnyIds";
+            public static final String FEATURE_NULL_PROPERTY_VALUES = "NullPropertyValues";
+
+            /**
+             * Determines if meta-properties allow for {@code null} property values.
+             */
+            @FeatureDescriptor(name = FEATURE_NULL_PROPERTY_VALUES)
+            public default boolean supportsNullPropertyValues() {
+                return true;
+            }
 
             /**
              * Determines if a {@link VertexProperty} allows properties to be removed.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Property.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Property.java
index 5b67f07..eac8355 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Property.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Property.java
@@ -139,10 +139,6 @@
             return new IllegalArgumentException("Property key can not be null");
         }
 
-        public static IllegalArgumentException propertyValueCanNotBeNull() {
-            return new IllegalArgumentException("Property value can not be null");
-        }
-
         public static IllegalArgumentException propertyKeyCanNotBeAHiddenKey(final String key) {
             return new IllegalArgumentException("Property key can not be a hidden key: " + key);
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Vertex.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Vertex.java
index 7b0d2a5..a972c72 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Vertex.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Vertex.java
@@ -29,7 +29,7 @@
  * <p/>
  * Diagrammatically:
  * <pre>
- * ---inEdges---> vertex ---outEdges--->.
+ * ---inEdges---&gt; vertex ---outEdges---&gt;.
  * </pre>
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
index 39aeaaf..ced0088 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
@@ -46,7 +46,9 @@
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.javatuples.Pair;
 
 import java.io.IOException;
 import java.lang.reflect.Modifier;
@@ -220,12 +222,27 @@
         /**
          * Provides a way to resolve the type serializer to use when there isn't any direct match.
          */
-        public Builder withFallbackResolver(Function<Class<?>, TypeSerializer<?>> fallbackResolver) {
+        public Builder withFallbackResolver(final Function<Class<?>, TypeSerializer<?>> fallbackResolver) {
             this.fallbackResolver = fallbackResolver;
             return this;
         }
 
         /**
+         * Add {@link CustomTypeSerializer} by way of an {@link IoRegistry}. The registry entries should be bound to
+         * {@link GraphBinaryIo}.
+         */
+        public Builder addRegistry(final IoRegistry registry) {
+            if (null == registry) throw new IllegalArgumentException("The registry cannot be null");
+
+            final List<Pair<Class, CustomTypeSerializer>> classSerializers = registry.find(GraphBinaryIo.class, CustomTypeSerializer.class);
+            for (Pair<Class,CustomTypeSerializer> cs : classSerializers) {
+                addCustomType(cs.getValue0(), cs.getValue1());
+            }
+
+            return this;
+        }
+
+        /**
          * Creates a new {@link TypeSerializerRegistry} instance based on the serializers added.
          */
         public TypeSerializerRegistry create() {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java
index d627f18..f107b8a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.binary.types;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalStrategySerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalStrategySerializer.java
index 38ea9c9..256e25d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalStrategySerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalStrategySerializer.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.binary.types;
 
-import org.apache.commons.configuration.ConfigurationConverter;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.ConfigurationConverter;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriter.java
index 3991e4e..5c70e99 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriter.java
@@ -24,7 +24,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
index 30112f9..bfa239b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
@@ -198,7 +198,7 @@
         private boolean loadCustomModules = false;
         private boolean normalize = false;
         private List<IoRegistry> registries = new ArrayList<>();
-        private GraphSONVersion version = GraphSONVersion.V2_0;
+        private GraphSONVersion version = GraphSONVersion.V3_0;
 
         /**
          * GraphSON 2.0/3.0 should have types activated by default (3.0 does not have a typeless option), and 1.0
@@ -219,7 +219,7 @@
         }
 
         /**
-         * Set the version of GraphSON to use. The default is {@link GraphSONVersion#V2_0}.
+         * Set the version of GraphSON to use. The default is {@link GraphSONVersion#V3_0}.
          */
         public Builder version(final GraphSONVersion version) {
             this.version = version;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index cb0eeaf..f51b34c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -41,9 +41,11 @@
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy;
@@ -185,9 +187,12 @@
                             HaltedTraverserStrategy.class,
                             PartitionStrategy.class,
                             SubgraphStrategy.class,
+                            SeedStrategy.class,
                             LazyBarrierStrategy.class,
                             MatchAlgorithmStrategy.class,
                             AdjacentToIncidentStrategy.class,
+                            ByModulatorOptimizationStrategy.class,
+                            CountStrategy.class,
                             FilterRankingStrategy.class,
                             IdentityRemovalStrategy.class,
                             IncidentToAdjacentStrategy.class,
@@ -197,7 +202,6 @@
                             OptionsStrategy.class,
                             PathProcessorStrategy.class,
                             PathRetractionStrategy.class,
-                            CountStrategy.class,
                             RepeatUnrollStrategy.class,
                             ComputerVerificationStrategy.class,
                             LambdaRestrictionStrategy.class,
@@ -311,9 +315,12 @@
                     HaltedTraverserStrategy.class,
                     PartitionStrategy.class,
                     SubgraphStrategy.class,
+                    SeedStrategy.class,
                     LazyBarrierStrategy.class,
                     MatchAlgorithmStrategy.class,
                     AdjacentToIncidentStrategy.class,
+                    ByModulatorOptimizationStrategy.class,
+                    CountStrategy.class,
                     FilterRankingStrategy.class,
                     IdentityRemovalStrategy.class,
                     IncidentToAdjacentStrategy.class,
@@ -323,7 +330,6 @@
                     OptionsStrategy.class,
                     PathProcessorStrategy.class,
                     PathRetractionStrategy.class,
-                    CountStrategy.class,
                     RepeatUnrollStrategy.class,
                     ComputerVerificationStrategy.class,
                     LambdaRestrictionStrategy.class,
@@ -417,9 +423,12 @@
                             HaltedTraverserStrategy.class,
                             PartitionStrategy.class,
                             SubgraphStrategy.class,
+                            SeedStrategy.class,
                             LazyBarrierStrategy.class,
                             MatchAlgorithmStrategy.class,
                             AdjacentToIncidentStrategy.class,
+                            ByModulatorOptimizationStrategy.class,
+                            CountStrategy.class,
                             FilterRankingStrategy.class,
                             IdentityRemovalStrategy.class,
                             IncidentToAdjacentStrategy.class,
@@ -429,7 +438,6 @@
                             OptionsStrategy.class,
                             PathProcessorStrategy.class,
                             PathRetractionStrategy.class,
-                            CountStrategy.class,
                             RepeatUnrollStrategy.class,
                             ComputerVerificationStrategy.class,
                             LambdaRestrictionStrategy.class,
@@ -533,9 +541,12 @@
                     HaltedTraverserStrategy.class,
                     PartitionStrategy.class,
                     SubgraphStrategy.class,
+                    SeedStrategy.class,
                     LazyBarrierStrategy.class,
                     MatchAlgorithmStrategy.class,
                     AdjacentToIncidentStrategy.class,
+                    ByModulatorOptimizationStrategy.class,
+                    CountStrategy.class,
                     FilterRankingStrategy.class,
                     IdentityRemovalStrategy.class,
                     IncidentToAdjacentStrategy.class,
@@ -545,7 +556,6 @@
                     OptionsStrategy.class,
                     PathProcessorStrategy.class,
                     PathRetractionStrategy.class,
-                    CountStrategy.class,
                     RepeatUnrollStrategy.class,
                     ComputerVerificationStrategy.class,
                     LambdaRestrictionStrategy.class,
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/LegacyGraphSONReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/LegacyGraphSONReader.java
index 3125e73..7432e22 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/LegacyGraphSONReader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/LegacyGraphSONReader.java
@@ -205,7 +205,6 @@
         private boolean loadCustomModules = false;
         private List<SimpleModule> customModules = new ArrayList<>();
         private long batchSize = 10000;
-        private boolean embedTypes = false;
 
         private Builder() {
         }
@@ -236,9 +235,12 @@
         }
 
         public LegacyGraphSONReader create() {
-            final GraphSONMapper.Builder builder = GraphSONMapper.build();
+            // not sure why there is specific need for V2 here with "no types" as we don't even need TP3 GraphSON
+            // at all. Seems like a standard Jackson ObjectMapper would have worked fine, but rather than change
+            // this ancient class at this stage we'll just stick to what is there.
+            final GraphSONMapper.Builder builder = GraphSONMapper.build().version(GraphSONVersion.V2_0);
             customModules.forEach(builder::addCustomModule);
-            final GraphSONMapper mapper = builder.typeInfo(embedTypes ? TypeInfo.PARTIAL_TYPES : TypeInfo.NO_TYPES)
+            final GraphSONMapper mapper = builder.typeInfo(TypeInfo.NO_TYPES)
                     .loadCustomModules(loadCustomModules).create();
             return new LegacyGraphSONReader(mapper.createMapper(), batchSize);
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
index 5297733..c66a1e8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
-import org.apache.commons.configuration.ConfigurationConverter;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.ConfigurationConverter;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
index 5132ebd..cc224cb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
-import org.apache.commons.configuration.ConfigurationConverter;
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.ConfigurationConverter;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 3138488..eb9566e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -50,9 +50,11 @@
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy;
@@ -333,10 +335,13 @@
             add(GryoTypeReg.of(HaltedTraverserStrategy.class, 139));
             add(GryoTypeReg.of(PartitionStrategy.class, 140, new JavaSerializer()));
             add(GryoTypeReg.of(SubgraphStrategy.class, 141, new JavaSerializer()));
+            add(GryoTypeReg.of(SeedStrategy.class, 192, new JavaSerializer()));          // ***LAST ID***
             add(GryoTypeReg.of(VertexProgramStrategy.class, 142, new JavaSerializer()));
             add(GryoTypeReg.of(MatchAlgorithmStrategy.class, 143));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 144));
             add(GryoTypeReg.of(AdjacentToIncidentStrategy.class, 145));
+            add(GryoTypeReg.of(ByModulatorOptimizationStrategy.class, 191));
+            add(GryoTypeReg.of(CountStrategy.class, 155));
             add(GryoTypeReg.of(FilterRankingStrategy.class, 146));
             add(GryoTypeReg.of(IdentityRemovalStrategy.class, 147));
             add(GryoTypeReg.of(IncidentToAdjacentStrategy.class, 148));
@@ -347,7 +352,6 @@
             add(GryoTypeReg.of(OptionsStrategy.class, 187, new JavaSerializer()));
             add(GryoTypeReg.of(PathProcessorStrategy.class, 153));
             add(GryoTypeReg.of(PathRetractionStrategy.class, 154));
-            add(GryoTypeReg.of(CountStrategy.class, 155));
             add(GryoTypeReg.of(RepeatUnrollStrategy.class, 156));
             add(GryoTypeReg.of(GraphFilterStrategy.class, 157));
             add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));
@@ -356,7 +360,7 @@
             add(GryoTypeReg.of(MatchStep.CountMatchAlgorithm.class, 160));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 164));
             add(GryoTypeReg.of(EdgeLabelVerificationStrategy.class, 189));
-            add(GryoTypeReg.of(ReservedKeysVerificationStrategy.class, 190));   // ***LAST ID***
+            add(GryoTypeReg.of(ReservedKeysVerificationStrategy.class, 190));
 
             add(GryoTypeReg.of(TraverserSet.class, 58));
             add(GryoTypeReg.of(Tree.class, 61));
@@ -570,10 +574,13 @@
             add(GryoTypeReg.of(HaltedTraverserStrategy.class, 139));
             add(GryoTypeReg.of(PartitionStrategy.class, 140, new JavaSerializer()));
             add(GryoTypeReg.of(SubgraphStrategy.class, 141, new JavaSerializer()));
+            add(GryoTypeReg.of(SeedStrategy.class, 192, new JavaSerializer()));          // ***LAST ID***
             add(GryoTypeReg.of(VertexProgramStrategy.class, 142, new JavaSerializer()));
             add(GryoTypeReg.of(MatchAlgorithmStrategy.class, 143));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 144));
             add(GryoTypeReg.of(AdjacentToIncidentStrategy.class, 145));
+            add(GryoTypeReg.of(ByModulatorOptimizationStrategy.class, 191));
+            add(GryoTypeReg.of(CountStrategy.class, 155));
             add(GryoTypeReg.of(FilterRankingStrategy.class, 146));
             add(GryoTypeReg.of(IdentityRemovalStrategy.class, 147));
             add(GryoTypeReg.of(IncidentToAdjacentStrategy.class, 148));
@@ -584,7 +591,6 @@
             add(GryoTypeReg.of(OptionsStrategy.class, 187, new JavaSerializer()));
             add(GryoTypeReg.of(PathProcessorStrategy.class, 153));
             add(GryoTypeReg.of(PathRetractionStrategy.class, 154));
-            add(GryoTypeReg.of(CountStrategy.class, 155));
             add(GryoTypeReg.of(RepeatUnrollStrategy.class, 156));
             add(GryoTypeReg.of(GraphFilterStrategy.class, 157));
             add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));
@@ -593,7 +599,7 @@
             add(GryoTypeReg.of(MatchStep.CountMatchAlgorithm.class, 160));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 167));
             add(GryoTypeReg.of(EdgeLabelVerificationStrategy.class, 189));
-            add(GryoTypeReg.of(ReservedKeysVerificationStrategy.class, 190));   // ***LAST ID***
+            add(GryoTypeReg.of(ReservedKeysVerificationStrategy.class, 190));
             // skip 171, 172 to sync with the 3.3.x
             add(GryoTypeReg.of(IndexedTraverserSet.VertexIndexedTraverserSet.class, 173));
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimService.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimService.java
index 4422e1b..6e7baff 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimService.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimService.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 
 import java.io.InputStream;
 import java.io.OutputStream;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimServiceLoader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimServiceLoader.java
index 97e6d16..3179905 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimServiceLoader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/kryoshim/KryoShimServiceLoader.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationUtils;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ConfigurationUtils;
 import org.apache.tinkerpop.gremlin.util.SystemUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/util/IoRegistryHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/util/IoRegistryHelper.java
index f878cfc..1db2197 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/util/IoRegistryHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/util/IoRegistryHelper.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.structure.io.util;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 
 import java.lang.reflect.Method;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
index 0ef7a63..6ba5b29 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
@@ -88,13 +88,11 @@
      * a pre-condition check prior to setting a property.
      *
      * @param key   the key of the property
-     * @param value the value of the property
+     * @param value the value of the property\
      * @throws IllegalArgumentException whether the key/value pair is legal and if not, a clear reason exception
      *                                  message is provided
      */
     public static void validateProperty(final String key, final Object value) throws IllegalArgumentException {
-        if (null == value)
-            throw Property.Exceptions.propertyValueCanNotBeNull();
         if (null == key)
             throw Property.Exceptions.propertyKeyCanNotBeNull();
         if (key.isEmpty())
@@ -105,7 +103,7 @@
 
     /**
      * Determines whether a list of key/values are legal, ensuring that there are an even number of values submitted
-     * and that the key values in the list of arguments are {@link String} or {@link Element} objects.
+     * and that the keys in the list of arguments are {@link String} or {@link T} objects.
      *
      * @param propertyKeyValues a list of key/value pairs
      * @throws IllegalArgumentException if something in the pairs is illegal
@@ -116,10 +114,6 @@
         for (int i = 0; i < propertyKeyValues.length; i = i + 2) {
             if (!(propertyKeyValues[i] instanceof String) && !(propertyKeyValues[i] instanceof T))
                 throw Element.Exceptions.providedKeyValuesMustHaveALegalKeyOnEvenIndices();
-
-            if (null == propertyKeyValues[i + 1]) {
-                throw Property.Exceptions.propertyValueCanNotBeNull();
-            }
         }
     }
 
@@ -128,12 +122,11 @@
      *
      * @param keyValues a list of key/value pairs
      * @return the value associated with {@link T#id}
-     * @throws NullPointerException if the value for the {@link T#id} key is {@code null}
      */
     public static Optional<Object> getIdValue(final Object... keyValues) {
         for (int i = 0; i < keyValues.length; i = i + 2) {
             if (keyValues[i].equals(T.id))
-                return Optional.of(keyValues[i + 1]);
+                return Optional.ofNullable(keyValues[i + 1]);
         }
         return Optional.empty();
     }
@@ -280,16 +273,24 @@
         if (null == element)
             throw Graph.Exceptions.argumentCanNotBeNull("element");
 
+        final boolean allowNullPropertyValues = element instanceof Vertex ?
+                element.graph().features().vertex().supportsNullPropertyValues() : element instanceof Edge ?
+                element.graph().features().edge().supportsNullPropertyValues() :
+                element.graph().features().vertex().properties().supportsNullPropertyValues();
+
         for (int i = 0; i < propertyKeyValues.length; i = i + 2) {
             if (!propertyKeyValues[i].equals(T.id) && !propertyKeyValues[i].equals(T.label))
-                element.property((String) propertyKeyValues[i], propertyKeyValues[i + 1]);
+                if (!allowNullPropertyValues && null == propertyKeyValues[i + 1])
+                    element.properties(((String) propertyKeyValues[i])).forEachRemaining(Property::remove);
+                else
+                    element.property((String) propertyKeyValues[i], propertyKeyValues[i + 1]);
         }
     }
 
     /**
-     * Assign key/value pairs as properties to an {@link Vertex}.  If the value of {@link T#id} or
-     * {@link T#label} is in the set of pairs, then they are ignored.
-     * The {@link VertexProperty.Cardinality} of the key is determined from the {@link Graph.Features.VertexFeatures}.
+     * Assign key/value pairs as properties to an {@link Vertex}.  If the value of {@link T#id} or {@link T#label} is
+     * in the set of pairs, then they are ignored. The {@link VertexProperty.Cardinality} of the key is determined from
+     * the {@link Graph.Features.VertexFeatures}.
      *
      * @param vertex            the graph vertex to assign the {@code propertyKeyValues}
      * @param propertyKeyValues the key/value pairs to assign to the {@code element}
@@ -300,15 +301,20 @@
         if (null == vertex)
             throw Graph.Exceptions.argumentCanNotBeNull("vertex");
 
+        final boolean allowNullPropertyValues = vertex.graph().features().vertex().supportsNullPropertyValues();
+
         for (int i = 0; i < propertyKeyValues.length; i = i + 2) {
             if (!propertyKeyValues[i].equals(T.id) && !propertyKeyValues[i].equals(T.label))
-                vertex.property(vertex.graph().features().vertex().getCardinality((String) propertyKeyValues[i]), (String) propertyKeyValues[i], propertyKeyValues[i + 1]);
+                if (!allowNullPropertyValues && null == propertyKeyValues[i + 1])
+                    vertex.properties(((String) propertyKeyValues[i])).forEachRemaining(VertexProperty::remove);
+                else
+                    vertex.property(vertex.graph().features().vertex().getCardinality((String) propertyKeyValues[i]), (String) propertyKeyValues[i], propertyKeyValues[i + 1]);
         }
     }
 
     /**
-     * Assign key/value pairs as properties to a {@link Vertex}.
-     * If the value of {@link T#id} or {@link T#label} is in the set of pairs, then they are ignored.
+     * Assign key/value pairs as properties to a {@link Vertex}. If the value of {@link T#id} or {@link T#label} is
+     * in the set of pairs, then they are ignored.
      *
      * @param vertex            the vertex to attach the properties to
      * @param cardinality       the cardinality of the key value pair settings
@@ -316,18 +322,24 @@
      * @throws ClassCastException       if the value of the key is not a {@link String}
      * @throws IllegalArgumentException if the value of {@code element} is null
      */
-    public static void attachProperties(final Vertex vertex, final VertexProperty.Cardinality cardinality, final Object... propertyKeyValues) {
+    public static void attachProperties(final Vertex vertex, final VertexProperty.Cardinality cardinality,
+                                        final Object... propertyKeyValues) {
         if (null == vertex)
             throw Graph.Exceptions.argumentCanNotBeNull("vertex");
 
+        final boolean allowNullPropertyValues = vertex.graph().features().vertex().supportsNullPropertyValues();
+
         for (int i = 0; i < propertyKeyValues.length; i = i + 2) {
             if (!propertyKeyValues[i].equals(T.id) && !propertyKeyValues[i].equals(T.label))
-                vertex.property(cardinality, (String) propertyKeyValues[i], propertyKeyValues[i + 1]);
+                if (!allowNullPropertyValues && null == propertyKeyValues[i + 1])
+                    vertex.properties(((String) propertyKeyValues[i])).forEachRemaining(VertexProperty::remove);
+                else
+                    vertex.property(cardinality, (String) propertyKeyValues[i], propertyKeyValues[i + 1]);
         }
     }
 
     /**
-     * This is a helper method for dealing with vertex property cardinality and typically used in {@link Vertex#property(org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality, String, Object, Object...)}.
+     * This is a helper method for dealing with vertex property cardinality and typically used in {@link Vertex#property(VertexProperty.Cardinality, String, Object, Object...)}.
      * If the cardinality is list, simply return {@link Optional#empty}.
      * If the cardinality is single, delete all existing properties of the provided key and return {@link Optional#empty}.
      * If the cardinality is set, find one that has the same key/value and attached the properties to it and return it. Else, if no equal value is found, return {@link Optional#empty}.
@@ -340,7 +352,9 @@
      * @param <V>         the type of the vertex property value
      * @return a vertex property if it has been found in set with equal value
      */
-    public static <V> Optional<VertexProperty<V>> stageVertexProperty(final Vertex vertex, final VertexProperty.Cardinality cardinality, final String key, final V value, final Object... keyValues) {
+    public static <V> Optional<VertexProperty<V>> stageVertexProperty(final Vertex vertex,
+                                                                      final VertexProperty.Cardinality cardinality,
+                                                                      final String key, final V value, final Object... keyValues) {
         if (cardinality.equals(VertexProperty.Cardinality.single))
             vertex.properties(key).forEachRemaining(VertexProperty::remove);
         else if (cardinality.equals(VertexProperty.Cardinality.set)) {
@@ -387,7 +401,8 @@
 
     /**
      * A standard method for determining if two {@link Element} objects are equal. This method should be used by any
-     * {@link Object#equals(Object)} implementation to ensure consistent behavior. This method is used for Vertex, Edge, and VertexProperty.
+     * {@link Object#equals(Object)} implementation to ensure consistent behavior. This method is used for Vertex,
+     * Edge, and VertexProperty.
      *
      * @param a The first {@link Element}
      * @param b The second {@link Element} (as an {@link Object})
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactory.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactory.java
index 61808aa..b670034 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactory.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactory.java
@@ -18,13 +18,16 @@
  */
 package org.apache.tinkerpop.gremlin.structure.util;
 
+import org.apache.commons.configuration2.ConfigurationUtils;
+import org.apache.commons.configuration2.FileBasedConfiguration;
+import org.apache.commons.configuration2.YAMLConfiguration;
+import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
+import org.apache.commons.configuration2.builder.fluent.Parameters;
 import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.util.config.YamlConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.MapConfiguration;
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.configuration2.MapConfiguration;
 
 import java.io.File;
 import java.util.Map;
@@ -106,8 +109,9 @@
     /**
      * Open a graph. See each {@link Graph} instance for its configuration options.
      *
-     * @param configuration A {@code Map} based configuration that will be converted to an {@code Configuration} object
-     *                      via {@code MapConfiguration} and passed to the appropriate overload.
+     * @param configuration A {@code Map} based configuration that will be converted to an
+     *                      {@code Configuration} object via {@code MapConfiguration} and passed to the appropriate
+     *                      overload.
      * @return A Graph instance.
      */
     public static Graph open(final Map configuration) {
@@ -115,7 +119,7 @@
         return open(new MapConfiguration(configuration));
     }
 
-    private static Configuration getConfiguration(final File configurationFile) {
+    private static org.apache.commons.configuration2.Configuration getConfiguration(final File configurationFile) {
         if (!configurationFile.isFile())
             throw new IllegalArgumentException(String.format("The location configuration must resolve to a file and [%s] does not", configurationFile));
 
@@ -123,18 +127,29 @@
             final String fileName = configurationFile.getName();
             final String fileExtension = fileName.substring(fileName.lastIndexOf('.') + 1);
 
+            final Configuration conf;
+            final Configurations configs = new Configurations();
+
             switch (fileExtension) {
                 case "yml":
                 case "yaml":
-                    final YamlConfiguration config = new YamlConfiguration();
-                    config.load(configurationFile);
-                    return config;
+                    final Parameters params = new Parameters();
+                    final FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
+                            new FileBasedConfigurationBuilder<FileBasedConfiguration>(YAMLConfiguration.class).
+                                    configure(params.fileBased().setFile(configurationFile));
+
+                    final org.apache.commons.configuration2.Configuration copy = new org.apache.commons.configuration2.BaseConfiguration();
+                    ConfigurationUtils.copy(builder.configure(params.fileBased().setFile(configurationFile)).getConfiguration(), copy);
+                    conf = copy;
+                    break;
                 case "xml":
-                    return new XMLConfiguration(configurationFile);
+                    conf = configs.xml(configurationFile);
+                    break;
                 default:
-                    return new PropertiesConfiguration(configurationFile);
+                    conf = configs.properties(configurationFile);
             }
-        } catch (final ConfigurationException e) {
+            return conf;
+        } catch (ConfigurationException e) {
             throw new IllegalArgumentException(String.format("Could not load configuration at: %s", configurationFile), e);
         }
     }
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 814bc09..3fc3591 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
@@ -49,6 +49,7 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.function.Predicate;
@@ -255,6 +256,6 @@
     }
 
     public static String pathString(final Path path) {
-        return PATH + L_BRACKET + String.join(", ", IteratorUtils.map(path, Object::toString)) + R_BRACKET;
+        return PATH + L_BRACKET + String.join(", ", IteratorUtils.map(path, Objects::toString)) + R_BRACKET;
     }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/empty/EmptyGraph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/empty/EmptyGraph.java
index fa10c99..7d4e836 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/empty/EmptyGraph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/empty/EmptyGraph.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.util.empty;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
index aa87d11..3bcdb7d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure.util.star;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
 import org.apache.tinkerpop.gremlin.structure.Direction;
@@ -224,14 +224,6 @@
         return starGraph;
     }
 
-    /**
-     * @deprecated As of release 3.3.5, replaced by {@link #build()}.
-     */
-    @Deprecated
-    public static StarGraph.Builder builder() {
-        return build();
-    }
-
     public static StarGraph.Builder build() {
         return new Builder();
     }
@@ -244,7 +236,7 @@
         private boolean compareIdsUsingStrings = true;
 
         /**
-         * Call {@link #builder()} to instantiate
+         * Call {@link #build()} to instantiate
          */
         private Builder() { }
 
@@ -270,9 +262,6 @@
          * However, if this builder method is never invoked, then the builder is guaranteed to use
          * whatever default value StarGraph's other public constructors or factory methods would use.
          * This option exists solely for performance tuning in specialized use-cases.
-         *
-         * @param b
-         * @return
          */
         public Builder compareIdsUsingStrings(final boolean b) {
             this.compareIdsUsingStrings = b;
@@ -281,15 +270,6 @@
 
         /**
          * @return a new StarGraph
-         * @deprecated As of release 3.3.5, replaced by {@link #create()}.
-         */
-        @Deprecated
-        public StarGraph build() {
-            return create();
-        }
-
-        /**
-         * @return a new StarGraph
          */
         public StarGraph create() {
             return new StarGraph(internStrings, compareIdsUsingStrings);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/SystemUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/SystemUtil.java
index bc2c5ff..be6c813 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/SystemUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/SystemUtil.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.util;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 
 import java.util.Map;
 
@@ -43,7 +43,6 @@
      */
     public static Configuration getSystemPropertiesConfiguration(final String prefix, final boolean trimPrefix) {
         final BaseConfiguration apacheConfiguration = new BaseConfiguration();
-        apacheConfiguration.setDelimiterParsingDisabled(true);
         for (final Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
             final String key = entry.getKey().toString();
             final Object value = entry.getValue();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TestSupport.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TestSupport.java
index 66820d6..0f89200 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TestSupport.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TestSupport.java
@@ -19,8 +19,6 @@
 package org.apache.tinkerpop.gremlin.util;
 
 import org.apache.tinkerpop.gremlin.structure.io.Storage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -28,7 +26,6 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.util.List;
-import java.util.Random;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -160,7 +157,7 @@
 
     /**
      * Copies a file stored as part of a resource to the file system in the path returned from
-     * {@link TestHelper#makeTestDataPath} in a subdirectory called {@code temp/resources}.
+     * {@link TestSupport#makeTestDataPath} in a subdirectory called {@code temp/resources}.
      */
     public static File generateTempFileFromResource(final Class graphClass, final Class resourceClass,
                                                     final String resourceName, final String extension, final boolean overwrite) throws IOException {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/config/YamlConfiguration.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/config/YamlConfiguration.java
deleted file mode 100644
index 1ccdb41..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/config/YamlConfiguration.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.util.config;
-
-import org.apache.commons.configuration.AbstractHierarchicalFileConfiguration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.tree.ConfigurationNode;
-import org.yaml.snakeyaml.DumperOptions;
-import org.yaml.snakeyaml.Yaml;
-
-import java.io.Reader;
-import java.io.Writer;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * Apache Commons Configuration object for YAML.  Adapted from code originally found here:
- * https://github.com/PEXPlugins/SimpleConfigs
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class YamlConfiguration extends AbstractHierarchicalFileConfiguration {
-    public final static int DEFAULT_IDENT = 4;
-    private final DumperOptions yamlOptions = new DumperOptions();
-    private final Yaml yaml = new Yaml(yamlOptions);
-    private boolean xmlCompatibility = true;
-
-    public YamlConfiguration() {
-        super();
-        initialize();
-    }
-
-    private void initialize() {
-        yamlOptions.setIndent(DEFAULT_IDENT);
-        yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
-    }
-
-    public void setXmlCompatibility(final boolean xmlCompatibility) {
-        this.xmlCompatibility = xmlCompatibility;
-    }
-
-    @Override
-    public void load(final Reader in) throws ConfigurationException {
-        try {
-            this.loadHierarchy(this.getRootNode(), yaml.load(in));
-        } catch (Throwable e) {
-            throw new ConfigurationException("Failed to load configuration: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public void save(final Writer out) throws ConfigurationException {
-        try {
-            yaml.dump(this.saveHierarchy(this.getRootNode()), out);
-        } catch (Throwable e) {
-            throw new ConfigurationException("Failed to save configuration: " + e.getMessage(), e);
-        }
-    }
-
-    protected void loadHierarchy(final ConfigurationNode parentNode, final Object obj) {
-        final String parentName = parentNode.getName();
-        if (obj instanceof Map<?, ?>) {
-            for (Map.Entry<String, Object> entry : ((Map<String, Object>) obj).entrySet()) {
-                final Node childNode = new Node(entry.getKey());
-
-                // if parent node is look like "tableS", "userS" or "groupS"
-                if (this.xmlCompatibility && parentName != null && parentName.endsWith("s")) {
-                    //this is done to have "users.user[@name='smith'] instead of "users.smith"
-                    childNode.setName(parentName.substring(0, parentName.length() - 1));
-                    childNode.addAttribute(new Node("name", entry.getKey()));
-                }
-
-                childNode.setReference(entry);
-                loadHierarchy(childNode, entry.getValue());
-                parentNode.addChild(childNode);
-            }
-        } else if (obj instanceof Collection) {
-            for (Object child : (Collection) obj) {
-                final Node childNode = new Node("item");
-                childNode.setReference(child);
-                loadHierarchy(childNode, child);
-                parentNode.addChild(childNode);
-            }
-        }
-
-        parentNode.setValue(obj);
-    }
-
-    protected Object saveHierarchy(final ConfigurationNode parentNode) {
-        if (parentNode.getChildrenCount() == 0)
-            return parentNode.getValue();
-
-        if (parentNode.getChildrenCount("item") == parentNode.getChildrenCount()) {
-            return parentNode.getChildren().stream().map(this::saveHierarchy).collect(Collectors.toList());
-        } else {
-            final Map<String, Object> map = new LinkedHashMap<>();
-            for (ConfigurationNode childNode : parentNode.getChildren()) {
-                String nodeName = childNode.getName();
-                if (this.xmlCompatibility && childNode.getAttributes("name").size() > 0)
-                    nodeName = String.valueOf(childNode.getAttributes("name").get(0).getValue());
-
-
-                map.put(nodeName, saveHierarchy(childNode));
-            }
-
-            return map;
-        }
-    }
-}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
index 1b90435..1247986 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
@@ -66,10 +66,11 @@
         TestGraph graph = new TestGraph();
         TraversalStrategies strategies = graph.traversal().getStrategies();
         assertFalse(TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList().isEmpty());
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()) {
+        assertTrue(TraversalStrategies.GlobalCache.getStrategies(Graph.class).iterator().hasNext());
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(Graph.class)) {
             assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
         }
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class)) {
             assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
         }
         assertTrue(strategies.getStrategy(StrategyA.class).isPresent());
@@ -83,10 +84,10 @@
         ///
         graph = new TestGraph();
         strategies = graph.traversal().getStrategies();
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(Graph.class)) {
             assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
         }
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class)) {
             assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
         }
         assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
@@ -98,10 +99,10 @@
         //////////////////////
         strategies = TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class);
         assertFalse(TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList().isEmpty());
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class)) {
             assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
         }
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraph.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraph.class)) {
             assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
         }
         assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
@@ -112,10 +113,10 @@
         //
         strategies = TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class);
         assertFalse(TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList().isEmpty());
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class)) {
             assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
         }
-        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraph.class).toList()) {
+        for (final TraversalStrategy strategy : TraversalStrategies.GlobalCache.getStrategies(TestGraph.class)) {
             assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
         }
         assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OrderTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OrderTest.java
index b2d3084..0204399 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OrderTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OrderTest.java
@@ -44,13 +44,17 @@
     @Parameterized.Parameters(name = "{0}.test({1},{2})")
     public static Iterable<Object[]> data() throws ParseException {
         return new ArrayList<>(Arrays.asList(new Object[][]{
+                {Order.asc, Arrays.asList("a", "c", null, "d"), Arrays.asList(null, "a", "c", "d")},
                 {Order.asc, Arrays.asList("b", "a", "c", "d"), Arrays.asList("a", "b", "c", "d")},
                 {Order.desc, Arrays.asList("b", "a", "c", "d"), Arrays.asList("d", "c", "b", "a")},
+                {Order.desc, Arrays.asList("c", "a", null, "d"), Arrays.asList("d", "c", "a", null)},
                 {Order.asc, Arrays.asList(formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2020"), formatter.parse("1-Jan-2008")),
                             Arrays.asList(formatter.parse("1-Jan-2008"), formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2020"))},
                 {Order.desc, Arrays.asList(formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2020"), formatter.parse("1-Jan-2008")),
                              Arrays.asList(formatter.parse("1-Jan-2020"), formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2008"))},
+                {Order.desc, Arrays.asList(100L, 1L, null, -1L, 0L), Arrays.asList(100L, 1L, 0L, -1L, null)},
                 {Order.desc, Arrays.asList(100L, 1L, -1L, 0L), Arrays.asList(100L, 1L, 0L, -1L)},
+                {Order.asc, Arrays.asList(100L, 1L, null, -1L, 0L), Arrays.asList(null, -1L, 0L, 1L, 100L)},
                 {Order.asc, Arrays.asList(100.1f, 1.1f, -1.1f, 0.1f), Arrays.asList(-1.1f, 0.1f, 1.1f, 100.1f)},
                 {Order.desc, Arrays.asList(100.1f, 1.1f, -1.1f, 0.1f), Arrays.asList(100.1f, 1.1f, 0.1f, -1.1f)},
                 {Order.asc, Arrays.asList(100.1d, 1.1d, -1.1d, 0.1d), Arrays.asList(-1.1d, 0.1d, 1.1d, 100.1d)},
@@ -60,22 +64,7 @@
                 {Order.asc, Arrays.asList(100, 1, -1, 0), Arrays.asList(-1, 0, 1, 100)},
                 {Order.desc, Arrays.asList(100, 1, -1, 0), Arrays.asList(100, 1, 0, -1)},
                 {Order.asc, Arrays.asList("b", "a", T.id, "c", "d"), Arrays.asList("a", "b", "c", "d", T.id)},
-                {Order.desc, Arrays.asList("b", "a", T.id, "c", "d"), Arrays.asList(T.id, "d", "c", "b", "a")},
-                {Order.incr, Arrays.asList("b", "a", "c", "d"), Arrays.asList("a", "b", "c", "d")},
-                {Order.decr, Arrays.asList("b", "a", "c", "d"), Arrays.asList("d", "c", "b", "a")},
-                {Order.incr, Arrays.asList(formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2020"), formatter.parse("1-Jan-2008")),
-                             Arrays.asList(formatter.parse("1-Jan-2008"), formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2020"))},
-                {Order.decr, Arrays.asList(formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2020"), formatter.parse("1-Jan-2008")),
-                             Arrays.asList(formatter.parse("1-Jan-2020"), formatter.parse("1-Jan-2018"), formatter.parse("1-Jan-2008"))},
-                {Order.decr, Arrays.asList(100L, 1L, -1L, 0L), Arrays.asList(100L, 1L, 0L, -1L)},
-                {Order.incr, Arrays.asList(100.1f, 1.1f, -1.1f, 0.1f), Arrays.asList(-1.1f, 0.1f, 1.1f, 100.1f)},
-                {Order.decr, Arrays.asList(100.1f, 1.1f, -1.1f, 0.1f), Arrays.asList(100.1f, 1.1f, 0.1f, -1.1f)},
-                {Order.incr, Arrays.asList(100.1d, 1.1d, -1.1d, 0.1d), Arrays.asList(-1.1d, 0.1d, 1.1d, 100.1d)},
-                {Order.decr, Arrays.asList(100.1d, 1.1d, -1.1d, 0.1d), Arrays.asList(100.1d, 1.1d, 0.1d, -1.1d)},
-                {Order.incr, Arrays.asList(100L, 1L, -1L, 0L), Arrays.asList(-1L, 0L, 1L, 100L)},
-                {Order.decr, Arrays.asList(100L, 1L, -1L, 0L), Arrays.asList(100L, 1L, 0L, -1L)},
-                {Order.incr, Arrays.asList(100, 1, -1, 0), Arrays.asList(-1, 0, 1, 100)},
-                {Order.decr, Arrays.asList(100, 1, -1, 0), Arrays.asList(100, 1, 0, -1)}}));
+                {Order.desc, Arrays.asList("b", "a", T.id, "c", "d"), Arrays.asList(T.id, "d", "c", "b", "a")}}));
     }
 
     @Parameterized.Parameter(value = 0)
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalTest.java
index 80d5024..90eab14 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalTest.java
@@ -19,10 +19,13 @@
 package org.apache.tinkerpop.gremlin.process.traversal;
 
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -35,11 +38,13 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsCollectionContaining.hasItems;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -128,6 +133,16 @@
         assertThat(t.isClosed(), is(true));
     }
 
+    @Test
+    public void shouldOnlyAllowAnonymousChildren() {
+        final GraphTraversalSource g = traversal().withGraph(EmptyGraph.instance());
+        g.V(1).addE("self").to(__.V(1));
+        try {
+            g.V(1).addE("self").to(g.V(1));
+            fail("Should not allow child traversals spawned from 'g'");
+        } catch (IllegalStateException ignored) {}
+    }
+
     private static class MockCloseStep<E> extends MockStep<E> implements AutoCloseable {
         private boolean closed = false;
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/GremlinDslProcessorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/GremlinDslProcessorTest.java
index 23876c6..53ff874 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/GremlinDslProcessorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/GremlinDslProcessorTest.java
@@ -45,7 +45,7 @@
         final Compilation compilation = javac()
                 .withProcessors(new GremlinDslProcessor())
                 .compile(JavaFileObjects.forResource(GremlinDsl.class.getResource("SocialTraversalDsl.java")));
-        assertThat(compilation).succeededWithoutWarnings();
+        assertCompilationSuccess(compilation);
     }
 
     @Test
@@ -53,7 +53,7 @@
         final Compilation compilation = javac()
                 .withProcessors(new GremlinDslProcessor())
                 .compile(JavaFileObjects.forResource(GremlinDsl.class.getResource("SocialMoveTraversalDsl.java")));
-        assertThat(compilation).succeededWithoutWarnings();
+        assertCompilationSuccess(compilation);
         assertThat(compilation)
                 .generatedFile(StandardLocation.SOURCE_OUTPUT, "org.apache.tinkerpop.gremlin.process.traversal.dsl.social", "SocialMoveTraversal.java");
     }
@@ -63,7 +63,7 @@
         final Compilation compilation = javac()
                 .withProcessors(new GremlinDslProcessor())
                 .compile(JavaFileObjects.forResource(GremlinDsl.class.getResource("SocialPackageTraversalDsl.java")));
-        assertThat(compilation).succeededWithoutWarnings();
+        assertCompilationSuccess(compilation);
     }
 
     @Test
@@ -71,7 +71,7 @@
         final Compilation compilation = javac()
                 .withProcessors(new GremlinDslProcessor())
                 .compile(JavaFileObjects.forResource(GremlinDsl.class.getResource("SocialNoDefaultMethodsTraversalDsl.java")));
-        assertThat(compilation).succeededWithoutWarnings();
+        assertCompilationSuccess(compilation);
     }
 
     @Test
@@ -90,6 +90,20 @@
         }
     }
 
+    private void assertCompilationSuccess(final Compilation compilation) {
+        if (isJava8())
+            assertThat(compilation).succeededWithoutWarnings();
+        else {
+            assertThat(compilation).hadWarningContaining("Supported source version 'RELEASE_8' from annotation processor");
+            assertThat(compilation).succeeded();
+        }
+    }
+
+    private boolean isJava8() {
+        String version = System.getProperty("java.version");
+        return version.startsWith("1.");
+    }
+
     static class JavaFileObjectClassLoader extends ClassLoader {
         Map<String, JavaFileObject> classFileMap;
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java
index ede66cc..fe60d6b 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.dsl.graph;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ElementValueTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ElementValueTraversalTest.java
deleted file mode 100644
index 2752a3d..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ElementValueTraversalTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.lambda;
-
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ElementValueTraversalTest {
-
-    @Test
-    public void shouldWorkOnVertex() {
-        final ElementValueTraversal<Integer> t = new ElementValueTraversal<>("age");
-        final Vertex v = mock(Vertex.class);
-        when(v.value("age")).thenReturn(29);
-        t.addStart(new B_O_Traverser(v, 1).asAdmin());
-        assertEquals(29, t.next().intValue());
-    }
-
-    @Test
-    public void shouldWorkOnEdge() {
-        final ElementValueTraversal<Double> t = new ElementValueTraversal<>("weight");
-        final Edge e = mock(Edge.class);
-        when(e.value("weight")).thenReturn(1.0d);
-        t.addStart(new B_O_Traverser(e, 1).asAdmin());
-        assertEquals(1.0d, t.next(), 0.00001d);
-    }
-
-    @Test
-    public void shouldWorkOnVertexProperty() {
-        final ElementValueTraversal<Integer> t = new ElementValueTraversal<>("age");
-        final VertexProperty vp = mock(VertexProperty.class);
-        when(vp.value("age")).thenReturn(29);
-        t.addStart(new B_O_Traverser(vp, 1).asAdmin());
-        assertEquals(29, t.next().intValue());
-    }
-
-    @Test
-    public void shouldWorkOnMap() {
-        final ElementValueTraversal<Integer> t = new ElementValueTraversal<>("age");
-        final Map<String,Integer> m = new HashMap<>();
-        m.put("age", 29);
-        t.addStart(new B_O_Traverser(m, 1).asAdmin());
-        assertEquals(29, t.next().intValue());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void shouldThrowExceptionWhenTryingUnsupportedType() {
-        final ElementValueTraversal<Integer> t = new ElementValueTraversal<>("age");
-        t.addStart(new B_O_Traverser(29, 1).asAdmin());
-        t.next();
-    }
-}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversalTest.java
new file mode 100644
index 0000000..7d1ad54
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/TokenTraversalTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.lambda;
+
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class TokenTraversalTest {
+    @Test
+    public void shouldWorkOnVertex() {
+        final TokenTraversal<Vertex, Integer> t = new TokenTraversal<>(T.id);
+        final Vertex v = mock(Vertex.class);
+        when(v.id()).thenReturn(100);
+        t.addStart(new B_O_Traverser<>(v, 1).asAdmin());
+        assertEquals(100, t.next().intValue());
+    }
+
+    @Test
+    public void shouldWorkOnVertexProperty() {
+        final TokenTraversal<VertexProperty, Integer> t = new TokenTraversal<>(T.id);
+        final VertexProperty vo = mock(VertexProperty.class);
+        when(vo.id()).thenReturn(100);
+        t.addStart(new B_O_Traverser<>(vo, 1).asAdmin());
+        assertEquals(100, t.next().intValue());
+    }
+
+    @Test
+    public void shouldWorkOnEdge() {
+        final TokenTraversal<Edge, Integer> t = new TokenTraversal<>(T.id);
+        final Edge e = mock(Edge.class);
+        when(e.id()).thenReturn(100);
+        t.addStart(new B_O_Traverser<>(e, 1).asAdmin());
+        assertEquals(100, t.next().intValue());
+    }
+
+    @Test
+    public void shouldWorkOnPropertyKey() {
+        final TokenTraversal<Property<String>, String> t = new TokenTraversal<>(T.key);
+        final Property<String> p = mock(Property.class);
+        when(p.key()).thenReturn("name");
+        t.addStart(new B_O_Traverser<>(p, 1).asAdmin());
+        assertEquals("name", t.next());
+    }
+
+    @Test
+    public void shouldWorkOnPropertyValue() {
+        final TokenTraversal<Property<String>, String> t = new TokenTraversal<>(T.value);
+        final Property<String> p = mock(Property.class);
+        when(p.value()).thenReturn("marko");
+        t.addStart(new B_O_Traverser<>(p, 1).asAdmin());
+        assertEquals("marko", t.next());
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ValueTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ValueTraversalTest.java
new file mode 100644
index 0000000..761d0b6
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ValueTraversalTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.lambda;
+
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ValueTraversalTest {
+
+    @Test
+    public void shouldWorkOnVertex() {
+        final ValueTraversal<Vertex, Integer> t = new ValueTraversal<>("age");
+        final Vertex v = mock(Vertex.class);
+        when(v.property("age")).thenReturn(new DetachedVertexProperty<>(1, "age", 29, null));
+        t.addStart(new B_O_Traverser<>(v, 1).asAdmin());
+        assertEquals(29, t.next().intValue());
+    }
+
+    @Test
+    public void shouldWorkOnVertexWithMissingKey() {
+        final ValueTraversal<Vertex, Integer> t = new ValueTraversal<>("age");
+        final Vertex v = mock(Vertex.class);
+        when(v.property("age")).thenReturn(VertexProperty.empty());
+        t.addStart(new B_O_Traverser<>(v, 1).asAdmin());
+        assertNull(t.next());
+    }
+
+    @Test
+    public void shouldWorkOnEdge() {
+        final ValueTraversal<Edge, Double> t = new ValueTraversal<>("weight");
+        final Edge e = mock(Edge.class);
+        when(e.property("weight")).thenReturn(new DetachedProperty<>("weight", 1.0d));
+        t.addStart(new B_O_Traverser<>(e, 1).asAdmin());
+        assertEquals(1.0d, t.next(), 0.00001d);
+    }
+
+    @Test
+    public void shouldWorkOnEdgeWithMissingKey() {
+        final ValueTraversal<Edge, Double> t = new ValueTraversal<>("weight");
+        final Edge e = mock(Edge.class);
+        when(e.property("weight")).thenReturn(Property.empty());
+        t.addStart(new B_O_Traverser<>(e, 1).asAdmin());
+        assertNull(t.next());
+    }
+
+    @Test
+    public void shouldWorkOnVertexProperty() {
+        final ValueTraversal<VertexProperty, Integer> t = new ValueTraversal<>("age");
+        final VertexProperty vp = mock(VertexProperty.class);
+        when(vp.property("age")).thenReturn(new DetachedProperty<>("age", 29));
+        t.addStart(new B_O_Traverser<>(vp, 1).asAdmin());
+        assertEquals(29, t.next().intValue());
+    }
+
+    @Test
+    public void shouldWorkOnVertexPropertyWithMissingKey() {
+        final ValueTraversal<VertexProperty, Integer> t = new ValueTraversal<>("age");
+        final VertexProperty vp = mock(VertexProperty.class);
+        when(vp.property("age")).thenReturn(Property.empty());
+        t.addStart(new B_O_Traverser<>(vp, 1).asAdmin());
+        assertNull(t.next());
+    }
+
+    @Test
+    public void shouldWorkOnMap() {
+        final ValueTraversal<Map<String,Integer>, Integer> t = new ValueTraversal<>("age");
+        final Map<String,Integer> m = new HashMap<>();
+        m.put("age", 29);
+        t.addStart(new B_O_Traverser<>(m, 1).asAdmin());
+        assertEquals(29, t.next().intValue());
+    }
+
+    @Test
+    public void shouldWorkOnMapWithMissingKey() {
+        final ValueTraversal<Map<String,Integer>, Integer> t = new ValueTraversal<>("not-age");
+        final Map<String,Integer> m = new HashMap<>();
+        m.put("age", 29);
+        t.addStart(new B_O_Traverser<>(m, 1).asAdmin());
+        assertNull(t.next());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void shouldThrowExceptionWhenTryingUnsupportedType() {
+        final ValueTraversal<Integer, Integer> t = new ValueTraversal<>("age");
+        t.addStart(new B_O_Traverser<>(29, 1).asAdmin());
+        t.next();
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStepTest.java
new file mode 100644
index 0000000..d5ae0ec
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStepTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.function.TraverserSetSupplier;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AddVertexStepTest {
+
+    @Test
+    public void shouldDefaultTheLabelIfNullString() {
+        final Traversal.Admin t = mock(Traversal.Admin.class);
+        when(t.getTraverserSetSupplier()).thenReturn(TraverserSetSupplier.instance());
+        final AddVertexStartStep starStep = new AddVertexStartStep(t, (String) null);
+        assertEquals(Vertex.DEFAULT_LABEL, starStep.getParameters().getRaw().get(T.label).get(0));
+        final AddVertexStep step = new AddVertexStep(t, (String) null);
+        assertEquals(Vertex.DEFAULT_LABEL, starStep.getParameters().getRaw().get(T.label).get(0));
+    }
+
+    @Test
+    public void shouldDefaultTheLabelIfNullTraversal() {
+        final Traversal.Admin t = mock(Traversal.Admin.class);
+        when(t.getTraverserSetSupplier()).thenReturn(TraverserSetSupplier.instance());
+        final AddVertexStartStep starStep = new AddVertexStartStep(t, (Traversal<?,String>) null);
+        assertEquals(Vertex.DEFAULT_LABEL, starStep.getParameters().getRaw().get(T.label).get(0));
+        final AddVertexStep step = new AddVertexStep(t, (String) null);
+        assertEquals(Vertex.DEFAULT_LABEL, starStep.getParameters().getRaw().get(T.label).get(0));
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStepTest.java
index 31457fc..8ba2c52 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStepTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStepTest.java
@@ -40,12 +40,6 @@
     protected List<Traversal> getTraversals() {
         return Arrays.asList(
                 __.order(),
-                __.order().by(Order.decr),
-                __.order().by("age", Order.incr),
-                __.order().by("age", Order.decr),
-                __.order().by(outE().count(), Order.incr),
-                __.order().by("age", Order.incr).by(outE().count(), Order.incr),
-                __.order().by(outE().count(), Order.incr).by("age", Order.incr),
                 __.order().by(Order.desc),
                 __.order().by("age", Order.asc),
                 __.order().by("age", Order.desc),
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStepTest.java
index 5999793..ec5e539 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStepTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStepTest.java
@@ -42,12 +42,6 @@
     protected List<Traversal> getTraversals() {
         return Arrays.asList(
                 __.order(Scope.local),
-                __.order(Scope.local).by(Order.decr),
-                __.order(Scope.local).by("age", Order.incr),
-                __.order(Scope.local).by("age", Order.decr),
-                __.order(Scope.local).by(outE().count(), Order.incr),
-                __.order(Scope.local).by("age", Order.incr).by(outE().count(), Order.incr),
-                __.order(Scope.local).by(outE().count(), Order.incr).by("age", Order.incr),
                 __.order(Scope.local).by(Order.desc),
                 __.order(Scope.local).by("age", Order.asc),
                 __.order(Scope.local).by("age", Order.desc),
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStepTest.java
new file mode 100644
index 0000000..f34f420
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStepTest.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.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class AggregateGlobalStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Arrays.asList(
+                __.aggregate("x"),
+                __.aggregate("x").by("name"),
+                __.aggregate("x").by("age"));
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStepTest.java
new file mode 100644
index 0000000..9128292
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStepTest.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.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class AggregateLocalStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Arrays.asList(
+                __.store("x"),
+                __.store("x").by("name"),
+                __.store("x").by("age"));
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStepTest.java
deleted file mode 100644
index 2c0101c..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStepTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class AggregateStepTest extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.aggregate("x"),
-                __.aggregate("x").by("name"),
-                __.aggregate("x").by("age"));
-    }
-}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/StoreStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/StoreStepTest.java
deleted file mode 100644
index be3ec8e..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/StoreStepTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class StoreStepTest extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.store("x"),
-                __.store("x").by("name"),
-                __.store("x").by("age"));
-    }
-}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java
index ebe40af..27d8e44 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java
@@ -43,6 +43,7 @@
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class ParametersTest {
+
     @Test
     public void shouldGetKeyValuesEmpty() {
         final Parameters parameters = new Parameters();
@@ -50,6 +51,16 @@
     }
 
     @Test
+    public void shouldAllowNullValues() {
+        final Parameters parameters = new Parameters();
+        parameters.set(null, "a", null, "b", "bat", "c", "cat");
+
+        final Object[] params = parameters.getKeyValues(mock(Traverser.Admin.class));
+        assertEquals(6, params.length);
+        assertThat(Arrays.equals(new Object[] {"a", null, "b", "bat", "c", "cat"}, params), is(true));
+    }
+
+    @Test
     public void shouldGetKeyValues() {
         final Parameters parameters = new Parameters();
         parameters.set(null, "a", "axe", "b", "bat", "c", "cat");
@@ -210,6 +221,14 @@
     }
 
     @Test
+    public void shouldContainKeyValue() {
+        final Parameters parameters = new Parameters();
+        parameters.set(null, "a", "axe", "b", "bat", "c", "cat");
+
+        assertThat(parameters.contains("b", "bat"), is(true));
+    }
+
+    @Test
     public void shouldNotContainKey() {
         final Parameters parameters = new Parameters();
         parameters.set(null, "a", "axe", "b", "bat", "c", "cat");
@@ -218,6 +237,14 @@
     }
 
     @Test
+    public void shouldNotContainKeyAndValue() {
+        final Parameters parameters = new Parameters();
+        parameters.set(null, "a", "axe", "b", "bat", "c", "cat");
+
+        assertThat(parameters.contains("b", "mat"), is(false));
+    }
+
+    @Test
     public void shouldGetSetMultiple() {
         final Parameters parameters = new Parameters();
         parameters.set(null, "a", "axe", "a", "ant", "b", "bat", "b", "ball", "c", "cat");
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/ByModulatorOptimizationStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/ByModulatorOptimizationStrategyTest.java
new file mode 100644
index 0000000..a3a0044
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/ByModulatorOptimizationStrategyTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.Operator.assign;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+@RunWith(Parameterized.class)
+public class ByModulatorOptimizationStrategyTest {
+
+    @Parameterized.Parameter
+    public Traversal original;
+
+    @Parameterized.Parameter(value = 1)
+    public Traversal optimized;
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> generateTestParameters() {
+
+        final List<Object[]> originalAndOptimized = new ArrayList<>();
+        final GraphTraversal[] baseTraversals = new GraphTraversal[]{
+                __.aggregate("x"),
+                __.dedup(),
+                __.dedup("a"),
+                __.group(),
+                __.group("x"),
+                __.groupCount(),
+                __.groupCount("x"),
+                __.order(),
+                __.order(Scope.local),
+                __.project("a"),
+                __.path(),
+                __.path().from("a").to("b"),
+                __.sack(assign),
+                __.sample(10),
+                __.select("a"),
+                __.select("a", "b"),
+                __.store("x"),
+                __.tree(),
+                __.tree("x"),
+                __.where(P.eq("a")),
+                __.where("a", P.eq("b"))
+        };
+
+        for (final Traversal traversal : baseTraversals) {
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(values("name")),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by("name"),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.id()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.id),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.label()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.label),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.key()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.key),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.value()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.value),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.identity()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(),
+            });
+        }
+
+        originalAndOptimized.add(new Traversal[]{
+                __.project("a", "b", "c", "d", "e")
+                        .by(values("name"))
+                        .by(__.id())
+                        .by(__.label())
+                        .by(__.identity())
+                        .by(__.outE().count()),
+                __.project("a", "b", "c", "d", "e")
+                        .by("name")
+                        .by(T.id)
+                        .by(T.label)
+                        .by()
+                        .by(__.outE().count())
+        });
+
+        final GraphTraversal[] baseGroupTraversals = new GraphTraversal[]{
+                __.group().by("age"),
+                __.group("x").by("age"),
+        };
+
+        for (final Traversal traversal : baseGroupTraversals) {
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(values("name").fold()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by("name"),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.id().fold()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.id),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.label().fold()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.label),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.key().fold()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.key),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.value().fold()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(T.value),
+            });
+            originalAndOptimized.add(new Traversal[]{
+                    ((GraphTraversal<?, ?>) traversal.asAdmin().clone()).by(__.identity()),
+                    ((GraphTraversal) traversal.asAdmin().clone()).by(),
+            });
+        }
+
+        originalAndOptimized.add(new Traversal[]{
+                __.group().by(values("age")).by(values("name")),
+                __.group().by("age").by(values("name"))
+        });
+
+        originalAndOptimized.add(new Traversal[]{
+                __.group("x").by(values("age")).by(values("name")),
+                __.group("x").by("age").by(values("name"))
+        });
+
+        originalAndOptimized.add(new Traversal[]{
+                __.group().by(values("age")).by(values("name").fold()),
+                __.group().by("age").by("name")
+        });
+
+        originalAndOptimized.add(new Traversal[]{
+                __.group("x").by(values("age")).by(values("name").fold()),
+                __.group("x").by("age").by("name")
+        });
+
+        return originalAndOptimized;
+    }
+
+    private void applyByModulatorOptimizationStrategy(final Traversal traversal) {
+        final TraversalStrategies strategies = new DefaultTraversalStrategies();
+        strategies.addStrategies(ByModulatorOptimizationStrategy.instance());
+        traversal.asAdmin().setStrategies(strategies);
+        traversal.asAdmin().applyStrategies();
+    }
+
+    @Test
+    public void doTest() {
+        applyByModulatorOptimizationStrategy(original);
+        assertEquals(optimized, original);
+    }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
index cf54f50..97d6407 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
@@ -98,7 +98,8 @@
                 {filter(has("age", gt(10)).as("b")).as("a"), has("age", gt(10)).as("b", "a"), Collections.emptyList()},
                 {filter(has("age", gt(10)).as("a")), has("age", gt(10)).as("a"), Collections.emptyList()},
                 {filter(and(has("age", gt(10)).as("a"), has("name", "marko"))), addHas(__.start(), "age", gt(10), "name", eq("marko")).as("a"), Collections.emptyList()},
-                {filter(out("created").and().out("knows").or().in("knows")), filter(or(and(out("created"), out("knows")), __.in("knows"))), Collections.singletonList(ConnectiveStrategy.instance())},
+                {filter(out("created").and().out("knows").or().in("knows")), or(and(out("created"), out("knows")), __.in("knows")), Collections.singletonList(ConnectiveStrategy.instance())},
+                {filter(out("created").and().out("knows").or().in("knows")).and(hasLabel("person")), or(and(out("created"), out("knows")), __.in("knows")).hasLabel("person"), Collections.singletonList(ConnectiveStrategy.instance())},
                 //
                 {or(has("name", "marko"), has("age", 32)), or(has("name", "marko"), has("age", 32)), Collections.emptyList()},
                 {or(has("name", "marko"), has("name", "bob")), has("name", eq("marko").or(eq("bob"))), Collections.emptyList()},
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
index 9616d5a..ec0b89c 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
@@ -27,7 +27,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
@@ -82,20 +82,20 @@
                 {__.select("a"), __.select("a"), Collections.emptyList()},
                 {__.select("a").by(), __.select("a").by(), Collections.emptyList()},
                 {__.select("a").by(__.outE().count()), __.select("a").map(__.outE().count()), Collections.emptyList()},
-                {__.select("a").by("name"), __.select("a").map(new ElementValueTraversal<>("name")), Collections.emptyList()},
+                {__.select("a").by("name"), __.select("a").map(new ValueTraversal<>("name")), Collections.emptyList()},
                 {__.select("a").out(), __.select("a").out(), Collections.emptyList()},
-                {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+                {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by("name"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
                 {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").map(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
                 {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").map(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
                 // select("a","b")
                 {__.select("a", "b"), __.select("a", "b"), Collections.emptyList()},
                 {__.select("a", "b").by(), __.select("a", "b").by(), Collections.emptyList()},
                 {__.select("a", "b", "c").by(), __.select("a", "b", "c").by(), Collections.emptyList()},
-                {__.select("a", "b").by().by("age"), __.select("b").map(new ElementValueTraversal<>("age")).as("b").select("a").map(new IdentityTraversal<>()).as("a").select(Pop.last, "a", "b"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
-                {__.select("a", "b").by("name").by("age"), __.select("b").map(new ElementValueTraversal<>("age")).as("b").select("a").map(new ElementValueTraversal<>("name")).as("a").select(Pop.last, "a", "b"), Collections.emptyList()},
-                {__.select("a", "b", "c").by("name").by(__.outE().count()), __.select("c").map(new ElementValueTraversal<>("name")).as("c").select("b").map(__.outE().count()).as("b").select("a").map(new ElementValueTraversal<>("name")).as("a").select(Pop.last, "a", "b", "c"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
-                {__.select(Pop.first, "a", "b").by("name").by("age"), __.select(Pop.first, "b").map(new ElementValueTraversal<>("age")).as("b").select(Pop.first, "a").map(new ElementValueTraversal<>("name")).as("a").select(Pop.last, "a", "b"), Collections.emptyList()},
-                {__.select(Pop.last, "a", "b").by("name").by("age"), __.select(Pop.last, "b").map(new ElementValueTraversal<>("age")).as("b").select(Pop.last, "a").map(new ElementValueTraversal<>("name")).as("a").select(Pop.last, "a", "b"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+                {__.select("a", "b").by().by("age"), __.select("b").map(new ValueTraversal<>("age")).as("b").select("a").map(new IdentityTraversal<>()).as("a").select(Pop.last, "a", "b"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+                {__.select("a", "b").by("name").by("age"), __.select("b").map(new ValueTraversal<>("age")).as("b").select("a").map(new ValueTraversal<>("name")).as("a").select(Pop.last, "a", "b"), Collections.emptyList()},
+                {__.select("a", "b", "c").by("name").by(__.outE().count()), __.select("c").map(new ValueTraversal<>("name")).as("c").select("b").map(__.outE().count()).as("b").select("a").map(new ValueTraversal<>("name")).as("a").select(Pop.last, "a", "b", "c"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+                {__.select(Pop.first, "a", "b").by("name").by("age"), __.select(Pop.first, "b").map(new ValueTraversal<>("age")).as("b").select(Pop.first, "a").map(new ValueTraversal<>("name")).as("a").select(Pop.last, "a", "b"), Collections.emptyList()},
+                {__.select(Pop.last, "a", "b").by("name").by("age"), __.select(Pop.last, "b").map(new ValueTraversal<>("age")).as("b").select(Pop.last, "a").map(new ValueTraversal<>("name")).as("a").select(Pop.last, "a", "b"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
                 {__.select(Pop.all, "a", "b").by("name").by("age"), __.select(Pop.all, "a", "b").by("name").by("age"), Collections.emptyList()},
                 {__.select(Pop.mixed, "a", "b").by("name").by("age"), __.select(Pop.mixed, "a", "b").by("name").by("age"), Collections.emptyList()},
                 // where(as("a")...)
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverserTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverserTest.java
new file mode 100644
index 0000000..da41900
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverserTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.traverser.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+public class EmptyTraverserTest {
+
+    @Test
+    public void shouldHaveSameInstance() {
+        assertSame(EmptyTraverser.instance(), EmptyTraverser.instance());
+    }
+
+    @Test
+    public void shouldHaveZeroBulk() {
+        assertEquals(0, EmptyTraverser.instance().bulk());
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/IndexedTraverserSetTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/IndexedTraverserSetTest.java
index 0d765f4..6f0b490 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/IndexedTraverserSetTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/IndexedTraverserSetTest.java
@@ -26,6 +26,7 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Random;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.IsNull.nullValue;
@@ -111,7 +112,7 @@
         assertEquals(1, nopeTraversers.size());
         assertEquals(1, nopeTraversers.get(0).bulk());
 
-        ts.shuffle();
+        ts.shuffle(new Random());
 
         final List<Traverser.Admin<String>> testTraversersAfterShuffle = new ArrayList<>(ts.get("test"));
         assertEquals(1, testTraversersAfterShuffle.size());
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
index 0a81238..89a37d5 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
@@ -130,8 +130,9 @@
         }
         assertEquals(4, found);
         //
+        //System.out.println(traversal.explain().prettyPrint(160));
         found = 0;
-        for (final String line : traversal.explain().prettyPrint(158).split("]\n")) { // need to split cause of word wrap
+        for (final String line : traversal.explain().prettyPrint(170).split("]\n")) { // need to split cause of word wrap
             if (line.contains("IncidentToAdjacentStrategy") && line.contains("[VertexStep(IN,vertex)"))
                 found++;
             if (line.contains("IncidentToAdjacentStrategy") && line.contains("[VertexStep(OUT,vertex)"))
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoPoolTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoPoolTest.java
index f9029bb..aaded07 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoPoolTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoPoolTest.java
@@ -18,8 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.gryo;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.convert.LegacyListDelimiterHandler;
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.IoX;
 import org.apache.tinkerpop.gremlin.structure.io.IoXIoRegistry;
@@ -103,6 +104,7 @@
     @Test
     public void shouldConfigPoolOnConstructionWithMultipleCustomIoRegistries() throws Exception {
         final Configuration conf = new BaseConfiguration();
+        ((BaseConfiguration) conf).setListDelimiterHandler(new LegacyListDelimiterHandler(','));
         conf.setProperty(IoRegistry.IO_REGISTRY,
                 IoXIoRegistry.InstanceBased.class.getName() + "," + IoYIoRegistry.InstanceBased.class.getName());
         final GryoPool pool = GryoPool.build().ioRegistries(conf.getList(IoRegistry.IO_REGISTRY, Collections.emptyList())).create();
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelperTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelperTest.java
index 636859d..e9b066d 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelperTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelperTest.java
@@ -54,13 +54,8 @@
     }
 
     @Test
-    public void shouldValidatePropertyAndNotAllowNullValue() {
-        try {
-            ElementHelper.validateProperty("test", null);
-            fail("Should fail as property value cannot be null");
-        } catch (IllegalArgumentException iae) {
-            assertEquals(Property.Exceptions.propertyValueCanNotBeNull().getMessage(), iae.getMessage());
-        }
+    public void shouldValidatePropertyAndAllowNullValue() {
+        ElementHelper.validateProperty("test", null);
     }
 
     @Test
@@ -125,15 +120,6 @@
     }
 
     @Test
-    public void shouldNotAllowEvenNumberOfKeyValuesAndInvalidValues() {
-        try {
-            ElementHelper.legalPropertyKeyValueArray("aKey", "test", "value-for-this-one", 1, "1", null);
-        } catch (IllegalArgumentException iae) {
-            assertEquals(Property.Exceptions.propertyValueCanNotBeNull().getMessage(), iae.getMessage());
-        }
-    }
-
-    @Test
     public void shouldFindTheIdValueAlone() {
         assertEquals(123l, ElementHelper.getIdValue(T.id, 123l).get());
     }
@@ -148,9 +134,9 @@
         assertFalse(ElementHelper.getIdValue("test", 321, "xyz", 123l, "testagain", "that").isPresent());
     }
 
-    @Test(expected = NullPointerException.class)
+    @Test
     public void shouldNotFindAnIdValueBecauseItIsNull() {
-        ElementHelper.getIdValue("test", 321, T.id, null, "testagain", "that");
+        assertEquals("default", ElementHelper.getIdValue("test", 321, T.id, null, "testagain", "that").orElse("default"));
     }
 
     @Test
@@ -191,6 +177,15 @@
     @Test
     public void shouldAttachPropertiesButNotLabelsOrId() {
         final Element mockElement = mock(Element.class);
+        final Graph mockGraph = mock(Graph.class);
+        final Graph.Features mockGraphFeatures = mock(Graph.Features.class);
+        final Graph.Features.VertexFeatures mockVertexFeatures = mock(Graph.Features.VertexFeatures.class);
+        final Graph.Features.VertexPropertyFeatures mockVertexPropertyFeatures = mock(Graph.Features.VertexPropertyFeatures.class);
+        when(mockElement.graph()).thenReturn(mockGraph);
+        when(mockGraph.features()).thenReturn(mockGraphFeatures);
+        when(mockGraphFeatures.vertex()).thenReturn(mockVertexFeatures);
+        when(mockVertexFeatures.properties()).thenReturn(mockVertexPropertyFeatures);
+        when(mockVertexPropertyFeatures.supportsNullPropertyValues()).thenReturn(true);
         ElementHelper.attachProperties(mockElement, "test", 123, T.id, 321, T.label, "friends");
         verify(mockElement, times(1)).property("test", 123);
         verify(mockElement, times(0)).property(T.id.getAccessor(), 321);
@@ -200,6 +195,15 @@
     @Test(expected = ClassCastException.class)
     public void shouldFailTryingToAttachPropertiesNonStringKey() {
         final Element mockElement = mock(Element.class);
+        final Graph mockGraph = mock(Graph.class);
+        final Graph.Features mockGraphFeatures = mock(Graph.Features.class);
+        final Graph.Features.VertexFeatures mockVertexFeatures = mock(Graph.Features.VertexFeatures.class);
+        final Graph.Features.VertexPropertyFeatures mockVertexPropertyFeatures = mock(Graph.Features.VertexPropertyFeatures.class);
+        when(mockElement.graph()).thenReturn(mockGraph);
+        when(mockGraph.features()).thenReturn(mockGraphFeatures);
+        when(mockGraphFeatures.vertex()).thenReturn(mockVertexFeatures);
+        when(mockVertexFeatures.properties()).thenReturn(mockVertexPropertyFeatures);
+        when(mockVertexPropertyFeatures.supportsNullPropertyValues()).thenReturn(true);
         ElementHelper.attachProperties(mockElement, "test", 123, 321, "test");
     }
 
@@ -216,6 +220,15 @@
     @Test
     public void shouldAttachPropertiesWithCardinalityButNotLabelsOrId() {
         final Vertex mockElement = mock(Vertex.class);
+        final Graph mockGraph = mock(Graph.class);
+        final Graph.Features mockGraphFeatures = mock(Graph.Features.class);
+        final Graph.Features.VertexFeatures mockVertexFeatures = mock(Graph.Features.VertexFeatures.class);
+        final Graph.Features.VertexPropertyFeatures mockVertexPropertyFeatures = mock(Graph.Features.VertexPropertyFeatures.class);
+        when(mockElement.graph()).thenReturn(mockGraph);
+        when(mockGraph.features()).thenReturn(mockGraphFeatures);
+        when(mockGraphFeatures.vertex()).thenReturn(mockVertexFeatures);
+        when(mockVertexFeatures.properties()).thenReturn(mockVertexPropertyFeatures);
+        when(mockVertexPropertyFeatures.supportsNullPropertyValues()).thenReturn(true);
         ElementHelper.attachProperties(mockElement, VertexProperty.Cardinality.single, "test", 123, T.id, 321, T.label, "friends");
         verify(mockElement, times(1)).property(VertexProperty.Cardinality.single, "test", 123);
         verify(mockElement, times(0)).property(VertexProperty.Cardinality.single, T.id.getAccessor(), 321);
@@ -225,6 +238,15 @@
     @Test(expected = ClassCastException.class)
     public void shouldFailTryingToAttachPropertiesWithCardinalityNonStringKey() {
         final Element mockElement = mock(Vertex.class);
+        final Graph mockGraph = mock(Graph.class);
+        final Graph.Features mockGraphFeatures = mock(Graph.Features.class);
+        final Graph.Features.VertexFeatures mockVertexFeatures = mock(Graph.Features.VertexFeatures.class);
+        final Graph.Features.VertexPropertyFeatures mockVertexPropertyFeatures = mock(Graph.Features.VertexPropertyFeatures.class);
+        when(mockElement.graph()).thenReturn(mockGraph);
+        when(mockGraph.features()).thenReturn(mockGraphFeatures);
+        when(mockGraphFeatures.vertex()).thenReturn(mockVertexFeatures);
+        when(mockVertexFeatures.properties()).thenReturn(mockVertexPropertyFeatures);
+        when(mockVertexPropertyFeatures.supportsNullPropertyValues()).thenReturn(true);
         ElementHelper.attachProperties(mockElement, VertexProperty.Cardinality.single, "test", 123, 321, "test");
     }
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactoryTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactoryTest.java
index 701e159..4a933d5 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactoryTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/util/GraphFactoryTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure.util;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AssertHelper;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.structure.Edge;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/SystemUtilTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/SystemUtilTest.java
index e5dc705..3705b99 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/SystemUtilTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/SystemUtilTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.util;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.junit.Test;
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/config/YamlConfigurationTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/config/YamlConfigurationTest.java
deleted file mode 100644
index e823dd3..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/config/YamlConfigurationTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.util.config;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.junit.Test;
-import org.yaml.snakeyaml.DumperOptions;
-import org.yaml.snakeyaml.Yaml;
-
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class YamlConfigurationTest {
-
-    @Test(expected = ConfigurationException.class)
-    public void shouldThrowConfigurationExceptionIfLoadFails() throws Exception {
-        final YamlConfiguration config = new YamlConfiguration();
-        config.load((Reader) null);
-    }
-
-    @Test(expected = ConfigurationException.class)
-    public void shouldThrowConfigurationExceptionIfSaveFails() throws Exception {
-        final YamlConfiguration config = new YamlConfiguration();
-        config.save((Writer) null);
-    }
-
-    @Test
-    public void shouldLoadSaveConfiguration() throws Exception {
-        final YamlConfiguration config = new YamlConfiguration();
-        final String testData = this.getTestInputData();
-        final StringWriter writer = new StringWriter();
-        config.load(new StringReader(testData));
-        config.save(writer);
-
-        assertEquals(testData, writer.getBuffer().toString());
-    }
-
-    @Test
-    public void shouldNavigationConfiguration() throws Exception {
-        final Map<Object, Object> testData = this.getTestData();
-        final YamlConfiguration config = new YamlConfiguration();
-        config.load(new StringReader(this.getTestInputData()));
-
-        assertEquals(testData.get("integer"), config.getInt("integer"));
-        assertEquals(testData.get("string"), config.getString("string"));
-        assertEquals(testData.get("long"), config.getLong("long"));
-        assertEquals(testData.get("true-boolean"), config.getBoolean("true-boolean"));
-        assertEquals(testData.get("false-boolean"), config.getBoolean("false-boolean"));
-        assertEquals(testData.get("list"), config.getList("list.item"));
-        assertEquals(testData.get("42"), config.getString("42"));
-
-        final Map<Object, Object> subData = this.getSubMap();
-        assertEquals(subData.get("sub-string"), config.getString("map.sub-string"));
-        assertEquals("String1", config.getString("map.sub-list.item(1).item(0)"));
-    }
-
-    @Test
-    public void shouldSupportXMLCompatibility() throws Exception {
-        final YamlConfiguration config = new YamlConfiguration();
-        config.setXmlCompatibility(true);
-        config.load(new StringReader(this.getTestInputData()));
-        assertEquals(Arrays.asList("testUser1-Data", "testUser2-Data"), config.getList("users.user.item"));
-    }
-
-    private String getTestInputData() {
-        final DumperOptions yamlOptions = new DumperOptions();
-        Yaml yaml = new Yaml(yamlOptions);
-
-        yamlOptions.setIndent(YamlConfiguration.DEFAULT_IDENT);
-        yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
-
-        return yaml.dump(this.getTestData());
-    }
-
-    private Map<Object, Object> getTestData() {
-        final HashMap<Object, Object> result = new LinkedHashMap<>();
-
-        result.put("integer", Integer.MIN_VALUE);
-        result.put("string", "String Value");
-        result.put("long", Long.MAX_VALUE);
-        result.put("true-boolean", true);
-        result.put("false-boolean", false);
-        result.put("list", Arrays.asList(1, 2, 3, 4, 5));
-        result.put("42", "The Answer");
-        result.put("map", getSubMap());
-
-        final Map<Object, Object> users = new LinkedHashMap<>();
-        users.put("testUser1", Arrays.asList("testUser1-Data"));
-        users.put("testUser2", Arrays.asList("testUser2-Data"));
-        result.put("users", users);
-
-        //result.put("tricky-list", Arrays.asList(Arrays.asList(Arrays.asList(leafMap.keySet()), leafMap.values())));
-
-        return result;
-    }
-
-    private Map<Object, Object> getSubMap() {
-        final Map<Object, Object> subMap = new LinkedHashMap<>();
-        subMap.put("sub-string", "The String!");
-
-        final Map<Object, Object> leafMap = new LinkedHashMap<>();
-        leafMap.put("test", "value");
-        leafMap.put("long", Long.MIN_VALUE);
-
-        subMap.put("sub-list", Arrays.asList(Integer.MIN_VALUE, Arrays.asList("String1", "String2"), Boolean.TRUE, leafMap));
-        return subMap;
-    }
-}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/iterator/ArrayIteratorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/iterator/ArrayIteratorTest.java
index 60ddd88..2293277 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/iterator/ArrayIteratorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/iterator/ArrayIteratorTest.java
@@ -25,6 +25,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -45,6 +46,21 @@
         assertFalse(itty.hasNext());
     }
 
+    @Test
+    public void shouldIterateAnArrayWithNull() {
+        final String[] arr = new String[3];
+        arr[0] = "test1";
+        arr[1] = "test2";
+        arr[2] = null;
+
+        final Iterator<String> itty = new ArrayIterator<>(arr);
+        assertEquals("test1", itty.next());
+        assertEquals("test2", itty.next());
+        assertNull(itty.next());
+
+        assertFalse(itty.hasNext());
+    }
+
     @Test(expected = FastNoSuchElementException.class)
     public void shouldThrowFastNoSuchElementException() {
         final Iterator<String> itty = new ArrayIterator<>(new String[0]);
diff --git a/gremlin-dotnet/glv/AnonymousTraversal.template b/gremlin-dotnet/glv/AnonymousTraversal.template
deleted file mode 100644
index 6b1de9c..0000000
--- a/gremlin-dotnet/glv/AnonymousTraversal.template
+++ /dev/null
@@ -1,59 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-using Gremlin.Net.Structure;
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-namespace Gremlin.Net.Process.Traversal
-{
-    /// <summary>
-    ///     An anonymous <see cref="GraphTraversal{SType, EType}" />.
-    /// </summary>
-    public static class __
-    {
-        /// <summary>
-        ///     Starts an empty <see cref="GraphTraversal{SType, EType}" />.
-        /// </summary>
-        public static GraphTraversal<object, object> Start()
-        {
-            return new GraphTraversal<object, object>();
-        }
-<% anonStepMethods.each { method -> %>
-        /// <summary>
-        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the <%= method.methodName %> step to that traversal.
-        /// </summary>
-        public static GraphTraversal<object, <%= method.t2 %>> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(<%= method.parameters %>)
-        {
-        <%  if (method.parameters.contains("params ")) {
-      %>    return <%= method.paramNames.last() %>.Length == 0
-                ? new GraphTraversal<object, <%= method.graphTraversalT2 %>>().<%= toCSharpMethodName.call(method.methodName) %><%= method.callGenericTypeArg %>(<%= method.paramNames.init().join(", ") %>)
-                : new GraphTraversal<object, <%= method.graphTraversalT2 %>>().<%= toCSharpMethodName.call(method.methodName) %><%= method.callGenericTypeArg %>(<%= method.paramNames.join(", ") %>);<%
-            }
-            else {
-      %>    return new GraphTraversal<object, <%= method.graphTraversalT2 %>>().<%= toCSharpMethodName.call(method.methodName) %><%= method.callGenericTypeArg %>(<%= method.paramNames.join(", ") %>);<%
-            } %>            
-        }
-<% } %>
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/Enum.template b/gremlin-dotnet/glv/Enum.template
deleted file mode 100644
index e785cd0..0000000
--- a/gremlin-dotnet/glv/Enum.template
+++ /dev/null
@@ -1,69 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections.Generic;
-
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    public class <%= enumClass.simpleName %> : <%= implementedTypes %>
-    {
-        private <%= enumClass.simpleName %>(string enumValue)
-            : base("<%= enumClass.simpleName %>", enumValue)
-        {
-        }
-<%
-    def toCSharpName = { enumClass, itemName ->
-        if (enumClass.equals(directionClass)) {
-            itemName = itemName.toLowerCase()
-        }
-
-        return itemName.substring(0, 1).toUpperCase() + itemName.substring(1)
-    }
-    constants.each { value -> %>
-        public static ${enumClass.simpleName} ${toCSharpName(enumClass, value.name())} => new ${enumClass.simpleName}("${value.name()}");
-<%  }%>
-        private static readonly IDictionary<string, <%= enumClass.simpleName %>> Properties = new Dictionary<string, <%= enumClass.simpleName %>>
-        {<%  constants.each { value -> %>
-            { "${value.name()}", ${toCSharpName(enumClass, value.name())} },<%  }%>
-        };
-
-        /// <summary>
-        /// Gets the <%= enumClass.simpleName %> enumeration by value.
-        /// </summary>
-        public static <%= enumClass.simpleName %> GetByValue(string value)
-        {
-            if (!Properties.TryGetValue(value, out var property))
-            {
-                throw new ArgumentException(\$"No matching <%= enumClass.simpleName%> for value '{value}'");
-            }
-            return property;
-        }
-    }
-
-
-#pragma warning restore 1591
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/GraphTraversal.template b/gremlin-dotnet/glv/GraphTraversal.template
deleted file mode 100644
index 430968d..0000000
--- a/gremlin-dotnet/glv/GraphTraversal.template
+++ /dev/null
@@ -1,92 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-using System.Linq;
-using Gremlin.Net.Structure;
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-namespace Gremlin.Net.Process.Traversal
-{
-    /// <summary>
-    ///     Graph traversals are the primary way in which graphs are processed.
-    /// </summary>
-    public class GraphTraversal<S, E> : DefaultTraversal<S, E>
-    {
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="GraphTraversal{SType, EType}" /> class.
-        /// </summary>
-        public GraphTraversal()
-            : this(new List<ITraversalStrategy>(), new Bytecode())
-        {
-        }
-
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="GraphTraversal{SType, EType}" /> class.
-        /// </summary>
-        /// <param name="traversalStrategies">The traversal strategies to be used by this graph traversal at evaluation time.</param>
-        /// <param name="bytecode">The <see cref="Bytecode" /> associated with the construction of this graph traversal.</param>
-        public GraphTraversal(ICollection<ITraversalStrategy> traversalStrategies, Bytecode bytecode)
-        {
-            TraversalStrategies = traversalStrategies;
-            Bytecode = bytecode;
-        }
-
-        private static GraphTraversal<S2, E2> Wrap<S2, E2>(GraphTraversal<S, E> traversal)
-        {
-            if (typeof(S2) == typeof(S) && typeof(E2) == typeof(E))
-            {
-                return traversal as GraphTraversal<S2, E2>;
-            }
-            // New wrapper
-            return new GraphTraversal<S2, E2>(traversal.TraversalStrategies, traversal.Bytecode);
-        }
-
-<% graphStepMethods.each { method -> %>
-        /// <summary>
-        ///     Adds the <%= method.methodName %> step to this <see cref="GraphTraversal{SType, EType}" />.
-        /// </summary>
-        public GraphTraversal<$method.t1, $method.t2> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %> (<%= method.parameters %>)
-        {
-        <%  if (method.parameters.contains("params ")) {
-      %>    var args = new List<object>(<%= method.paramNames.init().size() %> + <%= method.paramNames.last() %>.Length) {<%= method.paramNames.init().join(", ") %>};
-            args.AddRange(<%= method.paramNames.last() %><% if (method.isArgsCastNecessary) { %>.Cast<object>()<% } %>);
-            Bytecode.AddStep("<%= method.methodName %>", args.ToArray());<%
-            }
-            else {
-      %>    Bytecode.AddStep("<%= method.methodName %>"<% if (method.parameters) out << ', '+ method.paramNames.join(", ") %>);<%
-            }
-        %>
-            return Wrap<$method.t1, $method.t2>(this);
-        }
-<% } %>
-
-        /// <summary>
-        /// Make a copy of a traversal that is reset for iteration.
-        /// </summary>
-        public GraphTraversal<S, E> Clone()
-        {
-            return new GraphTraversal<S, E>(TraversalStrategies, new Bytecode(Bytecode));
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/GraphTraversalSource.template b/gremlin-dotnet/glv/GraphTraversalSource.template
deleted file mode 100644
index f3093e5..0000000
--- a/gremlin-dotnet/glv/GraphTraversalSource.template
+++ /dev/null
@@ -1,149 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Gremlin.Net.Process.Remote;
-using Gremlin.Net.Process.Traversal.Strategy.Decoration;
-using Gremlin.Net.Structure;
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    /// <summary>
-    ///     A <see cref="GraphTraversalSource" /> is the primary DSL of the Gremlin traversal machine.
-    ///     It provides access to all the configurations and steps for Turing complete graph computing.
-    /// </summary>
-    public class GraphTraversalSource
-    {
-        /// <summary>
-        ///     Gets or sets the traversal strategies associated with this graph traversal source.
-        /// </summary>
-        public ICollection<ITraversalStrategy> TraversalStrategies { get; set; }
-
-        /// <summary>
-        ///     Gets or sets the <see cref="Traversal.Bytecode" /> associated with the current state of this graph traversal
-        ///     source.
-        /// </summary>
-        public Bytecode Bytecode { get; set; }
-
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="GraphTraversalSource" /> class.
-        /// </summary>
-        public GraphTraversalSource()
-            : this(new List<ITraversalStrategy>(), new Bytecode())
-        {
-        }
-
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="GraphTraversalSource" /> class.
-        /// </summary>
-        /// <param name="traversalStrategies">The traversal strategies associated with this graph traversal source.</param>
-        /// <param name="bytecode">
-        ///     The <see cref="Traversal.Bytecode" /> associated with the current state of this graph traversal
-        ///     source.
-        /// </param>
-        public GraphTraversalSource(ICollection<ITraversalStrategy> traversalStrategies, Bytecode bytecode)
-        {
-            TraversalStrategies = traversalStrategies;
-            Bytecode = bytecode;
-        }
-
-<% sourceStepMethods.each{ method -> %>
-        public GraphTraversalSource <%= toCSharpMethodName.call(method.methodName) %>(<%= method.parameters %>)
-        {
-            var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
-                                                  new Bytecode(Bytecode));
-            <%  if (method.parameters.contains("params ")) {
-          %>var args = new List<object>(<%= method.paramNames.init().size() %> + <%= method.paramNames.last() %>.Length) {<%= method.paramNames.init().join(", ") %>};
-            args.AddRange(<%= method.paramNames.last() %>);
-            source.Bytecode.AddSource("<%= method.methodName %>", args.ToArray());<%
-            }
-            else {
-          %>source.Bytecode.AddSource("<%= method.methodName %>"<% if (method.parameters) out << ', '+ method.paramNames.join(", ") %>);<%
-            }
-        %>
-            return source;
-        }
-<% } %>
-        [Obsolete("Use the Bindings class instead.", false)]
-        public GraphTraversalSource WithBindings(object bindings)
-        {
-            return this;
-        }
-
-        /// <summary>
-        ///     Configures the <see cref="GraphTraversalSource" /> as a "remote" to issue the
-        ///     <see cref="GraphTraversal{SType, EType}" /> for execution elsewhere.
-        /// </summary>
-        /// <param name="remoteConnection">
-        ///     The <see cref="IRemoteConnection" /> instance to use to submit the
-        ///     <see cref="GraphTraversal{SType, EType}" />.
-        /// </param>
-        /// <returns>A <see cref="GraphTraversalSource" /> configured to use the provided <see cref="IRemoteConnection" />.</returns>
-        public GraphTraversalSource WithRemote(IRemoteConnection remoteConnection)
-        {
-            var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
-                new Bytecode(Bytecode));
-            source.TraversalStrategies.Add(new RemoteStrategy(remoteConnection));
-            return source;
-        }
-
-        /// <summary>
-        ///     Add a GraphComputer class used to execute the traversal.
-        ///     This adds a <see cref="VertexProgramStrategy" /> to the strategies.
-        /// </summary>
-        public GraphTraversalSource WithComputer(string graphComputer = null, int? workers = null, string persist = null,
-            string result = null, ITraversal vertices = null, ITraversal edges = null,
-            Dictionary<string, dynamic> configuration = null)
-        {
-            return WithStrategies(new VertexProgramStrategy(graphComputer, workers, persist, result, vertices, edges, configuration));
-        }
-
-<% sourceSpawnMethods.each { method -> %>
-        /// <summary>
-        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the <%= method.methodName %> step to that
-        ///     traversal.
-        /// </summary>
-        public GraphTraversal<$method.t1, $method.t2> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(<%= method.parameters %>)
-        {
-            var traversal = new GraphTraversal<$method.t1, $method.t2>(TraversalStrategies, new Bytecode(Bytecode));
-            <%  if (method.parameters.contains("params ")) {
-          %>var args = new List<object>(<%= method.paramNames.init().size() %> + <%= method.paramNames.last() %>.Length) {<%= method.paramNames.init().join(", ") %>};
-            args.AddRange(<%= method.paramNames.last() %><% if (method.isArgsCastNecessary) { %>.Cast<object>()<% } %>);
-            traversal.Bytecode.AddStep("<%= method.methodName %>", args.ToArray());<%
-            }
-            else {
-      %>    traversal.Bytecode.AddStep("<%= method.methodName %>"<% if (method.parameters) out << ', '+ method.paramNames.join(", ") %>);<%
-            }
-        %>
-            return traversal;
-        }
-<% } %>
-    }
-    
-#pragma warning restore 1591
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/Gremlin.Net.Template.csproj.template b/gremlin-dotnet/glv/Gremlin.Net.Template.csproj.template
deleted file mode 100644
index 3f694f6..0000000
--- a/gremlin-dotnet/glv/Gremlin.Net.Template.csproj.template
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
-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.
--->
-
-<!--  THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml -->
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <!-- We need both reference elements until this is resolved: https://github.com/dotnet/sdk/issues/1151 -->
-    <ProjectReference Include="../Gremlin.Net/Gremlin.Net.csproj" />
-    <PackageReference Include="Gremlin.Net" Version="$projectVersion" />
-  </ItemGroup>
-
-</Project>
diff --git a/gremlin-dotnet/glv/Gremlin.Net.Template.nuspec.template b/gremlin-dotnet/glv/Gremlin.Net.Template.nuspec.template
deleted file mode 100644
index d77663b..0000000
--- a/gremlin-dotnet/glv/Gremlin.Net.Template.nuspec.template
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
-    <metadata>
-        <id>Gremlin.Net.Template</id>
-        <title>Gremlin.Net Template</title>
-        <version>$projectVersion</version>
-        <description>Gremlin.Net template to create a console application with dotnet new.</description>
-        <authors>Apache TinkerPop</authors>
-        <license type="expression">Apache-2.0</license>
-        <projectUrl>http://tinkerpop.apache.org</projectUrl>
-        <tags>TinkerPop Gremlin Gremlin.Net</tags>
-        <packageTypes>
-            <packageType name="Template" />
-        </packageTypes>
-    </metadata>
-    <files>
-        <file src=".template.config/template.json" target="content/.template.config" />
-        <file src="Gremlin.Net.Template.csproj" target="content" />
-        <file src="*.cs" target="content" />
-        <file src="../../LICENSE" target="LICENSE"/>
-        <file src="../../NOTICE" target="NOTICE"/>
-    </files>
-</package>
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/Gremlin.Net.csproj.template b/gremlin-dotnet/glv/Gremlin.Net.csproj.template
deleted file mode 100644
index 1799a5a..0000000
--- a/gremlin-dotnet/glv/Gremlin.Net.csproj.template
+++ /dev/null
@@ -1,92 +0,0 @@
-<!--
-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.
--->
-
-<!--  THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml -->
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup Label="Build">
-    <TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-    <GenerateDocumentationFile>true</GenerateDocumentationFile>
-  </PropertyGroup>
-
-  <PropertyGroup Label="Package">
-    <Version>$projectVersion</Version>
-    <FileVersion><%= (projectVersion =~ /(\d+\.\d+\.\d+).*/)[0][1] %>.0</FileVersion>
-    <AssemblyVersion><%= (projectVersion =~ /(\d+\.\d+)\.*/)[0][1] %>.0.0</AssemblyVersion>
-    <Title>Gremlin.Net</Title>
-    <Authors>Apache TinkerPop</Authors>
-    <Description>Gremlin.Net for Apache TinkerPop™ is a language variant and driver for .NET.
-
-Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP). Gremlin is the graph traversal language of TinkerPop. It can be described as a functional, data-flow language that enables users to succinctly express complex traversals on (or queries of) their application's property graph.
-
-Gremlin.Net implements Gremlin within .NET. C# syntax has the same constructs as Java including "dot notation" for function chaining (a.b.c), round bracket function arguments (a(b,c)), and support for global namespaces (a(b()) vs a(__.b())). As such, anyone familiar with Gremlin-Java will immediately be able to work with Gremlin.Net. Moreover, there are a few added constructs to Gremlin.Net that make traversals a bit more succinct.
-
-Gremlin.Net is designed to connect to a "server" that is hosting a TinkerPop-enabled graph system. That "server" could be Gremlin Server
-
-https://tinkerpop.apache.org/docs/current/reference/#gremlin-server
-
-or a remote graph provider that exposes protocols by which Gremlin.Net can connect.
-
-Please see the Reference Documentation of Apache TinkerPop for more information on usage: https://tinkerpop.apache.org/docs/current/reference
-
-and use our Google Group gremlin-users if there are any questions: https://s.apache.org/c8hru
-
-The Gremlin language allows users to write highly expressive graph traversals and has a broad list of functions that cover a wide body of features. The Reference Documentation describes these functions and other aspects of the TinkerPop ecosystem including some specifics on Gremlin in .NET itself:
-
-https://s.apache.org/pgbwu
-
-Most of the examples found in the documentation use Groovy language syntax in the Gremlin Console. For the most part, these examples should generally translate to C# with some logical modification:
-
-https://s.apache.org/10v91
-
-Given the strong correspondence between canonical Gremlin in Java and its variants like C#, there is a limited amount of C#-specific documentation and examples. This strong correspondence among variants ensures that the general Gremlin reference documentation is applicable to all variants and that users moving between development languages can easily adopt the Gremlin variant for that language.
-
-NOTE that versions suffixed with "-rc" are considered release candidates (i.e. pre-alpha, alpha, beta, etc.) and thus for early testing purposes only.</Description>
-    <AssemblyOriginatorKeyFile>../../build/tinkerpop.snk</AssemblyOriginatorKeyFile>
-    <SignAssembly>true</SignAssembly>
-    <PackageId>Gremlin.Net</PackageId>
-    <PackageTags>gremlin;tinkerpop;apache</PackageTags>
-    <PackageProjectUrl>https://tinkerpop.apache.org</PackageProjectUrl>
-    <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
-    <PackageIcon>gremlin-dotnet-logo_256x256.png</PackageIcon>
-    <PackageIconUrl>https://tinkerpop.apache.org/docs/current/images/gremlin-dotnet-logo_256x256.png</PackageIconUrl>
-    <RepositoryUrl>https://github.com/apache/tinkerpop</RepositoryUrl>
-    <PublishRepositoryUrl>true</PublishRepositoryUrl>    
-    <AllowedOutputExtensionsInPackageBuildOutputFolder>\$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
-    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
-    <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
-    <PackageReference Include="Polly" Version="7.2.0" />
-  </ItemGroup>
-
-  <ItemGroup Condition="'\$(TargetFramework)' == 'netstandard1.3'">
-    <PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
-    <PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />
-    <PackageReference Include="System.Reflection.TypeExtensions" Version="4.3.0" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <None Include="../../LICENSE" Pack="true" PackagePath="" />
-    <None Include="../../NOTICE" Pack="true" PackagePath="" />
-    <None Include="../../../docs/static/images/gremlin-dotnet-logo_256x256.png" Pack="true" PackagePath="" />
-  </ItemGroup>
-
-</Project>
diff --git a/gremlin-dotnet/glv/P.template b/gremlin-dotnet/glv/P.template
deleted file mode 100644
index 3140475..0000000
--- a/gremlin-dotnet/glv/P.template
+++ /dev/null
@@ -1,113 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    /// <summary>
-    ///     A <see cref="P" /> is a predicate of the form Func&lt;object, bool&gt;.
-    ///     That is, given some object, return true or false.
-    /// </summary>
-    public class P : IPredicate
-    {
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="P" /> class.
-        /// </summary>
-        /// <param name="operatorName">The name of the predicate.</param>
-        /// <param name="value">The value of the predicate.</param>
-        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
-        public P(string operatorName, dynamic value, P other = null)
-        {
-            OperatorName = operatorName;
-            Value = value;
-            Other = other;
-        }
-
-        /// <summary>
-        ///     Gets the name of the predicate.
-        /// </summary>
-        public string OperatorName { get; }
-
-        /// <summary>
-        ///     Gets the value of the predicate.
-        /// </summary>
-        public dynamic Value { get; }
-
-        /// <summary>
-        ///     Gets an optional other predicate that is used as an argument for this predicate.
-        /// </summary>
-        public P Other { get; }
-
-        /// <summary>
-        ///     Returns a composed predicate that represents a logical AND of this predicate and another.
-        /// </summary>
-        /// <param name="otherPredicate">A predicate that will be logically-ANDed with this predicate.</param>
-        /// <returns>The composed predicate.</returns>
-        public P And(P otherPredicate)
-        {
-            return new P("and", this, otherPredicate);
-        }
-
-        /// <summary>
-        ///     Returns a composed predicate that represents a logical OR of this predicate and another.
-        /// </summary>
-        /// <param name="otherPredicate">A predicate that will be logically-ORed with this predicate.</param>
-        /// <returns>The composed predicate.</returns>
-        public P Or(P otherPredicate)
-        {
-            return new P("or", this, otherPredicate);
-        }
-<% pmethods.findAll{ !(it in ["within", "without"]) }.each { method -> %>
-        public static P <%= toCSharpMethodName.call(method) %>(params object[] args)
-        {
-            var value = args.Length == 1 ? args[0] : args;
-            return new P("<%= method %>", value);
-        }
-<% } %><% pmethods.findAll{ it in ["within", "without"] }.each { method -> %>
-        public static P <%= toCSharpMethodName.call(method) %>(params object[] args)
-        {
-            var x = args.Length == 1 && args[0] is ICollection collection ? collection : args;
-            return new P("<%= method %>", ToGenericList(x));
-        }
-<% } %>
-
-        private static List<object> ToGenericList(IEnumerable collection)
-        {
-            return collection?.Cast<object>().ToList() ?? Enumerable.Empty<object>().ToList();
-        }
-
-        /// <inheritdoc />
-        public override string ToString()
-        {
-            return Other == null ? \$"{OperatorName}({Value})" : \$"{OperatorName}({Value},{Other})";
-        }
-    }
-
-#pragma warning restore 1591
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/TextP.template b/gremlin-dotnet/glv/TextP.template
deleted file mode 100644
index 3e289f6..0000000
--- a/gremlin-dotnet/glv/TextP.template
+++ /dev/null
@@ -1,71 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    /// <summary>
-    ///     A <see cref="TextP" /> is a predicate of the form Func&lt;string, bool&gt;.
-    ///     That is, given some string, return true or false.
-    /// </summary>
-    public class TextP : P
-    {
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="TextP" /> class.
-        /// </summary>
-        /// <param name="operatorName">The name of the predicate.</param>
-        /// <param name="value">The value of the predicate.</param>
-        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
-        public TextP(string operatorName, string value, P other = null) : base(operatorName, value, other)
-        {
-        }
-
-<% tpmethods.each { method -> %>
-        public static TextP <%= toCSharpMethodName.call(method) %>(string value)
-        {
-            return new TextP("<%= method %>", value);
-        }
-<% } %>
-
-        private static T[] ToGenericArray<T>(ICollection<T> collection)
-        {
-            return collection?.ToArray() ?? new T[0];
-        }
-
-        /// <inheritdoc />
-        public override string ToString()
-        {
-            return Other == null ? \$"{OperatorName}({Value})" : \$"{OperatorName}({Value},{Other})";
-        }
-    }
-
-#pragma warning restore 1591
-}
diff --git a/gremlin-dotnet/glv/Token.template b/gremlin-dotnet/glv/Token.template
deleted file mode 100644
index b86634a..0000000
--- a/gremlin-dotnet/glv/Token.template
+++ /dev/null
@@ -1,43 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    public class <%= tokenName %>
-    {
-        <% tokenFields.each {k,v -> %>
-            public const String <%= k %> = "<%= v %>";
-        <% } %>
-    }
-
-#pragma warning restore 1591
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/glv/WithOptions.template b/gremlin-dotnet/glv/WithOptions.template
deleted file mode 100644
index d8dd6bd..0000000
--- a/gremlin-dotnet/glv/WithOptions.template
+++ /dev/null
@@ -1,47 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-
-namespace Gremlin.Net.Process.Traversal.Step.Util
-{
-#pragma warning disable 1591
-
-    /// <summary>
-    ///     Configuration options to be passed to the <c>With()</c> modulator.
-    /// </summary>
-    public class WithOptions
-    {
-<% withOptions.each { field -> %>
-
-        public static readonly <%= field.type %> <%= field.name %> = <%= field.value %>;
-<% } %>
-    }
-
-#pragma warning restore 1591
-}
diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy
deleted file mode 100644
index 26daa58..0000000
--- a/gremlin-dotnet/glv/generate.groovy
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * 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.
- */
-
-import org.apache.tinkerpop.gremlin.jsr223.CoreImports
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ConnectedComponent
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressure
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPath
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
-import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.TextP
-import org.apache.tinkerpop.gremlin.process.traversal.IO
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
-import org.apache.tinkerpop.gremlin.structure.Direction
-import java.lang.reflect.Modifier
-import java.lang.reflect.TypeVariable
-import java.lang.reflect.GenericArrayType
-
-def toCSharpTypeMap = ["Long": "long",
-                       "Double": "double",
-                       "Integer": "int",
-                       "String": "string",
-                       "boolean": "bool",
-                       "Object": "object",
-                       "String[]": "string[]",
-                       "Object[]": "object[]",
-                       "Class": "Type",
-                       "Class[]": "Type[]",
-                       "java.util.Map<java.lang.String, java.lang.Object>": "IDictionary<string, object>",
-                       "java.util.Map<java.lang.String, E2>": "IDictionary<string, E2>",
-                       "java.util.Map<java.lang.String, B>": "IDictionary<string, E2>",
-                       "java.util.Map<java.lang.Object, E2>": "IDictionary<object, E2>",
-                       "java.util.Map<java.lang.Object, B>": "IDictionary<object, E2>",
-                       "java.util.List<E>": "IList<E>",
-                       "java.util.List<A>": "IList<E2>",
-                       "java.util.Map<K, V>": "IDictionary<K, V>",
-                       "java.util.Collection<E2>": "ICollection<E2>",
-                       "java.util.Collection<B>": "ICollection<E2>",
-                       "java.util.Map<K, java.lang.Long>": "IDictionary<K, long>",
-                       "TraversalMetrics": "E2",
-                       "Traversal": "ITraversal",
-                       "Traversal[]": "ITraversal[]",
-                       "Predicate": "IPredicate",
-                       "P": "P",
-                       "TextP": "TextP",
-                       "TraversalStrategy": "ITraversalStrategy",
-                       "TraversalStrategy[]": "ITraversalStrategy[]",
-                       "Function": "IFunction",
-                       "BiFunction": "IBiFunction",
-                       "UnaryOperator": "IUnaryOperator",
-                       "BinaryOperator": "IBinaryOperator",
-                       "Consumer": "IConsumer",
-                       "Supplier": "ISupplier",
-                       "Comparator": "IComparator",
-                       "VertexProgram": "object"]
-
-def useE2 = ["E2", "E2"]
-def methodsWithSpecificTypes = ["constant": useE2,
-                                "limit": useE2,
-                                "mean": useE2,
-                                "optional": useE2,
-                                "range": useE2,
-                                "skip": useE2,
-                                "sum": useE2,
-                                "tail": useE2,
-                                "unfold": useE2,
-                                "valueMap": ["IDictionary<TKey, TValue>", "TKey, TValue"],]
-
-def getCSharpGenericTypeParam = { typeName ->
-    def tParam = ""
-    if (typeName.contains("E2")) {
-        tParam = "<E2>"
-    }
-    else if (typeName.contains("<K, V>")) {
-        tParam = "<K, V>"
-    }
-    else if (typeName.contains("<K, ")) {
-        tParam = "<K>"
-    }
-    else if (typeName.contains("S")) {
-        tParam = "<S>"
-    }
-    else if (typeName.contains("A")) {
-        tParam = "<A>"
-    }
-    return tParam
-}
-
-def toCSharpType = { name ->
-    String typeName = toCSharpTypeMap.getOrDefault(name, name)
-    if (typeName.equals(name) && (typeName.contains("? extends") || typeName.equals("Tree"))) {
-        typeName = "E2"
-    }
-    return typeName
-}
-
-def toCSharpMethodName = { symbol -> (String) Character.toUpperCase(symbol.charAt(0)) + symbol.substring(1) }
-
-def toCSharpValue = { type, value ->
-  type == String.class && value != null ? ('"' + value + '"') : value
-}
-
-def getJavaGenericTypeParameterTypeNames = { method ->
-    def typeArguments = method.genericReturnType.actualTypeArguments
-    return typeArguments.
-            collect { (it instanceof Class) ? ((Class)it).simpleName : it.typeName }.
-            collect { name ->
-                if (name.equals("A")) {
-                    name = "object"
-                }
-                else if (name.equals("B")) {
-                    name = "E2"
-                }
-                name
-            }
-}
-
-def getJavaParameterTypeNames = { method ->
-    return method.parameters.
-            collect { param ->
-                param.type.simpleName
-            }
-}
-
-def toCSharpParamString = { param, genTypeName ->
-    String csharpParamTypeName = genTypeName
-    if (csharpParamTypeName == null){
-        csharpParamTypeName = toCSharpType(param.type.simpleName)
-    }
-    else if (csharpParamTypeName == "M") {
-        csharpParamTypeName = "object"
-    }
-    else if (csharpParamTypeName == "A[]") {
-        csharpParamTypeName = "object[]"
-    }
-    else if (csharpParamTypeName == "A" || csharpParamTypeName == "B") {
-        csharpParamTypeName = "E2"
-    }
-    "${csharpParamTypeName} ${param.name}"
-    }
-
-def getJavaParamTypeString = { method ->
-    getJavaParameterTypeNames(method).join(",")
-}
-
-def getCSharpParamTypeString = { method ->
-    return method.parameters.
-            collect { param ->
-                toCSharpType(param.type.simpleName)
-            }.join(",")
-}
-
-def getCSharpParamString = { method, useGenericParams ->
-    def parameters = method.parameters
-    if (parameters.length == 0)
-        return ""
-
-    def genericTypes = method.getGenericParameterTypes()
-    def csharpParameters = parameters.
-            toList().indexed().
-            collect { index, param ->
-                String genTypeName = null
-                if (useGenericParams) {
-                    def genType = genericTypes[index]
-                    if (genType instanceof TypeVariable<?>) {
-                        genTypeName = ((TypeVariable<?>)genType).name
-                    }
-                    else if (genType instanceof GenericArrayType) {
-                        if (((GenericArrayType)genType).getGenericComponentType() instanceof TypeVariable<?>) {
-                            genTypeName = ((TypeVariable<?>)((GenericArrayType)genType).getGenericComponentType()).name + "[]"
-                        }
-                    }
-                }
-                toCSharpParamString(param, genTypeName)
-            }.
-            toArray()
-
-    if (method.isVarArgs()) {
-        def lastIndex = csharpParameters.length-1
-        csharpParameters[lastIndex] = "params " + csharpParameters[lastIndex]
-    }
-
-    csharpParameters.join(", ")
-}
-
-def getParamNames = { parameters ->
-    return parameters.
-        collect { param ->
-            param.name
-        }
-}
-
-def isParamsArgCastNecessary = { parameterString ->
-    if (parameterString.contains("params ")) {
-        def paramsType = parameterString.substring(parameterString.indexOf("params ") + "params ".length(), parameterString.indexOf("[]"))
-        return paramsType == "E" || paramsType == "S" 
-    }
-    return false
-}
-
-def hasMethodNoGenericCounterPartInGraphTraversal = { method ->
-    def parameterTypeNames = getJavaParameterTypeNames(method)
-    if (method.name.equals("fold")) {
-        return parameterTypeNames.size() == 0
-    }
-    return false
-}
-
-def t2withSpecialGraphTraversalt2 = ["IList<E2>": "E2"]
-
-def getGraphTraversalT2ForT2 = { t2 ->
-    if (t2withSpecialGraphTraversalt2.containsKey(t2)) {
-        return t2withSpecialGraphTraversalt2.get(t2)
-    }
-    return t2
-}
-
-def gatherTokensFrom = { tokenClasses ->
-    def m = [:]
-    tokenClasses.each { tc -> m << [(tc.simpleName) : tc.getFields().sort{ a, b -> a.name <=> b.name }.collectEntries{ f -> [(f.name) : f.get(null)]}]}
-    return m
-}
-
-def binding = ["pmethods": P.class.getMethods().
-        findAll { Modifier.isStatic(it.getModifiers()) }.
-        findAll { P.class.isAssignableFrom(it.returnType) }.
-        collect { it.name }.
-        unique().
-        sort { a, b -> a <=> b },
-               "tpmethods": TextP.class.getMethods().
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { TextP.class.isAssignableFrom(it.returnType) }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS
-                        findAll { GraphTraversalSource.class.equals(it.returnType) }.
-                        findAll {
-                            !it.name.equals("clone") &&
-                                    !it.name.equals(TraversalSource.Symbols.withRemote) &&
-                                    !it.name.equals(TraversalSource.Symbols.withComputer)
-                        }.
-                // Select unique combination of C# parameter types and sort by Java parameter type combination
-                        sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }.
-                        unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }.
-                        collect { javaMethod ->
-                            def parameters = getCSharpParamString(javaMethod, false)
-                            def paramNames = getParamNames(javaMethod.parameters)
-                            return ["methodName": javaMethod.name, "parameters":parameters, "paramNames":paramNames]
-                        },
-               "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS
-                        findAll { GraphTraversal.class.equals(it.returnType) }.
-                // Select unique combination of C# parameter types and sort by Java parameter type combination
-                        sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }.
-                        unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }.
-                        collect { javaMethod ->
-                            def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod)
-                            def t1 = toCSharpType(typeNames[0])
-                            def t2 = toCSharpType(typeNames[1])
-                            def tParam = getCSharpGenericTypeParam(t2)
-                            def parameters = getCSharpParamString(javaMethod, true)
-                            def paramNames = getParamNames(javaMethod.parameters)
-                            def isArgsCastNecessary = isParamsArgCastNecessary(parameters)
-                            return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "isArgsCastNecessary":isArgsCastNecessary]
-                        },
-               "graphStepMethods": GraphTraversal.getMethods().
-                        findAll { GraphTraversal.class.equals(it.returnType) }.
-                        findAll { !it.name.equals("clone") && !it.name.equals("iterate") }.
-                // Select unique combination of C# parameter types and sort by Java parameter type combination
-                        sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }.
-                        unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }.
-                        collect { javaMethod ->
-                            def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod)
-                            def t1 = toCSharpType(typeNames[0])
-                            def t2 = toCSharpType(typeNames[1])
-                            def tParam = getCSharpGenericTypeParam(t2)
-                            def specificTypes = methodsWithSpecificTypes.get(javaMethod.name)
-                            if (specificTypes) {
-                                t2 = specificTypes[0]
-                                tParam = specificTypes.size() > 1 ? "<" + specificTypes[1] + ">" : ""
-                            }
-                            def parameters = getCSharpParamString(javaMethod, true)
-                            def paramNames = getParamNames(javaMethod.parameters)
-                            def isArgsCastNecessary = isParamsArgCastNecessary(parameters)
-                            return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "isArgsCastNecessary":isArgsCastNecessary]
-                        },
-               "anonStepMethods": __.class.getMethods().
-                        findAll { GraphTraversal.class.equals(it.returnType) }.
-                        findAll { Modifier.isStatic(it.getModifiers()) }.
-                        findAll { !it.name.equals("__") && !it.name.equals("start") }.
-                // Select unique combination of C# parameter types and sort by Java parameter type combination
-                        sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }.
-                        unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }.
-                        collect { javaMethod ->
-                            def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod)
-                            def t2 = toCSharpType(typeNames[1])
-                            def tParam = getCSharpGenericTypeParam(t2)
-                            def specificTypes = methodsWithSpecificTypes.get(javaMethod.name)
-                            if (specificTypes) {
-                                t2 = specificTypes[0]
-                                tParam = specificTypes.size() > 1 ? "<" + specificTypes[1] + ">" : ""
-                            }
-                            def parameters = getCSharpParamString(javaMethod, true)
-                            def paramNames = getParamNames(javaMethod.parameters)
-                            def callGenericTypeArg = hasMethodNoGenericCounterPartInGraphTraversal(javaMethod) ? "" : tParam
-                            def graphTraversalT2 = getGraphTraversalT2ForT2(t2)
-                            return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "callGenericTypeArg":callGenericTypeArg, "graphTraversalT2":graphTraversalT2]
-                        },
-               "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
-               "toCSharpMethodName": toCSharpMethodName,
-               "withOptions": WithOptions.getDeclaredFields().
-                        collect {["type": toCSharpType(it.type.simpleName), "name": toCSharpMethodName(it.name), "value": toCSharpValue(it.type, it.get(null))]}]
-
-def engine = new groovy.text.GStringTemplateEngine()
-def traversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversal.template")).make(binding)
-def traversalFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs")
-traversalFile.newWriter().withWriter{ it << traversalTemplate }
-
-def graphTraversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversalSource.template")).make(binding)
-def graphTraversalFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs")
-graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate }
-
-def anonymousTraversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/AnonymousTraversal.template")).make(binding)
-def anonymousTraversalFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/__.cs")
-anonymousTraversalFile.newWriter().withWriter{ it << anonymousTraversalTemplate }
-
-def pTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/P.template")).make(binding)
-def pFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/P.cs")
-pFile.newWriter().withWriter{ it << pTemplate }
-
-def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TextP.template")).make(binding)
-def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TextP.cs")
-tpFile.newWriter().withWriter{ it << tpTemplate }
-
-def withOptionsTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/WithOptions.template")).make(binding)
-def withOptionsFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/WithOptions.cs")
-withOptionsFile.newWriter().withWriter{ it << withOptionsTemplate }
-
-binding.tokens.each {k,v ->
-    def tokenTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Token.template")).make([tokenFields: v, tokenName: k])
-    def tokenFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/${k}.cs")
-    tokenFile.newWriter().withWriter{ it << tokenTemplate }
-}
-
-def createEnum = { enumClass ->
-    def b = ["enumClass": enumClass,
-             "implementedTypes": enumClass.getInterfaces().
-                    collect { it.getSimpleName() }.
-                    findAll { toCSharpTypeMap.containsKey(it) }.
-                    findAll { toCSharpTypeMap[it] != "object" }.
-                    sort { a, b -> a <=> b }.
-                    collect(["EnumWrapper"]) { typeName ->
-                        return toCSharpTypeMap[typeName]
-                    }.join(", "),
-             "constants": enumClass.getEnumConstants().
-                    sort { a, b -> a.name() <=> b.name() },
-             "directionClass": Direction.class ]
-
-    def enumTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Enum.template")).make(b)
-    def enumFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/" + enumClass.getSimpleName() + ".cs")
-    enumFile.newWriter().withWriter{ it << enumTemplate }
-}
-
-CoreImports.getClassImports().findAll { Enum.class.isAssignableFrom(it) }.
-        sort { a, b -> a.getSimpleName() <=> b.getSimpleName() }.
-        each { createEnum(it) }
-
-def determineVersion = {
-    def env = System.getenv()
-    def mavenVersion = env.containsKey("TP_RELEASE_VERSION") ? env.get("DOTNET_RELEASE_VERSION") : "${projectVersion}"
-
-    // only want to generate a timestamp for the version if this is a nuget deploy
-    if (!mavenVersion.endsWith("-SNAPSHOT") || null == System.getProperty("nuget")) return mavenVersion
-
-    return mavenVersion.replace("-SNAPSHOT", "-dev-" + System.currentTimeMillis())
-}
-
-def versionToUse = determineVersion()
-def csprojTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.csproj.template")).make(["projectVersion":versionToUse])
-def csprojFile = new File("${projectBaseDir}/src/Gremlin.Net/Gremlin.Net.csproj")
-csprojFile.newWriter().withWriter{ it << csprojTemplate }
-def templateCsprojTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.Template.csproj.template")).make(["projectVersion":versionToUse])
-def templateCsprojFile = new File("${projectBaseDir}/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj")
-templateCsprojFile.newWriter().withWriter{ it << templateCsprojTemplate }
-def nuspecTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.Template.nuspec.template")).make(["projectVersion":versionToUse])
-def nuspecFile = new File("${projectBaseDir}/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec")
-nuspecFile.newWriter().withWriter{ it << nuspecTemplate }
diff --git a/gremlin-dotnet/pom.xml b/gremlin-dotnet/pom.xml
index 44c0e6a..bf5609c 100644
--- a/gremlin-dotnet/pom.xml
+++ b/gremlin-dotnet/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-dotnet</artifactId>
     <name>Apache TinkerPop :: Gremlin.Net</name>
@@ -59,54 +59,6 @@
                 <artifactId>dotnet-maven-plugin</artifactId>
                 <extensions>true</extensions>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.gmavenplus</groupId>
-                <artifactId>gmavenplus-plugin</artifactId>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.apache.tinkerpop</groupId>
-                        <artifactId>gremlin-server</artifactId>
-                        <version>${project.version}</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.codehaus.groovy</groupId>
-                        <artifactId>groovy-all</artifactId>
-                        <version>${groovy.version}</version>
-                        <type>pom</type>
-                        <scope>runtime</scope>
-                    </dependency>
-                    <dependency>
-                        <groupId>log4j</groupId>
-                        <artifactId>log4j</artifactId>
-                        <version>${log4j.version}</version>
-                        <scope>runtime</scope>
-                    </dependency>
-                </dependencies>
-                <executions>
-                    <execution>
-                        <id>generate-dsl</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>execute</goal>
-                        </goals>
-                        <configuration>
-                            <properties>
-                                <property>
-                                    <name>projectBaseDir</name>
-                                    <value>${project.basedir}</value>
-                                </property>
-                                <property>
-                                    <name>projectVersion</name>
-                                    <value>${project.version}</value>
-                                </property>
-                            </properties>
-                            <scripts>
-                                <script>${project.basedir}/glv/generate.groovy</script>
-                            </scripts>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
             <!--
             there is no point to deploying the jvm stuff - there is no java source really - just poms
             -->
diff --git a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
index 3fde585..434b52b 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
@@ -15,7 +15,6 @@
 limitations under the License.
 -->
 
-<!--  THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml -->
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
@@ -26,7 +25,9 @@
   <ItemGroup>
     <!-- We need both reference elements until this is resolved: https://github.com/dotnet/sdk/issues/1151 -->
     <ProjectReference Include="../Gremlin.Net/Gremlin.Net.csproj" />
-    <PackageReference Include="Gremlin.Net" Version="3.4.9-SNAPSHOT" />
+
+    <!-- do not edit the version directly - maven updates it automatically -->
+    <PackageReference Include="Gremlin.Net" Version="3.5.0-SNAPSHOT" />
   </ItemGroup>
 
 </Project>
diff --git a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec
index 19c6155..120a74c 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec
@@ -3,7 +3,10 @@
     <metadata>
         <id>Gremlin.Net.Template</id>
         <title>Gremlin.Net Template</title>
-        <version>3.4.9-SNAPSHOT</version>
+
+        <!-- do not edit the version directly - maven updates it automatically -->
+        <version>3.5.0-SNAPSHOT</version>
+
         <description>Gremlin.Net template to create a console application with dotnet new.</description>
         <authors>Apache TinkerPop</authors>
         <license type="expression">Apache-2.0</license>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
index 7436c3d..9bc4658 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
@@ -31,13 +31,12 @@
 using Gremlin.Net.Driver.Messages;
 using Gremlin.Net.Process;
 using Gremlin.Net.Structure.IO.GraphSON;
-using Newtonsoft.Json.Linq;
 
 namespace Gremlin.Net.Driver
 {
     internal interface IResponseHandlerForSingleRequestMessage
     {
-        void HandleReceived(ResponseMessage<JToken> received);
+        void HandleReceived(ResponseMessage received);
         void Finalize(Dictionary<string, object> statusAttributes);
         void HandleFailure(Exception objException);
     }
@@ -124,7 +123,7 @@
 
         private void Parse(byte[] received)
         {
-            var receivedMsg = _messageSerializer.DeserializeMessage<ResponseMessage<JToken>>(received);
+            var receivedMsg = _messageSerializer.DeserializeMessage<ResponseMessage>(received);
             if (receivedMsg == null)
             {
                 ThrowMessageDeserializedNull();
@@ -146,7 +145,7 @@
         private static void ThrowMessageDeserializedNull() =>
             throw new InvalidOperationException("Received data deserialized into null object message. Cannot operate on it.");
 
-        private void TryParseResponseMessage(ResponseMessage<JToken> receivedMsg)
+        private void TryParseResponseMessage(ResponseMessage receivedMsg)
         {
             var status = receivedMsg.Status;
             status.ThrowIfStatusIndicatesError();
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/JsonMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/JsonMessageSerializer.cs
index 53a546c..de4c610 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/JsonMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/JsonMessageSerializer.cs
@@ -21,14 +21,17 @@
 
 #endregion
 
+using System;
 using System.Text;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace Gremlin.Net.Driver
 {
     internal class JsonMessageSerializer
     {
         private readonly string _mimeType;
+        private static readonly JsonSerializerOptions JsonDeserializingOptions = new JsonSerializerOptions
+            {PropertyNamingPolicy = JsonNamingPolicy.CamelCase};
 
         public JsonMessageSerializer(string mimeType)
         {
@@ -47,8 +50,11 @@
 
         public TMessage DeserializeMessage<TMessage>(byte[] message)
         {
-            var responseStr = Encoding.UTF8.GetString(message);
-            return JsonConvert.DeserializeObject<TMessage>(responseStr);
+            if (message == null) throw new ArgumentNullException(nameof(message));
+            if (message.Length == 0) return default;
+            var reader = new Utf8JsonReader(message);
+            var deserialized = JsonSerializer.Deserialize<TMessage>(ref reader, JsonDeserializingOptions);
+            return deserialized;
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
index f1cb3ad..791433f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
@@ -22,19 +22,15 @@
 #endregion
 
 using System;
-using Newtonsoft.Json;
 
 namespace Gremlin.Net.Driver.Messages
 {
-    internal class ResponseMessage<T>
+    internal class ResponseMessage
     {
-        [JsonProperty(PropertyName = "requestId")]
         public Guid RequestId { get; set; }
 
-        [JsonProperty(PropertyName = "status")]
         public ResponseStatus Status { get; set; }
 
-        [JsonProperty(PropertyName = "result")]
         public ResponseResult Result { get; set; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
index 848473b..b26f415 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
@@ -22,17 +22,14 @@
 #endregion
 
 using System.Collections.Generic;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Driver.Messages
 {
     internal class ResponseResult
     {
-        [JsonProperty(PropertyName = "data")]
-        public JToken Data { get; set; }
-
-        [JsonProperty(PropertyName = "meta")]
+        public JsonElement Data { get; set; }
+        
         public Dictionary<string, object> Meta { get; set; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
index aa0b1b7..32d8b43 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
@@ -23,19 +23,15 @@
 
 using System.Collections.Generic;
 using Gremlin.Net.Driver.Exceptions;
-using Newtonsoft.Json;
 
 namespace Gremlin.Net.Driver.Messages
 {
     internal class ResponseStatus
     {
-        [JsonProperty(PropertyName = "code")]
         public ResponseStatusCode Code { get; set; }
-
-        [JsonProperty(PropertyName = "attributes")]
+        
         public Dictionary<string, object> Attributes { get; set; }
-
-        [JsonProperty(PropertyName = "message")]
+        
         public string Message { get; set; }
     }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatusCode.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatusCode.cs
index 78f8759..b1a841a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatusCode.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatusCode.cs
@@ -77,10 +77,10 @@
         ServerError = 500,
 
         /// <summary>
-        ///     The script submitted for processing evaluated in the ScriptEngine with errors and could not be processed.
-        ///     Check the script submitted for syntax errors or other problems and then resubmit.
+        ///     The request submitted for processing evaluated by the server with errors and could not be processed.
+        ///     Check the script or remote traversal submitted for errors or other problems and then resubmit.
         /// </summary>
-        ScriptEvaluationError = 597,
+        ServerEvaluationError = 597,
 
         /// <summary>
         ///     The server exceeded one of the timeout settings for the request and could therefore only partially responded
@@ -111,7 +111,7 @@
                 case ResponseStatusCode.MalformedRequest:
                 case ResponseStatusCode.InvalidRequestArguments:
                 case ResponseStatusCode.ServerError:
-                case ResponseStatusCode.ScriptEvaluationError:
+                case ResponseStatusCode.ServerEvaluationError:
                 case ResponseStatusCode.ServerTimeout:
                 case ResponseStatusCode.ServerSerializationError:
                     return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
index 2197388..cf50646 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
@@ -33,10 +33,6 @@
             IEnumerable<Traverser> traversers)
         {
             Traversers = traversers;
-
-            #pragma warning disable 612,618
-            SideEffects = new DriverRemoteTraversalSideEffects(gremlinClient, requestId);
-            #pragma warning disable 612,618
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversalSideEffects.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversalSideEffects.cs
deleted file mode 100644
index f7c6ca8..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversalSideEffects.cs
+++ /dev/null
@@ -1,129 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Gremlin.Net.Driver.Messages;
-using Gremlin.Net.Process;
-using Gremlin.Net.Process.Traversal;
-
-namespace Gremlin.Net.Driver.Remote
-{
-    #pragma warning disable 612,618
-    internal class DriverRemoteTraversalSideEffects : ITraversalSideEffects
-    {
-        private readonly IGremlinClient _gremlinClient;
-        private readonly List<string> _keys = new List<string>();
-        private readonly Guid _serverSideEffectId;
-        private readonly Dictionary<string, object> _sideEffects = new Dictionary<string, object>();
-        private bool _closed;
-        private bool _retrievedAllKeys;
-
-        public DriverRemoteTraversalSideEffects(IGremlinClient gremlinClient, Guid serverSideEffectId)
-        {
-            _gremlinClient = gremlinClient;
-            _serverSideEffectId = serverSideEffectId;
-        }
-
-        public void Dispose()
-        {
-            Close();
-        }
-
-        public IReadOnlyCollection<string> Keys()
-        {
-            if (_closed && !_retrievedAllKeys)
-                throw new InvalidOperationException("Traversal has been closed - side-effect keys cannot be retrieved");
-            if (!_retrievedAllKeys)
-            {
-                _keys.AddRange(RetrieveKeys());
-                _retrievedAllKeys = true;
-            }
-            return _keys;
-        }
-
-        private IEnumerable<string> RetrieveKeys()
-        {
-            return _gremlinClient.SubmitAsync<string>(SideEffectKeysMessage()).Result;
-        }
-
-        private RequestMessage SideEffectKeysMessage()
-        {
-            return RequestMessage.Build(Tokens.OpsKeys)
-                .AddArgument(Tokens.ArgsSideEffect, _serverSideEffectId)
-                .Processor(Tokens.ProcessorTraversal)
-                .Create();
-        }
-
-        public object Get(string key)
-        {
-            if (!Keys().Contains(key))
-                throw new KeyNotFoundException($"Side effect key {key} does not exist");
-            if (!_sideEffects.ContainsKey(key))
-            {
-                if (_closed)
-                    throw new InvalidOperationException(
-                        "Traversal has been closed - no new side-effects can be retrieved");
-                _sideEffects.Add(key, RetrieveSideEffectsForKey(key));
-            }
-            return _sideEffects[key];
-        }
-
-        private object RetrieveSideEffectsForKey(string key)
-        {
-            return _gremlinClient.SubmitAsync<object>(SideEffectGatherMessage(key)).Result;
-        }
-
-        private RequestMessage SideEffectGatherMessage(string key)
-        {
-            return RequestMessage.Build(Tokens.OpsGather)
-                .AddArgument(Tokens.ArgsSideEffect, _serverSideEffectId)
-                .AddArgument(Tokens.ArgsSideEffectKey, key)
-                .AddArgument(Tokens.ArgsAliases, new Dictionary<string, string> {{"g", "g"}})
-                .Processor(Tokens.ProcessorTraversal)
-                .Create();
-        }
-
-        public void Close()
-        {
-            if (_closed) return;
-            CloseSideEffects();
-            _closed = true;
-        }
-
-        private void CloseSideEffects()
-        {
-            _gremlinClient.SubmitAsync<object>(SideEffectCloseMessage()).WaitUnwrap();
-        }
-
-        private RequestMessage SideEffectCloseMessage()
-        {
-            return RequestMessage.Build(Tokens.OpsClose)
-                .AddArgument(Tokens.ArgsSideEffect, _serverSideEffectId)
-                .Processor(Tokens.ProcessorTraversal)
-                .Create();
-        }
-    }
-    #pragma warning disable 612,618
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/AggregatorFactory.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/AggregatorFactory.cs
deleted file mode 100644
index 522225d..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/AggregatorFactory.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-
-namespace Gremlin.Net.Driver.ResultsAggregation
-{
-    #pragma warning disable 612,618
-    internal class AggregatorFactory
-    {
-        private readonly Dictionary<string, IAggregator> _aggregatorByAggregateToType =
-            new Dictionary<string, IAggregator>
-            {
-                {Tokens.ValAggregateToMap, new DictionaryAggregator()},
-                {Tokens.ValAggregateToBulkSet, new TraverserAggregator()}
-            };
-
-        public IAggregator GetAggregatorFor(string aggregateTo)
-        {
-            if (_aggregatorByAggregateToType.ContainsKey(aggregateTo))
-                return _aggregatorByAggregateToType[aggregateTo];
-            return new DefaultAggregator();
-        }
-    }
-    #pragma warning disable 612,618
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/DefaultAggregator.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/DefaultAggregator.cs
deleted file mode 100644
index 82b247b..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/DefaultAggregator.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-
-namespace Gremlin.Net.Driver.ResultsAggregation
-{
-    internal class DefaultAggregator : IAggregator
-    {
-        private readonly List<dynamic> _result = new List<dynamic>();
-
-        public void Add(object value)
-        {
-            _result.Add(value);
-        }
-
-        public object GetAggregatedResult()
-        {
-            return _result;
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/DictionaryAggregator.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/DictionaryAggregator.cs
deleted file mode 100644
index 75764e3..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/DictionaryAggregator.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Gremlin.Net.Driver.ResultsAggregation
-{
-    internal class DictionaryAggregator : IAggregator
-    {
-        private readonly Dictionary<string, dynamic> _result = new Dictionary<string, dynamic>();
-
-        public void Add(object value)
-        {
-            var newEntry = ((Dictionary<string, dynamic>) value).First();
-            _result.Add(newEntry.Key, newEntry.Value);
-        }
-
-        public object GetAggregatedResult()
-        {
-            return _result;
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/IAggregator.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/IAggregator.cs
deleted file mode 100644
index bcc036a..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/IAggregator.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-namespace Gremlin.Net.Driver.ResultsAggregation
-{
-    internal interface IAggregator
-    {
-        void Add(object value);
-        object GetAggregatedResult();
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/TraverserAggregator.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/TraverserAggregator.cs
deleted file mode 100644
index 2d18804..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResultsAggregation/TraverserAggregator.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-using Gremlin.Net.Process.Traversal;
-
-namespace Gremlin.Net.Driver.ResultsAggregation
-{
-    internal class TraverserAggregator : IAggregator
-    {
-        private readonly Dictionary<object, long> _result = new Dictionary<object, long>();
-
-        public void Add(object value)
-        {
-            var traverser = (Traverser) value;
-            _result.Add(traverser.Object, traverser.Bulk);
-        }
-
-        public object GetAggregatedResult()
-        {
-            return _result;
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/SingleMessageResultReceiver.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/SingleMessageResultReceiver.cs
index 7b66e61..13fbaf4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/SingleMessageResultReceiver.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/SingleMessageResultReceiver.cs
@@ -23,11 +23,10 @@
 
 using System;
 using System.Collections.Generic;
+using System.Text.Json;
 using System.Threading.Tasks;
 using Gremlin.Net.Driver.Messages;
-using Gremlin.Net.Driver.ResultsAggregation;
 using Gremlin.Net.Structure.IO.GraphSON;
-using Newtonsoft.Json.Linq;
 
 namespace Gremlin.Net.Driver
 {
@@ -39,8 +38,6 @@
             new TaskCompletionSource<ResultSet<T>>(TaskCreationOptions.RunContinuationsAsynchronously);
 
         private readonly GraphSONReader _graphSONReader;
-        private bool _isAggregatingSideEffects;
-        private IAggregator _aggregator;
         private readonly List<T> _result = new List<T>();
 
         public ResponseHandlerForSingleRequestMessage(GraphSONReader graphSonReader)
@@ -48,37 +45,21 @@
             _graphSONReader = graphSonReader;
         }
 
-        public void HandleReceived(ResponseMessage<JToken> received)
+        public void HandleReceived(ResponseMessage received)
         {
-            var receivedData = typeof(T) == typeof(JToken)
+            var receivedData = typeof(T) == typeof(JsonElement)
                 ? new[] {received.Result.Data}
                 : _graphSONReader.ToObject(received.Result.Data);
-            #pragma warning disable 612,618
             foreach (var d in receivedData)
             {
-                if (received.Result.Meta.ContainsKey(Tokens.ArgsSideEffectKey))
-                {
-                    if (_aggregator == null)
-                        _aggregator =
-                            new AggregatorFactory().GetAggregatorFor(
-                                (string) received.Result.Meta[Tokens.ArgsAggregateTo]);
-                    _aggregator.Add(d);
-                    _isAggregatingSideEffects = true;
-                }
-                else
-                {
-                    _result.Add(d);
-                }
+                _result.Add(d);
             }
-            #pragma warning disable 612,618
         }
 
         public void Finalize(Dictionary<string, object> statusAttributes)
         {
             var resultSet =
-                new ResultSet<T>(
-                    _isAggregatingSideEffects ? new List<T> {(T) _aggregator.GetAggregatedResult()} : _result,
-                    statusAttributes);
+                new ResultSet<T>(_result, statusAttributes);
             _tcs.TrySetResult(resultSet);
         }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
index a7f804a..f8d0140 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
@@ -47,18 +47,6 @@
         public static string OpsEval = "eval";
 
         /// <summary>
-        ///     Operation used to get a particular side-effect as produced by a previously executed Traversal.
-        /// </summary>
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        public static string OpsGather = "gather";
-
-        /// <summary>
-        ///     Operation used to get all the keys of all side-effects as produced by a previously executed Traversal.
-        /// </summary>
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        public static string OpsKeys = "keys";
-
-        /// <summary>
         ///     Operation used to get all the keys of all side-effects as produced by a previously executed Traversal.
         /// </summary>
         public static string OpsClose = "close";
@@ -101,24 +89,6 @@
         public static string ArgsSession = "session";
 
         /// <summary>
-        ///     Argument name that allows to specify the unique identifier for the request.
-        /// </summary>
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        public static string ArgsSideEffect = "sideEffect";
-
-        /// <summary>
-        ///     Argument name that allows to specify the key for a specific side-effect.
-        /// </summary>
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        public static string ArgsSideEffectKey = "sideEffectKey";
-
-        /// <summary>
-        ///     <see cref="ResponseMessage{T}" /> argument that describes how side-effect data should be treated.
-        /// </summary>
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        public static string ArgsAggregateTo = "aggregateTo";
-
-        /// <summary>
         ///     Argument name that allows to change the flavor of Gremlin used (e.g. gremlin-groovy).
         /// </summary>
         public static string ArgsLanguage = "language";
@@ -134,11 +104,5 @@
         ///     authentication mechanism required by the server.
         /// </summary>
         public static string ArgsSasl = "sasl";
-
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        internal static string ValAggregateToMap = "map";
-
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        internal static string ValAggregateToBulkSet = "bulkset";
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj b/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
index 2aec57f..b9ad5d1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
+++ b/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
@@ -15,19 +15,17 @@
 limitations under the License.
 -->
 
-<!--  THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml -->
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup Label="Build">
-    <TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
+    <TargetFramework>netstandard2.0</TargetFramework>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>
 
   <PropertyGroup Label="Package">
-    <Version>3.4.9-SNAPSHOT</Version>
-    <FileVersion>3.4.9.0</FileVersion>
-    <AssemblyVersion>3.4.0.0</AssemblyVersion>
+    <!-- do not edit the version directly - maven updates it automatically -->
+    <Version>3.5.0-SNAPSHOT</Version>
     <Title>Gremlin.Net</Title>
     <Authors>Apache TinkerPop</Authors>
     <Description>Gremlin.Net for Apache TinkerPop™ is a language variant and driver for .NET.
@@ -71,18 +69,12 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
-    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
+    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
+    <PackageReference Include="System.Text.Json" Version="4.7.1" />
     <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
     <PackageReference Include="Polly" Version="7.2.0" />
   </ItemGroup>
 
-  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
-    <PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
-    <PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />
-    <PackageReference Include="System.Reflection.TypeExtensions" Version="4.3.0" />
-  </ItemGroup>
-
   <ItemGroup>
     <None Include="../../LICENSE" Pack="true" PackagePath="" />
     <None Include="../../NOTICE" Pack="true" PackagePath="" />
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs
index 098a46d..d361ac4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs
@@ -54,7 +54,6 @@
         {
             if (traversal.Traversers != null) return;
             var remoteTraversal = await _remoteConnection.SubmitAsync<S, E>(traversal.Bytecode).ConfigureAwait(false);
-            traversal.SideEffects = remoteTraversal.SideEffects;
             traversal.Traversers = remoteTraversal.Traversers;
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Barrier.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Barrier.cs
index 0f86f32..c65994b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Barrier.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Barrier.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
index e09c533..7149e8b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
@@ -110,12 +110,23 @@
 
         private object ConvertArgument(object argument, bool searchBindings)
         {
+            if (null == argument)
+            {
+                return null;
+            }
+
             if (searchBindings)
             {
                 var variable = Bindings.GetBoundVariable(argument);
                 if (variable != null)
                     return new Binding(variable, ConvertArgument(argument, false));
             }
+
+            if (argument is ITraversal traversal && !traversal.IsAnonymous)
+                throw new ArgumentException(
+                    $"The child traversal of {traversal.Bytecode} was not spawned anonymously - use the __ class rather than a TraversalSource to construct the child traversal");
+
+            
             if (IsDictionaryType(argument.GetType()))
             {
                 var dict = new Dictionary<object, object>();
@@ -158,4 +169,4 @@
             return type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(HashSet<>);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Cardinality.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Cardinality.cs
index caced7d..65663d6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Cardinality.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Cardinality.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Column.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Column.cs
index cacf886..66a6edd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Column.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Column.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ConnectedComponent.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ConnectedComponent.cs
index ca1f53e..860e87a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ConnectedComponent.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ConnectedComponent.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections;
 using System.Collections.Generic;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
index 2b6d378..38e031c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
@@ -40,12 +40,11 @@
         ///     Gets the <see cref="Traversal.Bytecode" /> representation of this traversal.
         /// </summary>
         public Bytecode Bytecode { get; protected set; }
-
+        
         /// <summary>
-        ///     Gets or sets the <see cref="ITraversalSideEffects" /> of this traversal.
+        ///     Determines if this traversal was spawned anonymously or not.
         /// </summary>
-        [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-        public ITraversalSideEffects SideEffects { get; set; }
+        public bool IsAnonymous { get; protected set; }
 
         /// <summary>
         ///     Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal.
@@ -71,7 +70,6 @@
         /// <inheritdoc />
         public void Dispose()
         {
-            Dispose(true);
         }
 
         /// <inheritdoc />
@@ -261,15 +259,6 @@
             return objs;
         }
 
-        /// <inheritdoc />
-        protected virtual void Dispose(bool disposing)
-        {
-            if (disposing)
-                #pragma warning disable 612,618
-                SideEffects?.Dispose();
-                #pragma warning disable 612,618
-        }
-
         /// <summary>
         ///     Starts a promise to execute a function on the current traversal that will be completed in the future.
         /// </summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Direction.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Direction.cs
index 92d9416..8c3ed4a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Direction.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Direction.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphSONVersion.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphSONVersion.cs
index 366c48c..e79c86e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphSONVersion.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphSONVersion.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 7394fe8..8fb742c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -25,7 +25,6 @@
 using System.Linq;
 using Gremlin.Net.Structure;
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 namespace Gremlin.Net.Process.Traversal
 {
     /// <summary>
@@ -37,7 +36,7 @@
         ///     Initializes a new instance of the <see cref="GraphTraversal{SType, EType}" /> class.
         /// </summary>
         public GraphTraversal()
-            : this(new List<ITraversalStrategy>(), new Bytecode())
+            : this(new List<ITraversalStrategy>(), new Bytecode(), true)
         {
         }
 
@@ -47,9 +46,21 @@
         /// <param name="traversalStrategies">The traversal strategies to be used by this graph traversal at evaluation time.</param>
         /// <param name="bytecode">The <see cref="Bytecode" /> associated with the construction of this graph traversal.</param>
         public GraphTraversal(ICollection<ITraversalStrategy> traversalStrategies, Bytecode bytecode)
+            : this(traversalStrategies, bytecode, false)
+        {
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="GraphTraversal{SType, EType}" /> class.
+        /// </summary>
+        /// <param name="traversalStrategies">The traversal strategies to be used by this graph traversal at evaluation time.</param>
+        /// <param name="bytecode">The <see cref="Bytecode" /> associated with the construction of this graph traversal.</param>
+        /// <param name="anonymous">Set to true if spawned from an anonymous traversal source and false otherwise.</param>
+        private GraphTraversal(ICollection<ITraversalStrategy> traversalStrategies, Bytecode bytecode, bool anonymous)
         {
             TraversalStrategies = traversalStrategies;
             Bytecode = bytecode;
+            IsAnonymous = anonymous;
         }
 
         private static GraphTraversal<S2, E2> Wrap<S2, E2>(GraphTraversal<S, E> traversal)
@@ -59,7 +70,7 @@
                 return traversal as GraphTraversal<S2, E2>;
             }
             // New wrapper
-            return new GraphTraversal<S2, E2>(traversal.TraversalStrategies, traversal.Bytecode);
+            return new GraphTraversal<S2, E2>(traversal.TraversalStrategies, traversal.Bytecode, traversal.IsAnonymous);
         }
 
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index b52b898..920d6d8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -28,7 +28,6 @@
 using Gremlin.Net.Process.Traversal.Strategy.Decoration;
 using Gremlin.Net.Structure;
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 namespace Gremlin.Net.Process.Traversal
 {
 #pragma warning disable 1591
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GryoVersion.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GryoVersion.cs
index 01d2a99..e34c7b3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GryoVersion.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GryoVersion.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs
index 3a57d4b..b9e0fdd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections;
 using System.Collections.Generic;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
index 22f792a..95cbb74 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
@@ -38,13 +38,11 @@
         ///     Gets the <see cref="Bytecode" /> representation of this traversal.
         /// </summary>
         Bytecode Bytecode { get; }
-
+        
         /// <summary>
-        ///     Gets or sets the <see cref="ITraversalSideEffects" /> of this traversal.
+        ///     Determines if this traversal was spawned anonymously or not.
         /// </summary>
-        #pragma warning disable 612,618
-        ITraversalSideEffects SideEffects { get; set; }
-        #pragma warning disable 612,618
+        bool IsAnonymous { get;  }
 
         /// <summary>
         ///     Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal.
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalSideEffects.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalSideEffects.cs
deleted file mode 100644
index d8d9fc1..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalSideEffects.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-
-namespace Gremlin.Net.Process.Traversal
-{
-    /// <summary>
-    ///     A <see cref="ITraversal" /> can maintain global sideEffects.
-    /// </summary>
-    [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step to retrieve side-effects as part of traversal iteration", false)]
-    public interface ITraversalSideEffects : IDisposable
-    {
-        /// <summary>
-        ///     Retrieves the keys of the side-effect that can be supplied to <see cref="Get" />.
-        /// </summary>
-        /// <returns>The keys of the side-effect.</returns>
-        IReadOnlyCollection<string> Keys();
-
-        /// <summary>
-        ///     Gets the side-effect associated with the provided key.
-        /// </summary>
-        /// <param name="key">The key to get the value for.</param>
-        /// <returns>The value associated with key.</returns>
-        object Get(string key);
-
-        /// <summary>
-        ///     Invalidates the side effect cache for traversal.
-        /// </summary>
-        void Close();
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
index 65847c5..55df44d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
@@ -21,6 +21,8 @@
 
 #endregion
 
+using System;
+
 namespace Gremlin.Net.Process.Traversal
 {
     /// <summary>
@@ -48,5 +50,14 @@
         ///     Gets the arguments.
         /// </summary>
         public dynamic[] Arguments { get; }
+
+        /// <summary>
+        ///     String representation of the <see cref="Instruction"/>.
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return OperatorName + " [" + String.Join(",", Arguments) + "]";
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
index eadaa0e..a650dc5 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
@@ -23,7 +23,6 @@
 
 using System.Collections.Generic;
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 namespace Gremlin.Net.Process.Traversal
 {
     internal static class NamingConversions
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Operator.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Operator.cs
index 8b87e40..ce33569 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Operator.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Operator.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Order.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Order.cs
index 9fce332..fca67ab 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Order.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Order.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
@@ -38,20 +37,14 @@
 
         public static Order Asc => new Order("asc");
 
-        public static Order Decr => new Order("decr");
-
         public static Order Desc => new Order("desc");
 
-        public static Order Incr => new Order("incr");
-
         public static Order Shuffle => new Order("shuffle");
 
         private static readonly IDictionary<string, Order> Properties = new Dictionary<string, Order>
         {
             { "asc", Asc },
-            { "decr", Decr },
             { "desc", Desc },
-            { "incr", Incr },
             { "shuffle", Shuffle },
         };
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
index b83e3c2..d37a614 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PageRank.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PageRank.cs
index 73d248a..5c2ade9 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PageRank.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PageRank.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections;
 using System.Collections.Generic;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PeerPressure.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PeerPressure.cs
index 185879e..fde3b41 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PeerPressure.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/PeerPressure.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections;
 using System.Collections.Generic;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pick.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pick.cs
index b7dd8c2..f0312a3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pick.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pick.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pop.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pop.cs
index 1210f5c..196ce01 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pop.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Pop.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Scope.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Scope.cs
index 2df6a95..ff70069 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Scope.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Scope.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ShortestPath.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ShortestPath.cs
index f125e42..238a5e7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ShortestPath.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ShortestPath.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections;
 using System.Collections.Generic;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SeedStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SeedStrategy.cs
new file mode 100644
index 0000000..bf531f5
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SeedStrategy.cs
@@ -0,0 +1,51 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+
+namespace Gremlin.Net.Process.Traversal.Strategy.Decoration
+{
+    /// <summary>
+    ///     A strategy that resets the specified {@code seed} value for Seedable steps like coin(), sample()
+    ///     and Order.shuffle, which in turn will produce deterministic results from those steps.
+    /// </summary>
+    public class SeedStrategy : AbstractTraversalStrategy
+    {
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="OptionsStrategy" /> class.
+        /// </summary>
+        public SeedStrategy()
+        {
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="SeedStrategy" /> class.
+        /// </summary>
+        /// <param name="seed">Specifies the seed the traversal will use.</param>
+        public SeedStrategy(long seed)
+        {
+            Configuration["seed"] = seed;
+        }
+    }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/T.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/T.cs
index 80ca0ec..e688e8d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/T.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/T.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections.Generic;
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
index 3047f75..a77f206 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
@@ -21,12 +21,8 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 
 namespace Gremlin.Net.Process.Traversal
 {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
index c20c59a..0229d4c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
@@ -21,7 +21,6 @@
 
 #endregion
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 using System;
 using System.Collections;
 using System.Collections.Generic;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 9bd0b14..fa1c027 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -24,7 +24,6 @@
 using System.Collections.Generic;
 using Gremlin.Net.Structure;
 
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
 namespace Gremlin.Net.Process.Traversal
 {
     /// <summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
index 755dbcc..a3f1ff6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
@@ -22,16 +22,15 @@
 #endregion
 
 using System.Numerics;
-using System.Xml;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class BigIntegerDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphson, GraphSONReader reader)
         {
-            var bigInteger = graphsonObject.ToObject<string>();
+            var bigInteger = graphson.ValueKind == JsonValueKind.String ? graphson.GetString() : graphson.GetRawText();
             return BigInteger.Parse(bigInteger);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
index 58d4c9b..539224a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
@@ -23,17 +23,15 @@
 
 using System.Collections.Generic;
 using System.Linq;
-using System.Runtime.CompilerServices;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class BulkSetSerializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var jArray = graphsonObject as JArray;
-            if (jArray == null)
+            if (graphsonObject.ValueKind != JsonValueKind.Array)
             {
                 return new List<object>(0);
             }
@@ -42,9 +40,9 @@
             // so this query will be trouble. we'd need a legit BulkSet implementation here in C#. this current 
             // implementation is here to replicate the previous functionality that existed on the server side in 
             // previous versions.
-            return Enumerable.Range(0, jArray.Count / 2).SelectMany<int,object>(i =>
-                           Enumerable.Repeat<object>(reader.ToObject(jArray[i * 2]), (int) reader.ToObject(jArray[i * 2 + 1]))).
-                       ToList();
+            return Enumerable.Range(0, graphsonObject.GetArrayLength() / 2).SelectMany<int, object>(i =>
+                Enumerable.Repeat<object>(reader.ToObject(graphsonObject[i * 2]),
+                    (int) reader.ToObject(graphsonObject[i * 2 + 1]))).ToList();
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
index f77abb0..0feb3a2 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
@@ -21,15 +21,15 @@
 #endregion
 
 using System;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class ByteBufferDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var base64String = graphsonObject.ToObject<string>();
+            var base64String = graphsonObject.GetString();
             return Convert.FromBase64String(base64String);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs
index 6525d52..c9fc8a5 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs
@@ -20,14 +20,14 @@
  */
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class ByteConverter : NumberConverter
+    internal class ByteConverter : NumberConverter<byte>
     {
         protected override string GraphSONTypeName => "Byte";
-        protected override Type HandledType => typeof(byte);
         protected override string Prefix => "gx";
+        protected override dynamic FromJsonElement(JsonElement graphson) => graphson.GetByte();
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
index b7023be..0c3e539 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
@@ -20,15 +20,19 @@
  */
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class CharConverter : NumberConverter
+    internal class CharConverter : NumberConverter<char>
     {
         protected override string GraphSONTypeName => "Char";
-        protected override Type HandledType => typeof(char);
         protected override string Prefix => "gx";
         protected override bool StringifyValue => true;
+        protected override dynamic FromJsonElement(JsonElement graphson)
+        {
+            var deserializedByte = graphson.GetString();
+            return deserializedByte[0];
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DateDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DateDeserializer.cs
index 98ca25e..bc5bf61 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DateDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DateDeserializer.cs
@@ -21,7 +21,7 @@
 #endregion
 
 using System;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -29,9 +29,9 @@
     {
         private static readonly DateTimeOffset UnixStart = new DateTimeOffset(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
 
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var milliseconds = graphsonObject.ToObject<long>();
+            var milliseconds = graphsonObject.GetInt64();
             return UnixStart.AddTicks(TimeSpan.TicksPerMillisecond * milliseconds);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
index 6860137..f195522 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
@@ -21,15 +21,23 @@
 
 #endregion
 
-using System;
+using System.Globalization;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class DecimalConverter : NumberConverter
+    internal class DecimalConverter : NumberConverter<decimal>
     {
         protected override string GraphSONTypeName => "BigDecimal";
-        protected override Type HandledType => typeof(decimal);
         protected override string Prefix => "gx";
         protected override bool StringifyValue => true;
+        protected override dynamic FromJsonElement(JsonElement graphson)
+        {
+            if (graphson.ValueKind == JsonValueKind.String)
+            {
+                return decimal.Parse(graphson.GetString(), CultureInfo.InvariantCulture);
+            }
+            return graphson.GetDecimal();
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
index 4027171..34d4f61 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
@@ -21,16 +21,16 @@
 
 #endregion
 
+using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
-using Newtonsoft.Json.Linq;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class DirectionDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return Direction.GetByValue(graphsonObject.ToString());
+            return Direction.GetByValue(graphsonObject.GetString());
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DoubleConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DoubleConverter.cs
index 416423b..ba5a2f7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DoubleConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DoubleConverter.cs
@@ -21,13 +21,52 @@
 
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class DoubleConverter : NumberConverter
+    internal class DoubleConverter : NumberConverter<double>
     {
         protected override string GraphSONTypeName => "Double";
-        protected override Type HandledType => typeof(double);
+        private const string NaN = "NaN";
+        private const string PositiveInfinity = "Infinity";
+        private const string NegativeInfinity = "-Infinity";
+
+        protected override dynamic FromJsonElement(JsonElement graphson)
+        {
+            if (graphson.ValueKind == JsonValueKind.String)
+            {
+                switch (graphson.GetString())
+                {
+                    case NaN:
+                        return double.NaN;
+                    case PositiveInfinity:
+                        return double.PositiveInfinity;
+                    case NegativeInfinity:
+                        return double.NegativeInfinity;
+                }
+            }  
+            return graphson.GetDouble();
+        }
+
+        protected override object ConvertInvalidNumber(double number)
+        {
+            if (double.IsNaN(number))
+            {
+                return NaN;
+            }
+
+            if (double.IsPositiveInfinity(number))
+            {
+                return PositiveInfinity;
+            }
+
+            if (double.IsNegativeInfinity(number))
+            {
+                return NegativeInfinity;
+            }
+            
+            return number;
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
index 00a9a70..2c1d17f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
@@ -21,16 +21,16 @@
 
 #endregion
 
+using System.Text.Json;
 using System.Xml;
-using Newtonsoft.Json.Linq;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class DurationDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var duration = graphsonObject.ToObject<string>();
+            var duration = graphsonObject.GetString();
             return XmlConvert.ToTimeSpan(duration);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
index 6ec8694..13f4ce0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
@@ -21,22 +21,28 @@
 
 #endregion
 
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class EdgeDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var outVId = reader.ToObject(graphsonObject["outV"]);
-            var outVLabel = (string) (graphsonObject["outVLabel"] ?? Vertex.DefaultLabel);
+            var outVId = reader.ToObject(graphsonObject.GetProperty("outV"));
+            var outVLabel = graphsonObject.TryGetProperty("outVLabel", out var outVLabelProperty)
+                ? outVLabelProperty.GetString()
+                : Vertex.DefaultLabel;
             var outV = new Vertex(outVId, outVLabel);
-            var inVId = reader.ToObject(graphsonObject["inV"]);
-            var inVLabel = (string) (graphsonObject["inVLabel"] ?? Vertex.DefaultLabel);
+            var inVId = reader.ToObject(graphsonObject.GetProperty("inV"));
+            var inVLabel = graphsonObject.TryGetProperty("inVLabel", out var inVLabelProperty)
+                ? inVLabelProperty.GetString()
+                : Vertex.DefaultLabel;
             var inV = new Vertex(inVId, inVLabel);
-            var edgeId = reader.ToObject(graphsonObject["id"]);
-            var edgeLabel = (string) graphsonObject["label"] ?? "edge";
+            var edgeId = reader.ToObject(graphsonObject.GetProperty("id"));
+            var edgeLabel = graphsonObject.TryGetProperty("label", out var labelProperty)
+                ? labelProperty.GetString()
+                : "edge";
             return new Edge(edgeId, outV, edgeLabel, inV);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/FloatConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/FloatConverter.cs
index 432aeab..5bbd9b2 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/FloatConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/FloatConverter.cs
@@ -21,13 +21,13 @@
 
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class FloatConverter : NumberConverter
+    internal class FloatConverter : NumberConverter<float>
     {
         protected override string GraphSONTypeName => "Float";
-        protected override Type HandledType => typeof(float);
+        protected override dynamic FromJsonElement(JsonElement graphson) => graphson.GetSingle();
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
index 63641f0..16901bd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
@@ -24,7 +24,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -90,7 +90,7 @@
         /// </summary>
         /// <param name="graphSonData">The GraphSON collection to deserialize.</param>
         /// <returns>The deserialized object.</returns>
-        public virtual dynamic ToObject(IEnumerable<JToken> graphSonData)
+        public virtual dynamic ToObject(IEnumerable<JsonElement> graphSonData)
         {
             return graphSonData.Select(graphson => ToObject(graphson));
         }
@@ -98,52 +98,50 @@
         /// <summary>
         ///     Deserializes GraphSON to an object.
         /// </summary>
-        /// <param name="jToken">The GraphSON to deserialize.</param>
+        /// <param name="graphSon">The GraphSON to deserialize.</param>
         /// <returns>The deserialized object.</returns>
-        public virtual dynamic ToObject(JToken jToken)
+        public virtual dynamic ToObject(JsonElement graphSon)
         {
-            if (jToken is JArray)
+            switch (graphSon.ValueKind)
             {
-                return jToken.Select(t => ToObject(t));
+                case JsonValueKind.Array:
+                    return graphSon.EnumerateArray().Select(t => ToObject(t));
+                case JsonValueKind.String:
+                    return graphSon.GetString();
+                case JsonValueKind.Null:
+                    return null;
+                case JsonValueKind.True:
+                    return true;
+                case JsonValueKind.False:
+                    return false;
+                case JsonValueKind.Object:
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(graphSon.ValueKind), graphSon.ValueKind,
+                        $"JSON type not supported.");
             }
-            if (jToken is JValue jValue)
+
+            if (graphSon.TryGetProperty(GraphSONTokens.TypeKey, out var graphSonTypeProperty))
             {
-                return jValue.Value;
+                return ReadValueOfType(graphSon, graphSonTypeProperty.GetString());
             }
-            if (!HasTypeKey(jToken))
-            {
-                return ReadDictionary(jToken);
-            }
-            return ReadTypedValue(jToken);
+            return ReadDictionary(graphSon);
+            
         }
 
-        private bool HasTypeKey(JToken jToken)
+        private dynamic ReadValueOfType(JsonElement typedValue, string graphSONType)
         {
-            var graphSONType = (string) jToken[GraphSONTokens.TypeKey];
-            return graphSONType != null;
-        }
-
-        private dynamic ReadTypedValue(JToken typedValue)
-        {
-            var graphSONType = (string) typedValue[GraphSONTokens.TypeKey];
             if (!Deserializers.TryGetValue(graphSONType, out var deserializer))
             {
                 throw new InvalidOperationException($"Deserializer for \"{graphSONType}\" not found");
             }
-            return deserializer.Objectify(typedValue[GraphSONTokens.ValueKey], this);
+            return deserializer.Objectify(typedValue.GetProperty(GraphSONTokens.ValueKey), this);
         }
-
-        private dynamic ReadDictionary(JToken jtokenDict)
+        
+        private dynamic ReadDictionary(JsonElement jsonDict)
         {
-            var dict = new Dictionary<string, dynamic>();
-            foreach (var e in jtokenDict)
-            {
-                var property = e as JProperty;
-                if (property == null)
-                    throw new InvalidOperationException($"Cannot read graphson: {jtokenDict}");
-                dict.Add(property.Name, ToObject(property.Value));
-            }
-            return dict;
+            return jsonDict.EnumerateObject()
+                .ToDictionary(property => property.Name, property => ToObject(property.Value));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
index dba6e60..dd4fa27 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
@@ -26,11 +26,11 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Numerics;
-using System.Reflection;
+using System.Text.Encodings.Web;
+using System.Text.Json;
 using Gremlin.Net.Driver.Messages;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Process.Traversal.Strategy;
-using Newtonsoft.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -39,6 +39,9 @@
     /// </summary>
     public abstract class GraphSONWriter
     {
+        private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
+            {Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping};
+        
         /// <summary>
         /// Contains the information of serializers by type.
         /// </summary>
@@ -103,7 +106,7 @@
         /// <returns>The serialized GraphSON.</returns>
         public virtual string WriteObject(dynamic objectData)
         {
-            return JsonConvert.SerializeObject(ToDict(objectData));
+            return JsonSerializer.Serialize(ToDict(objectData), _jsonOptions);
         }
 
         /// <summary>
@@ -113,17 +116,20 @@
         /// <returns>A GraphSON representation of the object ready to be serialized.</returns>
         public dynamic ToDict(dynamic objectData)
         {
-            var type = objectData.GetType();
+            if (objectData != null)
+            {
+                var type = objectData.GetType();
 
-            IGraphSONSerializer serializer = TryGetSerializerFor(type);
+                IGraphSONSerializer serializer = TryGetSerializerFor(type);
 
-            if (serializer != null)
-                return serializer.Dictify(objectData, this);
-            if (IsDictionaryType(type))
-                return DictToGraphSONDict(objectData);
-            if (IsCollectionType(type))
-                return CollectionToGraphSONCollection(objectData);
-            return objectData;
+                if (serializer != null)
+                    return serializer.Dictify(objectData, this);
+                if (IsDictionaryType(type))
+                    return DictToGraphSONDict(objectData);
+                if (IsCollectionType(type))
+                    return CollectionToGraphSONCollection(objectData);
+            }
+            return objectData;         
         }
 
         private IGraphSONSerializer TryGetSerializerFor(Type type)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/IGraphSONDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/IGraphSONDeserializer.cs
index b15b169..e0c4993 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/IGraphSONDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/IGraphSONDeserializer.cs
@@ -21,7 +21,7 @@
 
 #endregion
 
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -36,6 +36,6 @@
         /// <param name="graphsonObject">The GraphSON object to objectify.</param>
         /// <param name="reader">A <see cref="GraphSONReader" /> that can be used to objectify properties of the GraphSON object.</param>
         /// <returns>The deserialized object.</returns>
-        dynamic Objectify(JToken graphsonObject, GraphSONReader reader);
+        dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int16Converter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int16Converter.cs
index abe5a77..6182de9 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int16Converter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int16Converter.cs
@@ -21,14 +21,15 @@
 
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class Int16Converter : NumberConverter
+    internal class Int16Converter : NumberConverter<short>
     {
         protected override string GraphSONTypeName => "Int16";
-        protected override Type HandledType => typeof(short);
         protected override string Prefix => "gx";
+        
+        protected override dynamic FromJsonElement(JsonElement graphson) => graphson.GetInt16();
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int32Converter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int32Converter.cs
index 052f938..6cdcdfd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int32Converter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int32Converter.cs
@@ -21,13 +21,14 @@
 
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class Int32Converter : NumberConverter
+    internal class Int32Converter : NumberConverter<int>
     {
         protected override string GraphSONTypeName => "Int32";
-        protected override Type HandledType => typeof(int);
+
+        protected override dynamic FromJsonElement(JsonElement graphson) => graphson.GetInt32();
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int64Converter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int64Converter.cs
index dd0160f..c0192a8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int64Converter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Int64Converter.cs
@@ -21,13 +21,14 @@
 
 #endregion
 
-using System;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal class Int64Converter : NumberConverter
+    internal class Int64Converter : NumberConverter<long>
     {
         protected override string GraphSONTypeName => "Int64";
-        protected override Type HandledType => typeof(long);
+        
+        protected override dynamic FromJsonElement(JsonElement graphson) => graphson.GetInt64();
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
index f432c7e..add8eb5 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
@@ -21,12 +21,8 @@
 
 #endregion
 
-using System;
-using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
-using Microsoft.Win32.SafeHandles;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -34,17 +30,16 @@
     {
         private static readonly IReadOnlyList<object> EmptyList = new object[0];
         
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var jArray = graphsonObject as JArray;
-            if (jArray == null)
+            if (graphsonObject.ValueKind != JsonValueKind.Array)
             {
                 return EmptyList;
             }
-            var result = new object[jArray.Count];
+            var result = new object[graphsonObject.GetArrayLength()];
             for (var i = 0; i < result.Length; i++)
             {
-                result[i] = reader.ToObject(jArray[i]);
+                result[i] = reader.ToObject(graphsonObject[i]);
             }
             // object[] implements IList<object>
             return result;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
index a096e3e..99165a7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
@@ -24,23 +24,22 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class MapSerializer : IGraphSONDeserializer, IGraphSONSerializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var jArray = graphsonObject as JArray;
-            if (jArray == null)
+            if (graphsonObject.ValueKind != JsonValueKind.Array)
             {
                 return new Dictionary<object, object>(0);
             }
-            var result = new Dictionary<object, object>(jArray.Count / 2);
-            for (var i = 0; i < jArray.Count; i += 2)
+            var result = new Dictionary<object, object>(graphsonObject.GetArrayLength() / 2);
+            for (var i = 0; i < graphsonObject.GetArrayLength(); i += 2)
             {
-                result[reader.ToObject(jArray[i])] = reader.ToObject(jArray[i + 1]);
+                result[reader.ToObject(graphsonObject[i])] = reader.ToObject(graphsonObject[i + 1]);
             }
             // IDictionary<object, object>
             return result;
@@ -48,8 +47,7 @@
         
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
         {
-            var map = objectData as IDictionary;
-            if (map == null)
+            if (!(objectData is IDictionary map))
             {
                 throw new InvalidOperationException("Object must implement IDictionary");
             }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
index 8127415..4492685 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
@@ -21,33 +21,36 @@
 
 #endregion
 
-using System;
 using System.Collections.Generic;
 using System.Globalization;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal abstract class NumberConverter : IGraphSONDeserializer, IGraphSONSerializer
+    internal abstract class NumberConverter<T> : IGraphSONDeserializer, IGraphSONSerializer
     {
         protected abstract string GraphSONTypeName { get; }
-        protected abstract Type HandledType { get; }
         protected virtual string Prefix => "g";
         protected virtual bool StringifyValue => false;
 
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return graphsonObject.ToObject(HandledType);
+            return FromJsonElement(graphsonObject);
         }
 
+        protected abstract dynamic FromJsonElement(JsonElement graphson);
+
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
         {
-            object value = objectData;
+            T number = objectData;
+            var value = ConvertInvalidNumber(number);
             if (StringifyValue)
             {
                 value = string.Format(CultureInfo.InvariantCulture, "{0}", value);
             }
             return GraphSONUtil.ToTypedValue(GraphSONTypeName, value, Prefix);
         }
+
+        protected virtual object ConvertInvalidNumber(T number) => number;
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
index 4754135..d05663b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
@@ -23,21 +23,21 @@
 
 using System.Collections.Generic;
 using System.Linq;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class Path3Deserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             // "labels" is a object[] where each item is ISet<object>
-            var labelProperty = (object[])reader.ToObject(graphsonObject["labels"]);
+            var labelProperty = (object[])reader.ToObject(graphsonObject.GetProperty("labels"));
             var labels = labelProperty
                 .Select(x => new HashSet<string>(((ISet<object>)x).Cast<string>()))
                 .ToList<ISet<string>>();
             // "objects" is an object[]
-            object[] objects = reader.ToObject(graphsonObject["objects"]);
+            object[] objects = reader.ToObject(graphsonObject.GetProperty("objects"));
             return new Path(labels, objects);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
index b322df8..3a37f66 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
@@ -23,19 +23,21 @@
 
 using System.Collections.Generic;
 using System.Linq;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class PathDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var labels =
-                graphsonObject["labels"]
-                    .Select(readObjLabels => new HashSet<string>(readObjLabels.Select(l => (string) l)))
+                graphsonObject.GetProperty("labels").EnumerateArray()
+                    .Select(readObjLabels =>
+                        new HashSet<string>(readObjLabels.EnumerateArray().Select(l => l.GetString())))
                     .ToList<ISet<string>>();
-            var objects = graphsonObject["objects"].Select(o => reader.ToObject(o)).ToList();
+            var objects = graphsonObject.GetProperty("objects").EnumerateArray().Select(o => reader.ToObject(o))
+                .ToList();
             return new Path(labels, objects);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertyDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertyDeserializer.cs
index 11f160e..7c9ea0c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertyDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertyDeserializer.cs
@@ -21,17 +21,19 @@
 
 #endregion
 
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class PropertyDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var key = (string) graphsonObject["key"];
-            var value = reader.ToObject(graphsonObject["value"]);
-            var element = graphsonObject["element"] != null ? reader.ToObject(graphsonObject["element"]) : null;
+            var key = graphsonObject.GetProperty("key").GetString();
+            var value = reader.ToObject(graphsonObject.GetProperty("value"));
+            var element = graphsonObject.TryGetProperty("element", out var elementProperty)
+                ? reader.ToObject(elementProperty)
+                : null;
             return new Property(key, value, element);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
index e657bd8..590392e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
@@ -21,24 +21,22 @@
 
 #endregion
 
-using System;
 using System.Collections.Generic;
 using System.Linq;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class SetSerializer : IGraphSONDeserializer, IGraphSONSerializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var jArray = graphsonObject as JArray;
-            if (jArray == null)
+            if (graphsonObject.ValueKind != JsonValueKind.Array)
             {
                 return new HashSet<object>();
             }
             // ISet<object>
-            return new HashSet<object>(jArray.Select(reader.ToObject));
+            return new HashSet<object>(graphsonObject.EnumerateArray().Select(reader.ToObject));
         }
 
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
index a3d972f..efbc542 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
@@ -21,16 +21,16 @@
 
 #endregion
 
+using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
-using Newtonsoft.Json.Linq;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class TDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return T.GetByValue(graphsonObject.ToString());
+            return T.GetByValue(graphsonObject.GetString());
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TraverserReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TraverserReader.cs
index abbb45f..1997325 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TraverserReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TraverserReader.cs
@@ -21,17 +21,17 @@
 
 #endregion
 
+using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
-using Newtonsoft.Json.Linq;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class TraverserReader : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var bulkObj = reader.ToObject(graphsonObject["bulk"]);
-            var valueObj = reader.ToObject(graphsonObject["value"]);
+            var bulkObj = reader.ToObject(graphsonObject.GetProperty("bulk"));
+            var valueObj = reader.ToObject(graphsonObject.GetProperty("value"));
             return new Traverser(valueObj, bulkObj);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
index 82ca43d..58caac7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
@@ -22,15 +22,17 @@
 #endregion
 
 using System;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class UuidDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return graphsonObject.ToObject<Guid>();
+            var uuidString = graphsonObject.GetString();
+
+            return Guid.Parse(uuidString);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
index f1d64ed..72615ef 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
@@ -21,16 +21,18 @@
 
 #endregion
 
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class VertexDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var id = reader.ToObject(graphsonObject["id"]);
-            var label = (string) graphsonObject["label"] ?? Vertex.DefaultLabel;
+            var id = reader.ToObject(graphsonObject.GetProperty("id"));
+            var label = graphsonObject.TryGetProperty("label", out var labelProperty)
+                ? labelProperty.GetString()
+                : Vertex.DefaultLabel;
             return new Vertex(id, label);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
index 7c2505f..15a99dc 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
@@ -21,19 +21,19 @@
 
 #endregion
 
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class VertexPropertyDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            var id = reader.ToObject(graphsonObject["id"]);
-            var label = (string) graphsonObject["label"];
-            var value = reader.ToObject(graphsonObject["value"]);
-            var vertex = graphsonObject["vertex"] != null
-                ? new Vertex(reader.ToObject(graphsonObject["vertex"]))
+            var id = reader.ToObject(graphsonObject.GetProperty("id"));
+            var label = graphsonObject.GetProperty("label").GetString();
+            var value = reader.ToObject(graphsonObject.GetProperty("value"));
+            var vertex = graphsonObject.TryGetProperty("vertex", out var vertexProperty)
+                ? new Vertex(reader.ToObject(vertexProperty))
                 : null;
             return new VertexProperty(id, label, value, vertex);
         }
diff --git a/gremlin-dotnet/src/pom.xml b/gremlin-dotnet/src/pom.xml
index 1311e99..e6ff9c8 100644
--- a/gremlin-dotnet/src/pom.xml
+++ b/gremlin-dotnet/src/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>gremlin-dotnet</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-dotnet-source</artifactId>
     <name>Apache TinkerPop :: Gremlin.Net - Source</name>
@@ -33,14 +33,40 @@
 
     <build>
         <plugins>
-            <!-- Override the execution from gremlin-dotnet to disable code generation from happening a second time -->
             <plugin>
                 <groupId>org.codehaus.gmavenplus</groupId>
                 <artifactId>gmavenplus-plugin</artifactId>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.codehaus.groovy</groupId>
+                        <artifactId>groovy-all</artifactId>
+                        <version>${groovy.version}</version>
+                        <type>pom</type>
+                        <scope>runtime</scope>
+                    </dependency>
+                </dependencies>
                 <executions>
                     <execution>
-                        <id>generate-dsl</id>
-                        <phase/>
+                        <id>update-version</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>execute</goal>
+                        </goals>
+                        <configuration>
+                            <scripts>
+                                <script>
+def mavenVersion = "${project.version}"
+def file = new File("${project.basedir}/Gremlin.Net/Gremlin.Net.csproj")
+file.write(file.getText("UTF-8").replaceFirst(/&lt;Version&gt;(.*)&lt;\/Version&gt;/, "&lt;Version&gt;" + mavenVersion + "&lt;/Version&gt;"))
+
+file = new File("${project.basedir}/Gremlin.Net.Template/Gremlin.Net.Template.csproj")
+file.write(file.getText("UTF-8").replaceFirst(/Version="(.*)"/, "Version=\"" + mavenVersion + "\""))
+
+file = new File("${project.basedir}/Gremlin.Net.Template/Gremlin.Net.Template.nuspec")
+file.write(file.getText("UTF-8").replaceFirst(/&lt;version&gt;(.*)&lt;\/version&gt;/, "&lt;version&gt;" + mavenVersion + "&lt;/version&gt;"))
+                                </script>
+                            </scripts>
+                        </configuration>
                     </execution>
                 </executions>
             </plugin>
@@ -301,18 +327,10 @@
                                 <configuration>
                                     <scripts>
                                         <script><![CDATA[
-// revert back the version after a SNAPSHOT deployment
+// prevent SNAPSHOT deployment for .NET
 def versionToUse = '${project.version}'
-def engine = new groovy.text.GStringTemplateEngine()
-def csprojTemplate = engine.createTemplate(new File('${project.parent.basedir}/glv/Gremlin.Net.csproj.template')).make(["projectVersion":versionToUse])
-def csprojFile = new File('${project.basedir}/Gremlin.Net/Gremlin.Net.csproj')
-csprojFile.newWriter().withWriter{ it << csprojTemplate }
-def templateCsprojTemplate = engine.createTemplate(new File('${project.parent.basedir}/glv/Gremlin.Net.Template.csproj.template')).make(["projectVersion":versionToUse])
-def templateCsprojFile = new File('${project.basedir}/Gremlin.Net.Template/Gremlin.Net.Template.csproj')
-templateCsprojFile.newWriter().withWriter{ it << templateCsprojTemplate }
-def nuspecTemplate = engine.createTemplate(new File('${project.parent.basedir}/glv/Gremlin.Net.Template.nuspec.template')).make(["projectVersion":versionToUse])
-def nuspecFile = new File('${project.basedir}/Gremlin.Net.Template/Gremlin.Net.Template.nuspec')
-nuspecFile.newWriter().withWriter{ it << nuspecTemplate }
+if (versionToUse.endsWith("-SNAPSHOT")
+  throw new RuntimeException("Current version is a SNAPSHOT which can not be deployed to nuget")
 ]]>
                                         </script>
                                     </scripts>
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Dev/Provider/IndexTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Dev/Provider/IndexTests.cs
index 6d8cda2..906a117 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Dev/Provider/IndexTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Dev/Provider/IndexTests.cs
@@ -23,9 +23,9 @@
 
 using System;
 using System.Collections.Generic;
+using System.Text.Json;
 using Gremlin.Net.Driver;
 using Gremlin.Net.Structure.IO.GraphSON;
-using Newtonsoft.Json.Linq;
 using Xunit;
 using Xunit.Sdk;
 
@@ -64,10 +64,10 @@
 
 internal class MyTypeReader : IGraphSONDeserializer
 {
-    public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+    public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
     {
-        var x = reader.ToObject(graphsonObject["x"]);
-        var y = reader.ToObject(graphsonObject["y"]);
+        var x = reader.ToObject(graphsonObject.GetProperty("x"));
+        var y = reader.ToObject(graphsonObject.GetProperty("y"));
         return new MyType(x, y);
     }
 }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
index e2c6ef6..377040c 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
@@ -24,12 +24,12 @@
 using System;
 using System.Collections.Generic;
 using System.Net.WebSockets;
+using System.Text.Json;
 using System.Threading.Tasks;
 using Gremlin.Net.Driver;
 using Gremlin.Net.Driver.Exceptions;
 using Gremlin.Net.Driver.Messages;
 using Gremlin.Net.IntegrationTest.Util;
-using Newtonsoft.Json.Linq;
 using Xunit;
 
 namespace Gremlin.Net.IntegrationTest.Driver
@@ -70,31 +70,29 @@
         }
 
         [Fact]
-        public async Task ShouldReturnResultWithoutDeserializingItForJTokenType()
+        public async Task ShouldReturnResultWithoutDeserializingItForJsonElementType()
         {
             var gremlinServer = new GremlinServer(TestHost, TestPort);
-            using (var gremlinClient = new GremlinClient(gremlinServer))
-            {
-                var gremlinScript = "'someString'";
+            using var gremlinClient = new GremlinClient(gremlinServer);
+            const string gremlinScript = "'someString'";
                 
-                var response = await gremlinClient.SubmitWithSingleResultAsync<JToken>(gremlinScript);
+            var response = await gremlinClient.SubmitWithSingleResultAsync<JsonElement>(gremlinScript);
 
-                //Expected:
-                /* {
+            //Expected:
+            /* {
                   "@type": "g:List",
                   "@value": [
                     "someString"
                   ]
                 }*/
 
-                Assert.IsType<JObject>(response);
-                Assert.Equal("g:List", response["@type"]);
+            Assert.IsType<JsonElement>(response);
+            Assert.Equal("g:List", response.GetProperty("@type").GetString());
 
-                var jArray = response["@value"] as JArray;
-                Assert.NotNull(jArray);
-                Assert.Equal(1, jArray.Count);
-                Assert.Equal("someString", (jArray[0] as JValue)?.Value);
-            }
+            var valueProperty = response.GetProperty("@value");
+            Assert.NotNull(valueProperty);
+            Assert.Equal(1, valueProperty.GetArrayLength());
+            Assert.Equal("someString", (valueProperty[0].GetString()));
         }
 
         [Fact]
@@ -129,7 +127,7 @@
                     await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync(requestMsg));
 
                 Assert.Equal(typeof(ResponseException), exception.GetType());
-                Assert.Contains($"ScriptEvaluationError: No such property: {requestMsg}",
+                Assert.Contains($"ServerEvaluationError: No such property: {requestMsg}",
                     exception.Message);
             }
         }
@@ -201,16 +199,14 @@
         public async Task ShouldReturnResponseAttributes()
         {
             var gremlinServer = new GremlinServer(TestHost, TestPort);
-            using (var gremlinClient = new GremlinClient(gremlinServer))
-            {
-                var requestMsg = _requestMessageProvider.GetDummyMessage();
-                var resultSet = await gremlinClient.SubmitAsync<int>(requestMsg);
+            using var gremlinClient = new GremlinClient(gremlinServer);
+            var requestMsg = _requestMessageProvider.GetDummyMessage();
+            var resultSet = await gremlinClient.SubmitAsync<int>(requestMsg);
 
-                Assert.NotNull(resultSet.StatusAttributes);
+            Assert.NotNull(resultSet.StatusAttributes);
 
-                var values= resultSet.StatusAttributes["@value"] as JArray;
-                Assert.True(values.First.ToString().Equals("host"));
-            }
+            var values = (JsonElement) resultSet.StatusAttributes["@value"];
+            Assert.True(values[0].ToString().Equals("host"));
         }
 
         [Fact]
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
index 0461572..bbb107b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
@@ -139,7 +139,7 @@
                 var thrownException =
                     await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync(requestMsg));
 
-                Assert.Contains("ScriptEvaluationError", thrownException.Message);
+                Assert.Contains("ServerEvaluationError", thrownException.Message);
                 Assert.Contains(unknownLanguage, thrownException.Message);
             }
         }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 8b56b73..1022856 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -26,13 +26,13 @@
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
+using System.Text.Json;
 using System.Text.RegularExpressions;
 using Gherkin.Ast;
 using Gremlin.Net.IntegrationTest.Gherkin.Attributes;
 using Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Structure;
-using Newtonsoft.Json.Linq;
 using Xunit;
 
 using static Gremlin.Net.Process.Traversal.AnonymousTraversalSource;
@@ -46,6 +46,8 @@
         private readonly IDictionary<string, object> _parameters = new Dictionary<string, object>();
         private ITraversal _traversal;
         private object[] _result;
+        private static readonly JsonSerializerOptions JsonDeserializingOptions = new JsonSerializerOptions
+            {PropertyNamingPolicy = JsonNamingPolicy.CamelCase};
 
         private static readonly IDictionary<Regex, Func<string, string, object>> Parsers =
             new Dictionary<string, Func<string, string, object>>
@@ -63,7 +65,8 @@
                 {@"s\[(.*)\]", ToSet},
                 {@"m\[(.+)\]", ToMap},
                 {@"c\[(.+)\]", ToLambda},
-                {@"t\[(.+)\]", ToT}
+                {@"t\[(.+)\]", ToT},
+                {"null", (_, __) => null}
             }.ToDictionary(kv => new Regex("^" + kv.Key + "$", RegexOptions.Compiled), kv => kv.Value);
 
         private static readonly IDictionary<char, Func<string, object>> NumericParsers =
@@ -180,6 +183,7 @@
                     var rows = table.Rows.ToArray();
                     Assert.Equal("result", rows[0].Cells.First().Value);
                     var expected = rows.Skip(1).Select(x => ParseValue(x.Cells.First().Value, _graphName));
+
                     if (ordered)
                     {
                         Assert.Equal(expected, _result);
@@ -232,7 +236,8 @@
 
         private static object ToMap(string stringMap, string graphName)
         {
-            return ParseMapValue(JObject.Parse(stringMap), graphName);
+            var jsonMap = JsonSerializer.Deserialize<JsonElement>(stringMap, JsonDeserializingOptions);
+            return ParseMapValue(jsonMap, graphName);
         }
 
         private static object ToLambda(string stringLambda, string graphName)
@@ -256,29 +261,45 @@
                 stringNumber.Substring(0, stringNumber.Length - 1));
         }
 
-        private static object ParseMapValue(JToken value, string graphName)
+        private static object ParseMapValue(JsonElement value, string graphName)
         {
-            if (value.Type == JTokenType.Object)
+            switch (value.ValueKind)
             {
-                IDictionary<string, JToken> jsonMap = (JObject)value;
-                return jsonMap.ToDictionary(kv => ParseMapValue(kv.Key, graphName),
-                    kv => ParseMapValue(kv.Value, graphName));
+                case JsonValueKind.Object:
+                {
+                    return value.EnumerateObject().ToDictionary(property => ParseValue(property.Name, graphName),
+                        property => ParseMapValue(property.Value, graphName));
+                }
+                case JsonValueKind.Array:
+                    return value.EnumerateArray().Select(v => ParseMapValue(v, graphName)).ToArray();
+                case JsonValueKind.Number:
+                {
+                    // This can maybe be simplified when this issue is resolved:
+                    // https://github.com/dotnet/runtime/issues/31274
+                    if (value.TryGetInt32(out var integer))
+                    {
+                        return integer;
+                    }
+
+                    if (value.TryGetDouble(out var floating))
+                    {
+                        return floating;
+                    }
+
+                    throw new ArgumentOutOfRangeException(nameof(value), value, "Not a supported number type");
+                }
+                case JsonValueKind.String:
+                    return ParseValue(value.GetString(), graphName);
+                case JsonValueKind.True:
+                    return true;
+                case JsonValueKind.False:
+                    return false;
+                case JsonValueKind.Null:
+                    return null;
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(value.ValueKind), value.ValueKind,
+                        "JSON type not supported");
             }
-            if (value.Type == JTokenType.Array)
-            {
-                return value.Select(v => ParseMapValue(v, graphName)).ToArray();
-            }
-            var objValue = value.ToObject<object>();
-            if (objValue is long longValue)
-            {
-                // JSON Numeric values converted to int64 by default
-                return Convert.ToInt32(longValue);
-            }
-            if (objValue is string stringValue)
-            {
-                return ParseValue(stringValue, graphName);
-            }
-            return objValue;
         }
 
         private static ISet<object> ToSet(string stringSet, string graphName)
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index 59fd11e..2649e68 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -41,6 +41,7 @@
             new Dictionary<string, IgnoreReason>
             {
                 // Add here the name of scenarios to ignore and the reason, e.g.:
+                { "g_V_group_byXageX", IgnoreReason.NullKeysInMapNotSupported }
                 //{ "g_V_properties_propertiesXstartTimeX_drop", IgnoreReason.NoReason },
             };
         
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
index 726e684..0e25440 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
@@ -50,12 +50,11 @@
     
     public enum IgnoreReason
     {
-        /// <summary>
-        /// Deserialization of g:T on GraphSON3 is not supported.
-        /// </summary>
-        TraversalTDeserializationNotSupported,
-        ReceivedDataDoesntMatchExpected,
         NoReason,
-        EmbeddedListAssertion
+
+        /// <summary>
+        /// C# does not allow a `null` value to be used as a key.
+        /// </summary>
+        NullKeysInMapNotSupported
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
index 8c80982..4a15178 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
@@ -104,14 +104,14 @@
 
         private static IDictionary<string, Vertex> GetVertices(GraphTraversalSource g)
         {
-            try
+            // Property name might not exist and C# doesn't support "null" keys in Dictionary
+            if (g.V().Count().Next() == g.V().Has("name").Count().Next())
             {
                 return g.V().Group<string, object>().By("name").By(__.Tail<Vertex>()).Next()
                     .ToDictionary(kv => kv.Key, kv => (Vertex) kv.Value);
             }
-            catch (ResponseException)
+            else
             {
-                // Property name might not exist
                 return EmptyVertices;
             }
         }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/LiteralParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/LiteralParameter.cs
index da0ac24..10a88a2 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/LiteralParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/LiteralParameter.cs
@@ -29,10 +29,15 @@
     /// <summary>
     /// Represents a literal (number / boolean) that is allowed as a gremlin parameter.
     /// </summary>
-    public class LiteralParameter<T> : ITokenParameter, IEquatable<LiteralParameter<T>> where T : struct
+    public class LiteralParameter<T> : ITokenParameter, IEquatable<LiteralParameter<T>>
     {
         public bool Equals(LiteralParameter<T> other)
         {
+            if (Value == null)
+            {
+                return other.Value == null;
+            }
+
             return Value.Equals(other.Value);
         }
 
@@ -46,7 +51,7 @@
 
         public override int GetHashCode()
         {
-            return Value.GetHashCode();
+            return Value?.GetHashCode() ?? 0;
         }
 
         public T Value { get; }
@@ -79,7 +84,7 @@
 
     internal static class LiteralParameter
     {
-        public static LiteralParameter<TType> Create<TType>(TType value) where TType : struct
+        public static LiteralParameter<TType> Create<TType>(TType value)
         {
             return new LiteralParameter<TType>(value);
         }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
index 105932f..b747200 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -36,7 +36,10 @@
         private static readonly IDictionary<string, Func<GraphTraversalSource, ITraversal>> FixedTranslations = 
             new Dictionary<string, Func<GraphTraversalSource, ITraversal>>
             {
-                { "g.V().fold().count(Scope.local)", g => g.V().Fold().Count(Scope.Local)}
+                { "g.V().fold().count(Scope.local)", g => g.V().Fold().Count(Scope.Local)},
+                { "g.inject(10,20,null,20,10,10).groupCount(\"x\").dedup().as(\"y\").project(\"a\",\"b\").by().by(__.select(\"x\").select(__.select(\"y\")))", 
+                    g => g.Inject<object>(10,20,null,20,10,10).GroupCount("x").Dedup().As("y").Project<object>("a","b").By().By(__.Select<int>("x").Select<object>(__.Select<int>("y")))},
+                { "g.inject(m).select(\"name\",\"age\")", g => g.Inject(new Dictionary<string,object>() {{"name", "marko"}, {"age", null}}).Select<object>("name", "age") }
             };
 
         private static readonly Regex RegexNumeric =
@@ -169,7 +172,7 @@
                     {
                         if (IsNumeric(methodParameter.ParameterType) && IsNumeric(tokenParameterType))
                         {
-                            // Acount for implicit conversion of numeric values as an exact match 
+                            // Account for implicit conversion of numeric values as an exact match
                             exactMatches++;
                         }
                         else if (!methodParameter.ParameterType.GetTypeInfo().IsAssignableFrom(tokenParameterType))
@@ -233,6 +236,7 @@
             var paramsInfo = method.GetParameters();
             var parameters = new object[paramsInfo.Length];
             genericParameterTypes = new Dictionary<string, Type>();
+
             for (var i = 0; i < paramsInfo.Length; i++)
             {
                 var info = paramsInfo[i];
@@ -246,15 +250,18 @@
                         // We've provided a value for parameter of a generic type, we can infer the
                         // type of the generic argument based on the parameter.
                         // For example, in the case of `Constant<E2>(E2 value)`
-                        // if we have the type of value we have the type of E2. 
+                        // if we have the type of value we have the type of E2.
                         genericParameterTypes.Add(info.ParameterType.Name, tokenParameter.GetParameterType());
                     }
                     else if (IsParamsArray(info) && info.ParameterType.GetElementType().IsGenericParameter)
                     {
                         // Its a method where the type parameter comes from an params Array
                         // e.g., Inject<S>(params S[] value)
-                        genericParameterTypes.Add(info.ParameterType.GetElementType().Name,
-                            tokenParameter.GetParameterType());
+                        var type = tokenParameter.GetParameterType();
+                        genericParameterTypes.Add(info.ParameterType.GetElementType().Name, type);
+
+                        // Use a placeholder value
+                        value = type.IsValueType ? Activator.CreateInstance(type) : new object();
                     }
 
                     if (info.ParameterType != tokenParameter.GetParameterType() && IsNumeric(info.ParameterType) &&
@@ -270,7 +277,6 @@
                     // For `params type[] value` we should provide an empty array
                     if (value == null)
                     {
-                        // An empty array
                         value = Array.CreateInstance(info.ParameterType.GetElementType(), 0);
                     }
                     else if (!value.GetType().IsArray)
@@ -286,8 +292,7 @@
                         }
 
                         var arr = Array.CreateInstance(elementType, token.Parameters.Count - i);
-                        arr.SetValue(value, 0);
-                        for (var j = 1; j < token.Parameters.Count - i; j++)
+                        for (var j = 0; j < token.Parameters.Count - i; j++)
                         {
                             arr.SetValue(token.Parameters[i + j].GetValue(), j);
                         }
@@ -449,6 +454,11 @@
                 i += parameterText.Length - 1;
                 return LiteralParameter.Create(Convert.ToBoolean(parameterText));
             }
+            if (parameterText == "null")
+            {
+                i += parameterText.Length - 1;
+                return LiteralParameter.Create<object>(null);
+            }
             if (RegexIO.IsMatch(parameterText))
             {
                 i += parameterText.Length - 1;
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
index 0f6bea6..5e11e33 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
@@ -220,6 +220,20 @@
         }
 
         [Fact]
+        public void ShouldUseSeedStrategyToReturnDeterministicResults()
+        {
+            var connection = _connectionFactory.CreateRemoteConnection();
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection).WithStrategies(new SeedStrategy(664664));
+
+            var shuffledResults = g.V().Values<string>("name").Order().By(Order.Shuffle).ToList();
+            Assert.Equal(shuffledResults, g.V().Values<string>("name").Order().By(Order.Shuffle).ToList());
+            Assert.Equal(shuffledResults, g.V().Values<string>("name").Order().By(Order.Shuffle).ToList());
+            Assert.Equal(shuffledResults, g.V().Values<string>("name").Order().By(Order.Shuffle).ToList());
+            Assert.Equal(shuffledResults, g.V().Values<string>("name").Order().By(Order.Shuffle).ToList());
+            Assert.Equal(shuffledResults, g.V().Values<string>("name").Order().By(Order.Shuffle).ToList());
+        }
+
+        [Fact]
         public async Task ShouldExecuteAsynchronouslyWhenPromiseIsCalled()
         {
             var connection = _connectionFactory.CreateRemoteConnection();
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs
deleted file mode 100644
index 5d98f97..0000000
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Gremlin.Net.Process.Traversal;
-using Xunit;
-
-namespace Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
-{
-    public class SideEffectTests
-    {
-        private readonly RemoteConnectionFactory _connectionFactory = new RemoteConnectionFactory();
-
-        [Fact]
-        public void ShouldReturnCachedSideEffectWhenGetIsCalledAfterClose()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-            var t = g.V().Aggregate("a").Iterate();
-
-            t.SideEffects.Get("a");
-            t.SideEffects.Close();
-            var results = t.SideEffects.Get("a");
-
-            Assert.NotNull(results);
-        }
-
-        [Fact]
-        public void ShouldThrowWhenGetIsCalledAfterCloseAndNoSideEffectsAreCachec()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-            var t = g.V().Aggregate("a").Iterate();
-
-            t.SideEffects.Close();
-            Assert.Throws<InvalidOperationException>(() => t.SideEffects.Get("a"));
-        }
-
-        [Fact]
-        public void ShouldThrowWhenGetIsCalledAfterDisposeAndNoSideEffectsAreCachec()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-            var t = g.V().Aggregate("a").Iterate();
-
-            t.SideEffects.Dispose();
-            Assert.Throws<InvalidOperationException>(() => t.SideEffects.Get("a"));
-        }
-
-        [Fact]
-        public void ShouldThrowWhenGetIsCalledWithAnUnknownKey()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-            var t = g.V().Iterate();
-
-            Assert.Throws<KeyNotFoundException>(() => t.SideEffects.Get("m"));
-        }
-
-        [Fact]
-        public void ShouldReturnAnEmptyCollectionWhenKeysIsCalledForTraversalWithoutSideEffect()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-
-            var t = g.V().Iterate();
-            var keys = t.SideEffects.Keys();
-
-            Assert.Equal(0, keys.Count);
-        }
-
-        [Fact]
-        public void ShouldReturnCachedKeysWhenForCloseAfterSomeGet()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-            var t = g.V().Aggregate("a").Aggregate("b").Iterate();
-
-            t.SideEffects.Get("a");
-            t.SideEffects.Close();
-            var keys = t.SideEffects.Keys();
-
-            Assert.Equal(2, keys.Count);
-            Assert.Contains("a", keys);
-            Assert.Contains("b", keys);
-        }
-
-        [Fact]
-        public void ShouldReturnSideEffectKeyWhenKeysIsCalledForNamedGroupCount()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-            var t = g.V().Out("created").GroupCount("m").By("name").Iterate();
-
-            var keys = t.SideEffects.Keys();
-
-            var keysList = keys.ToList();
-            Assert.Equal(1, keysList.Count);
-            Assert.Contains("m", keysList);
-        }
-
-        [Fact]
-        public async Task ShouldReturnSideEffectsKeysWhenKeysIsCalledOnTraversalThatExecutedAsynchronously()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-
-            var t = await g.V().Aggregate("a").Promise(x => x);
-            var keys = t.SideEffects.Keys();
-
-            Assert.Equal(1, keys.Count);
-            Assert.Contains("a", keys);
-        }
-
-        [Fact]
-        public async Task ShouldReturnSideEffectValueWhenGetIsCalledOnTraversalThatExecutedAsynchronously()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-
-            var t = await g.V().Aggregate("a").Promise(x => x);
-            var value = t.SideEffects.Get("a");
-
-            Assert.NotNull(value);
-        }
-
-        [Fact]
-        public async Task ShouldNotThrowWhenCloseIsCalledOnTraversalThatExecutedAsynchronously()
-        {
-            var connection = _connectionFactory.CreateRemoteConnection();
-            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
-
-            var t = await g.V().Aggregate("a").Promise(x => x);
-            t.SideEffects.Close();
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/JsonMessageSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/JsonMessageSerializerTests.cs
index 67766a5..79c1731 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/JsonMessageSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/JsonMessageSerializerTests.cs
@@ -23,15 +23,12 @@
 
 using Gremlin.Net.Driver;
 using Gremlin.Net.Driver.Messages;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
 using System;
 using System.Text;
 using Xunit;
 
 namespace Gremlin.Net.UnitTest.Driver
 {
-    // Will be used in future to switch to new .NET Core Json deserializer
     public class JsonMessageSerializerTests
     {
         [Fact]
@@ -39,7 +36,7 @@
         {
             var sut = new JsonMessageSerializer(GremlinClient.DefaultMimeType);
 
-            Assert.Throws<ArgumentNullException>(()=> sut.DeserializeMessage<ResponseMessage<JToken>>(null));
+            Assert.Throws<ArgumentNullException>(()=> sut.DeserializeMessage<ResponseMessage>(null));
         }
 
         [Fact]
@@ -47,7 +44,7 @@
         {
             var sut = new JsonMessageSerializer(GremlinClient.DefaultMimeType);
 
-            Assert.Null(sut.DeserializeMessage<ResponseMessage<JToken>>(new byte[0]));            
+            Assert.Null(sut.DeserializeMessage<ResponseMessage>(new byte[0]));            
         }
 
         [Fact]
@@ -56,7 +53,7 @@
             var sut = new JsonMessageSerializer(GremlinClient.DefaultMimeType);
             var ofEmpty = Encoding.UTF8.GetBytes("");
 
-            Assert.Null(sut.DeserializeMessage<ResponseMessage<JToken>>(ofEmpty));
+            Assert.Null(sut.DeserializeMessage<ResponseMessage>(ofEmpty));
         }
 
         [Fact]
@@ -65,7 +62,7 @@
             var sut = new JsonMessageSerializer(GremlinClient.DefaultMimeType);
             var ofNull = Encoding.UTF8.GetBytes("null");
 
-            Assert.Null(sut.DeserializeMessage<ResponseMessage<JToken>>(ofNull));
+            Assert.Null(sut.DeserializeMessage<ResponseMessage>(ofNull));
         }
     }
 }
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
index 415072f..90296be 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
@@ -12,7 +12,6 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
     <PackageReference Include="Moq" Version="4.7.99" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GraphTraversalSourceTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GraphTraversalSourceTests.cs
index b3c285f..2cc39a6 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GraphTraversalSourceTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GraphTraversalSourceTests.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System;
 using Gremlin.Net.Process.Traversal;
 using Xunit;
 
@@ -83,5 +84,15 @@
             Assert.Equal(5, clone.Bytecode.StepInstructions.Count);
             Assert.Equal(4, cloneClone.Bytecode.StepInstructions.Count);
         }
+        
+        [Fact]
+        public void ShouldOnlyAllowChildTraversalsThatAreAnonymous()
+        {
+            var g = AnonymousTraversalSource.Traversal();
+
+            g.V(0).AddE("self").To(__.V(1));
+
+            Assert.Throws<ArgumentException>(() => g.V(0).AddE("self").To(g.V(1)));
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TraversalTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TraversalTests.cs
index a7d62ac..e773f74 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TraversalTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TraversalTests.cs
@@ -24,7 +24,6 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using Moq;
 using Xunit;
 using Gremlin.Net.Process.Traversal;
 
@@ -180,16 +179,5 @@
             var expectedObjs = UnfoldBulks(objs, bulks);
             Assert.Equal(expectedObjs, traversedObjs);
         }
-
-        [Fact]
-        public void ShouldDisposeSideEffectsWhenDisposeIsCalled()
-        {
-            var sideEffectsMock = new Mock<ITraversalSideEffects>();
-            var traversal = new TestTraversal(new List<object>()) {SideEffects = sideEffectsMock.Object};
-
-            traversal.Dispose();
-
-            sideEffectsMock.Verify(m => m.Dispose());
-        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
index 9b39391..29a434f 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
@@ -162,6 +162,7 @@
         public TestTraversal(Bytecode bytecode)
         {
             Bytecode = bytecode;
+            IsAnonymous = true;
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
index 3a49143..d50da9c 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
@@ -24,11 +24,11 @@
 using System;
 using System.Collections.Generic;
 using System.Numerics;
+using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Structure;
 using Gremlin.Net.Structure.IO.GraphSON;
 using Moq;
-using Newtonsoft.Json.Linq;
 using Xunit;
 
 namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
@@ -61,17 +61,6 @@
             return new GraphSON2Reader();
         }
 
-        //During CI, we encountered a case where Newtonsoft.Json version 9.0.0
-        //was loaded although there is no obvious direct nor indirect dependency
-        //on that version of the library. An explicit reference to version
-        //11.0.0 from Gremlin.Net.UnitTest fixes that, however, it is
-        //still unclear what causes the downgrade. Until resolution, we keep this test.
-        [Fact]
-        public void NewtonsoftJsonVersionShouldSupportReallyBigIntegers()
-        {
-            Assert.Equal(new Version(11, 0, 0, 0), typeof(JToken).Assembly.GetName().Version);
-        }
-
         [Fact]
         public void ShouldDeserializeWithCustomDeserializerForNewType()
         {
@@ -80,259 +69,297 @@
                 {"NS:TestClass", new TestGraphSONDeserializer()}
             };
             var reader = new GraphSON2Reader(deserializerByGraphSONType);
-            var graphSON = "{\"@type\":\"NS:TestClass\",\"@value\":\"test\"}";
-
-            var jObject = JObject.Parse(graphSON);
-            var readObj = reader.ToObject(jObject);
-
-            Assert.Equal("test", readObj.Value);
+            const string graphSON = "{\"@type\":\"NS:TestClass\",\"@value\":\"test\"}";
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSON);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal("test", deserializedValue.Value);
         }
-
+        
         [Fact]
         public void ShouldDeserializeWithCustomDeserializerForCommonType()
         {
             var customSerializerMock = new Mock<IGraphSONDeserializer>();
-            var overrideTypeString = "g:Int64";
+            const string overrideTypeString = "g:Int64";
             var customSerializerByType = new Dictionary<string, IGraphSONDeserializer>
             {
                 {overrideTypeString, customSerializerMock.Object}
             };
             var reader = new GraphSON2Reader(customSerializerByType);
 
+            var jsonElement =
+                JsonSerializer.Deserialize<JsonElement>($"{{\"@type\":\"{overrideTypeString}\",\"@value\":12}}");
+            var deserializedValue = reader.ToObject(jsonElement);
 
-            reader.ToObject(JObject.Parse($"{{\"@type\":\"{overrideTypeString}\",\"@value\":12}}"));
-
-            customSerializerMock.Verify(m => m.Objectify(It.IsAny<JToken>(), It.IsAny<GraphSONReader>()));
+            customSerializerMock.Verify(m => m.Objectify(It.IsAny<JsonElement>(), It.IsAny<GraphSONReader>()));
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDateToDateTimeOffset(int version)
         {
-            var graphSon = "{\"@type\":\"g:Date\",\"@value\":1475583442552}";
+            const string graphSon = "{\"@type\":\"g:Date\",\"@value\":1475583442552}";
             var reader = CreateStandardGraphSONReader(version);
-
-            DateTimeOffset deserializedValue = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             var expectedDateTimeOffset = TestUtils.FromJavaTime(1475583442552);
             Assert.Equal(expectedDateTimeOffset, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDictionary(int version)
         {
-            var serializedDict = "{\"age\":[{\"@type\":\"g:Int32\",\"@value\":29}],\"name\":[\"marko\"]}";
+            const string serializedDict = "{\"age\":[{\"@type\":\"g:Int32\", \"@value\":29}], \"name\":[\"marko\"], " +
+                                          "\"gender\": null}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedDict);
-            var deserializedDict = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedDict);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             var expectedDict = new Dictionary<string, dynamic>
             {
                 {"age", new List<object> {29}},
-                {"name", new List<object> {"marko"}}
+                {"name", new List<object> {"marko"}},
+                {"gender", null}
             };
-            Assert.Equal(expectedDict, deserializedDict);
+            Assert.Equal(expectedDict, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeEdge(int version)
         {
-            var graphSon =
-                "{\"@type\":\"g:Edge\", \"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":17},\"label\":\"knows\",\"inV\":\"x\",\"outV\":\"y\",\"inVLabel\":\"xLab\",\"properties\":{\"aKey\":\"aValue\",\"bKey\":true}}}";
+            const string graphSon = "{\"@type\":\"g:Edge\", \"@value\":{\"id\":{\"@type\":\"g:Int64\", \"@value\":17}, " +
+                                    "\"label\":\"knows\", \"inV\":\"x\", \"outV\":\"y\", \"inVLabel\":\"xLab\", " +
+                                    "\"properties\":{\"aKey\":\"aValue\", \"bKey\":true}}}";
             var reader = CreateStandardGraphSONReader(version);
-
-            Edge readEdge = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            Edge readEdge = reader.ToObject(jsonElement);
+        
             Assert.Equal((long) 17, readEdge.Id);
             Assert.Equal("knows", readEdge.Label);
             Assert.Equal(new Vertex("x", "xLabel"), readEdge.InV);
             Assert.Equal(new Vertex("y"), readEdge.OutV);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeInt(int version)
         {
             var serializedValue = "{\"@type\":\"g:Int32\",\"@value\":5}";
             var reader = CreateStandardGraphSONReader(version);
 
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(5, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeLong(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Int64\",\"@value\":5}";
+            const string serializedValue = "{\"@type\":\"g:Int64\",\"@value\":5}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal((long) 5, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeFloat(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Float\",\"@value\":31.3}";
+            const string serializedValue = "{\"@type\":\"g:Float\",\"@value\":31.3}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal((float) 31.3, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDouble(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Double\",\"@value\":31.2}";
+            const string serializedValue = "{\"@type\":\"g:Double\",\"@value\":31.2}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(31.2, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeNaN(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Double\",\"@value\":'NaN'}";
+            const string serializedValue = "{\"@type\":\"g:Double\",\"@value\":\"NaN\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(Double.NaN, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializePositiveInfinity(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Double\",\"@value\":'Infinity'}";
+            const string serializedValue = "{\"@type\":\"g:Double\",\"@value\":\"Infinity\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
-            Assert.Equal(Double.PositiveInfinity, deserializedValue);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(double.PositiveInfinity, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeNegativeInfinity(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Double\",\"@value\":'-Infinity'}";
+            const string serializedValue = "{\"@type\":\"g:Double\",\"@value\":\"-Infinity\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
-            Assert.Equal(Double.NegativeInfinity, deserializedValue);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(double.NegativeInfinity, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDecimal(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:BigDecimal\",\"@value\":-8.201}";
+            const string serializedValue = "{\"@type\":\"gx:BigDecimal\",\"@value\":-8.201}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            decimal deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(-8.201M, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDecimalValueAsString(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:BigDecimal\",\"@value\":\"7.50\"}";
+            const string serializedValue = "{\"@type\":\"gx:BigDecimal\",\"@value\":\"7.50\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            decimal deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            decimal deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(7.5M, deserializedValue);
         }
-
+        
+        [Theory, MemberData(nameof(Versions))]
+        public void ShouldDeserializeByte(int version)
+        {
+            const string serializedValue = "{\"@type\":\"gx:Byte\",\"@value\":1}";
+            var reader = CreateStandardGraphSONReader(version);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(1, deserializedValue);
+        }
+        
+        [Theory, MemberData(nameof(Versions))]
+        public void ShouldDeserializeChar(int version)
+        {
+            const string serializedValue = "{\"@type\":\"gx:Char\",\"@value\":\"x\"}";
+            var reader = CreateStandardGraphSONReader(version);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal('x', deserializedValue);
+        }
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeList(int version)
         {
-            var serializedValue = "[{\"@type\":\"g:Int32\",\"@value\":5},{\"@type\":\"g:Int32\",\"@value\":6}]";
+            const string serializedValue = "[{\"@type\":\"g:Int32\", \"@value\":5}, {\"@type\":\"g:Int32\", " +
+                                           "\"@value\":6}, null]";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JArray.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
-            Assert.Equal(new List<object> {5, 6}, deserializedValue);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(new List<object> {5, 6, null}, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeT(int version)
         {
-            var graphSon = "{\"@type\":\"g:T\",\"@value\":\"label\"}";
+            const string graphSon = "{\"@type\":\"g:T\",\"@value\":\"label\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            T readT = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            T readT = reader.ToObject(jsonElement);
+        
             Assert.Equal(T.Label, readT);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDirection(int version)
         {
-            var serializedValue = "{\"@type\":\"g:Direction\",\"@value\":\"OUT\"}";
+            const string serializedValue = "{\"@type\":\"g:Direction\",\"@value\":\"OUT\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(Direction.Out, deserializedValue);
         }
-
+        
         [Fact]
         public void ShouldDeserializePathFromGraphSON2()
         {
-            var graphSon =
+            const string graphSon =
                 "{\"@type\":\"g:Path\",\"@value\":{\"labels\":[[\"a\"],[\"b\",\"c\"],[]],\"objects\":[{\"@type\":\"g:Vertex\",\"@value\":{\"id\":{\"@type\":\"g:Int32\",\"@value\":1},\"label\":\"person\",\"properties\":{\"name\":[{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":0},\"value\":\"marko\",\"label\":\"name\"}}],\"age\":[{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":1},\"value\":{\"@type\":\"g:Int32\",\"@value\":29},\"label\":\"age\"}}]}}},{\"@type\":\"g:Vertex\",\"@value\":{\"id\":{\"@type\":\"g:Int32\",\"@value\":3},\"label\":\"software\",\"properties\":{\"name\":[{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":4},\"value\":\"lop\",\"label\":\"name\"}}],\"lang\":[{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":5},\"value\":\"java\",\"label\":\"lang\"}}]}}},\"lop\"]}}";
             var reader = CreateStandardGraphSONReader(2);
-
-            Path readPath = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            Path readPath = reader.ToObject(jsonElement);
+        
             Assert.Equal("path[v[1], v[3], lop]", readPath.ToString());
             Assert.Equal(new Vertex(1), readPath[0]);
             Assert.Equal(new Vertex(1), readPath["a"]);
             Assert.Equal("lop", readPath[2]);
             Assert.Equal(3, readPath.Count);
         }
-
+        
         [Fact]
         public void ShouldDeserializePathFromGraphSON3()
         {
-            var graphSon = "{\"@type\":\"g:Path\",\"@value\":{" +
-                           "\"labels\":{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Set\",\"@value\":[\"z\"]}]}," +
-                           "\"objects\":{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Vertex\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":5},\"label\":\"\"}}]}}}";
+            const string graphSon = "{\"@type\":\"g:Path\",\"@value\":{" +
+                                    "\"labels\":{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Set\",\"@value\":[\"z\"]}]}," +
+                                    "\"objects\":{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Vertex\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":5},\"label\":\"\"}}]}}}";
             var reader = CreateStandardGraphSONReader(3);
-
-            Path readPath = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            Path readPath = reader.ToObject(jsonElement);
+        
             Assert.Equal("path[v[5]]", readPath.ToString());
             Assert.Equal(new Vertex(5L), readPath[0]);
             Assert.Equal(new Vertex(5L), readPath["z"]);
             Assert.Equal(1, readPath.Count);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializePropertyWithEdgeElement(int version)
         {
-            var graphSon =
-                "{\"@type\":\"g:Property\",\"@value\":{\"key\":\"aKey\",\"value\":{\"@type\":\"g:Int64\",\"@value\":17},\"element\":{\"@type\":\"g:Edge\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":122},\"label\":\"knows\",\"inV\":\"x\",\"outV\":\"y\",\"inVLabel\":\"xLab\"}}}}";
+            const string graphSon = "{\"@type\":\"g:Property\", \"@value\":{\"key\":\"aKey\", " +
+                                    "\"value\":{\"@type\":\"g:Int64\", \"@value\":17}, " +
+                                    "\"element\":{\"@type\":\"g:Edge\", \"@value\":{\"id\":{\"@type\":\"g:Int64\", " +
+                                    "\"@value\":122}, \"label\":\"knows\", \"inV\":\"x\", \"outV\":\"y\", " +
+                                    "\"inVLabel\":\"xLab\"}}}}";
             var reader = CreateStandardGraphSONReader(version);
-
-            Property readProperty = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            Property readProperty = reader.ToObject(jsonElement);
+        
             Assert.Equal("aKey", readProperty.Key);
             Assert.Equal((long) 17, readProperty.Value);
             Assert.Equal(typeof(Edge), readProperty.Element.GetType());
@@ -342,265 +369,285 @@
             Assert.Equal("x", edge.InV.Id);
             Assert.Equal("y", edge.OutV.Id);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeTimestampToDateTimeOffset(int version)
         {
-            var graphSon = "{\"@type\":\"g:Timestamp\",\"@value\":1475583442558}";
+            const string graphSon = "{\"@type\":\"g:Timestamp\",\"@value\":1475583442558}";
             var reader = CreateStandardGraphSONReader(version);
-
-            DateTimeOffset deserializedValue = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             var expectedDateTimeOffset = TestUtils.FromJavaTime(1475583442558);
             Assert.Equal(expectedDateTimeOffset, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeGuid(int version)
         {
-            var graphSon = "{\"@type\":\"g:UUID\",\"@value\":\"41d2e28a-20a4-4ab0-b379-d810dede3786\"}";
+            const string graphSon = "{\"@type\":\"g:UUID\",\"@value\":\"41d2e28a-20a4-4ab0-b379-d810dede3786\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            Guid readGuid = reader.ToObject(JObject.Parse(graphSon));
-
-            Assert.Equal(Guid.Parse("41d2e28a-20a4-4ab0-b379-d810dede3786"), readGuid);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(Guid.Parse("41d2e28a-20a4-4ab0-b379-d810dede3786"), deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeVertexProperty(int version)
         {
-            var graphSon =
-                "{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":\"anId\",\"label\":\"aKey\",\"value\":true,\"vertex\":{\"@type\":\"g:Int32\",\"@value\":9}}}";
+            const string graphSon = "{\"@type\":\"g:VertexProperty\", \"@value\":{\"id\":\"anId\", \"label\":\"aKey\", " +
+                                    "\"value\":true, \"vertex\":{\"@type\":\"g:Int32\", \"@value\":9}}}";
             var reader = CreateStandardGraphSONReader(version);
-
-            VertexProperty readVertexProperty = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            VertexProperty readVertexProperty = reader.ToObject(jsonElement);
+        
             Assert.Equal("anId", readVertexProperty.Id);
             Assert.Equal("aKey", readVertexProperty.Label);
             Assert.True(readVertexProperty.Value);
             Assert.NotNull(readVertexProperty.Vertex);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeVertexPropertyWithLabel(int version)
         {
-            var graphSon =
-                "{\"@type\":\"g:VertexProperty\", \"@value\":{\"id\":{\"@type\":\"g:Int32\",\"@value\":1},\"label\":\"name\",\"value\":\"marko\"}}";
+            const string graphSon = "{\"@type\":\"g:VertexProperty\", \"@value\":{\"id\":{\"@type\":\"g:Int32\", " +
+                                    "\"@value\":1}, \"label\":\"name\", \"value\":\"marko\"}}";
             var reader = CreateStandardGraphSONReader(version);
-
-            VertexProperty readVertexProperty = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            VertexProperty readVertexProperty = reader.ToObject(jsonElement);
+        
             Assert.Equal(1, readVertexProperty.Id);
             Assert.Equal("name", readVertexProperty.Label);
             Assert.Equal("marko", readVertexProperty.Value);
             Assert.Null(readVertexProperty.Vertex);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeVertex(int version)
         {
-            var graphSon = "{\"@type\":\"g:Vertex\", \"@value\":{\"id\":{\"@type\":\"g:Float\",\"@value\":45.23}}}";
+            const string graphSon = "{\"@type\":\"g:Vertex\", \"@value\":{\"id\":{\"@type\":\"g:Float\", " +
+                                    "\"@value\":45.23}}}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var readVertex = reader.ToObject(JObject.Parse(graphSon));
-
-            Assert.Equal(new Vertex(45.23f), readVertex);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(new Vertex(45.23f), deserializedValue);
         }
-
+        
+        [Theory, MemberData(nameof(Versions))]
+        public void ShouldDeserializeVertexWithLabel(int version)
+        {
+            const string graphSon = "{\"@type\":\"g:Vertex\", \"@value\":{\"id\":{\"@type\":\"g:Float\", " +
+                                    "\"@value\":45.23}, \"label\": \"person\"}}";
+            var reader = CreateStandardGraphSONReader(version);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            Vertex deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal("person", deserializedValue.Label);
+        }
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeVertexWithEdges(int version)
         {
-            var graphSon =
+            const string graphSon =
                 "{\"@type\":\"g:Vertex\", \"@value\":{\"id\":{\"@type\":\"g:Int32\",\"@value\":1},\"label\":\"person\",\"outE\":{\"created\":[{\"id\":{\"@type\":\"g:Int32\",\"@value\":9},\"inV\":{\"@type\":\"g:Int32\",\"@value\":3},\"properties\":{\"weight\":{\"@type\":\"g:Double\",\"@value\":0.4}}}],\"knows\":[{\"id\":{\"@type\":\"g:Int32\",\"@value\":7},\"inV\":{\"@type\":\"g:Int32\",\"@value\":2},\"properties\":{\"weight\":{\"@type\":\"g:Double\",\"@value\":0.5}}},{\"id\":{\"@type\":\"g:Int32\",\"@value\":8},\"inV\":{\"@type\":\"g:Int32\",\"@value\":4},\"properties\":{\"weight\":{\"@type\":\"g:Double\",\"@value\":1.0}}}]},\"properties\":{\"name\":[{\"id\":{\"@type\":\"g:Int64\",\"@value\":0},\"value\":\"marko\"}],\"age\":[{\"id\":{\"@type\":\"g:Int64\",\"@value\":1},\"value\":{\"@type\":\"g:Int32\",\"@value\":29}}]}}}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var readVertex = reader.ToObject(JObject.Parse(graphSon));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            Vertex readVertex = reader.ToObject(jsonElement);
+        
             Assert.Equal(new Vertex(1), readVertex);
             Assert.Equal("person", readVertex.Label);
             Assert.Equal(typeof(int), readVertex.Id.GetType());
         }
-
+        
         [Theory, MemberData(nameof(VersionsSupportingCollections))]
         public void ShouldDeserializeEmptyGList(int version)
         {
-            var graphSon =
-                "{\"@type\":\"g:List\", \"@value\": []}";
+            const string graphSon = "{\"@type\":\"g:List\", \"@value\": []}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var deserializedValue = reader.ToObject(JObject.Parse(graphSon));
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+            
             Assert.Equal(new object[0], deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(VersionsSupportingCollections))]
         public void ShouldDeserializeGList(int version)
         {
             const string json = "{\"@type\":\"g:List\", \"@value\": [{\"@type\": \"g:Int32\", \"@value\": 1}," +
                                 "{\"@type\": \"g:Int32\", \"@value\": 2}, {\"@type\": \"g:Int32\", \"@value\": 3}]}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var deserializedValue = reader.ToObject(JObject.Parse(json));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal((IList<object>)new object[] { 1, 2, 3}, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(VersionsSupportingCollections))]
         public void ShouldDeserializeGSet(int version)
         {
-            const string json = "{\"@type\":\"g:Set\", \"@value\": [{\"@type\": \"g:Int32\", \"@value\": 1}," +
-                                "{\"@type\": \"g:Int32\", \"@value\": 2}, {\"@type\": \"g:Int32\", \"@value\": 3}]}";
+            const string graphSon = "{\"@type\":\"g:Set\", \"@value\": [{\"@type\": \"g:Int32\", \"@value\": 1}," +
+                                    "{\"@type\": \"g:Int32\", \"@value\": 2}, {\"@type\": \"g:Int32\", \"@value\": 3}]}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var deserializedValue = reader.ToObject(JObject.Parse(json));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal((ISet<object>)new HashSet<object>{ 1, 2, 3}, deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(VersionsSupportingCollections))]
         public void ShouldDeserializeGMap(int version)
         {
             const string json = "{\"@type\":\"g:Map\", \"@value\": [\"a\",{\"@type\": \"g:Int32\", \"@value\": 1}, " +
                                 "\"b\", {\"@type\": \"g:Int32\", \"@value\": 2}]}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var deserializedValue = reader.ToObject(JObject.Parse(json));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(new Dictionary<object, object>{ { "a", 1 }, { "b", 2 }}, deserializedValue);
         }
-
+        
+        [Theory, MemberData(nameof(VersionsSupportingCollections))]
+        public void ShouldDeserializeGMapWithNonStringKeys(int version)
+        {
+            const string json = "{\"@type\":\"g:Map\", \"@value\": [{\"@type\":\"g:Int32\", \"@value\":123}, \"red\"]}";
+            var reader = CreateStandardGraphSONReader(version);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
+            Assert.Equal(new Dictionary<object, object>{ { 123, "red" }}, deserializedValue);
+        }
+        
         [Theory, MemberData(nameof(VersionsSupportingCollections))]
         public void ShouldDeserializeBulkSet(int version)
         {
-            const string json = "{\"@type\": \"g:BulkSet\", \"@value\": [" +
-                                "\"marko\", {\"@type\": \"g:Int64\", \"@value\": 1}, " +
-                                "\"josh\", {\"@type\": \"g:Int64\", \"@value\": 3}]}";
+            const string graphSon = "{\"@type\": \"g:BulkSet\", \"@value\": [" +
+                                    "\"marko\", {\"@type\": \"g:Int64\", \"@value\": 1}, " +
+                                    "\"josh\", {\"@type\": \"g:Int64\", \"@value\": 3}]}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var deserializedValue = reader.ToObject(JObject.Parse(json));
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(new List<object>{ "marko", "josh", "josh", "josh" }, deserializedValue);
         }
-
+        
         [Fact]
         public void ShouldDeserializeBulkSetWithGraphSON3()
         {
-            const string json =
+            const string graphSon =
                 "{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Traverser\",\"@value\":{\"bulk\":{\"@type\":\"g:Int64\",\"@value\":1},\"value\":{\"@type\":\"g:BulkSet\",\"@value\":[{\"@type\":\"g:Int64\",\"@value\":1},{\"@type\":\"g:Int64\",\"@value\":2},{\"@type\":\"g:Int64\",\"@value\":0},{\"@type\":\"g:Int64\",\"@value\":3},{\"@type\":\"g:Int64\",\"@value\":2},{\"@type\":\"g:Int64\",\"@value\":1},{\"@type\":\"g:Double\",\"@value\":1.0},{\"@type\":\"g:Int64\",\"@value\":2}]}}}]}";
             var reader = CreateStandardGraphSONReader(3);
-            var deserializedValue = reader.ToObject(JObject.Parse(json));
+            
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
         }
-
-        [Fact]
-        public void ShouldDeserializeTraverser()
+        
+        [Theory, MemberData(nameof(VersionsSupportingCollections))]
+        public void ShouldDeserializeTraverser(int version)
         {
-            dynamic d = JObject.Parse("{\"@type\":\"g:Traverser\",\"@value\":1,\"bulk\": {\"type\":\"g:Int64\",\"value\":10}}");
-
-            Assert.NotNull(d);
-            Assert.Equal("g:Traverser", (string)d["@type"]);
+            const string json = "{\"@type\":\"g:Traverser\", \"@value\":{\"bulk\":{\"@type\":\"g:Int64\", " +
+                                "\"@value\":10}, \"value\":{\"@type\":\"g:Int32\", \"@value\":1}}}";
+            var reader = CreateStandardGraphSONReader(version);
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
+            Traverser deserializedValue = reader.ToObject(jsonElement);
+            
+            Assert.Equal(10, deserializedValue.Bulk);
+            Assert.Equal(1, deserializedValue.Object);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeDurationToTimeSpan(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:Duration\",\"@value\":\"PT120H\"}";
+            const string graphSon = "{\"@type\":\"gx:Duration\",\"@value\":\"PT120H\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            TimeSpan deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(TimeSpan.FromDays(5), deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeBigInteger(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:BigInteger\",\"@value\":123456789}";
+            var graphSon = "{\"@type\":\"gx:BigInteger\",\"@value\":123456789}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            BigInteger deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(BigInteger.Parse("123456789"), deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeBigIntegerValueAsString(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:BigInteger\",\"@value\":\"123456789\"}";
+            var graphSon = "{\"@type\":\"gx:BigInteger\", \"@value\":\"123456789\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            BigInteger deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(BigInteger.Parse("123456789"), deserializedValue);
         }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeReallyBigIntegerValue(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:BigInteger\",\"@value\":123456789987654321123456789987654321}";
+            const string graphSon = "{\"@type\":\"gx:BigInteger\", \"@value\":123456789987654321123456789987654321}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            BigInteger deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(BigInteger.Parse("123456789987654321123456789987654321"), deserializedValue);
         }
-
-        [Theory, MemberData(nameof(Versions))]
-        public void ShouldDeserializeByte(int version)
-        {
-            var serializedValue = "{\"@type\":\"gx:Byte\",\"@value\":1}";
-            var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
-            Assert.Equal(1, deserializedValue);
-        }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeByteBuffer(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:ByteBuffer\",\"@value\":\"c29tZSBieXRlcyBmb3IgeW91\"}";
+            const string graphSon = "{\"@type\":\"gx:ByteBuffer\", \"@value\":\"c29tZSBieXRlcyBmb3IgeW91\"}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(Convert.FromBase64String("c29tZSBieXRlcyBmb3IgeW91"), deserializedValue);
         }
-
-        [Theory, MemberData(nameof(Versions))]
-        public void ShouldDeserializeChar(int version)
-        {
-            var serializedValue = "{\"@type\":\"gx:Char\",\"@value\":\"x\"}";
-            var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
-            Assert.Equal('x', deserializedValue);
-        }
-
+        
         [Theory, MemberData(nameof(Versions))]
         public void ShouldDeserializeInt16(int version)
         {
-            var serializedValue = "{\"@type\":\"gx:Int16\",\"@value\":100}";
+            const string graphSon = "{\"@type\":\"gx:Int16\", \"@value\":100}";
             var reader = CreateStandardGraphSONReader(version);
-
-            var jObject = JObject.Parse(serializedValue);
-            var deserializedValue = reader.ToObject(jObject);
-
+        
+            var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
+            var deserializedValue = reader.ToObject(jsonElement);
+        
             Assert.Equal(100, deserializedValue);
         }
     }
 
     internal class TestGraphSONDeserializer : IGraphSONDeserializer
     {
-        public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+        public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return new TestClass {Value = graphsonObject.ToString()};
+            return new TestClass {Value = graphsonObject.GetString()};
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
index 409776b..ce593f7 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
@@ -203,6 +203,8 @@
         public void ShouldSerializeWithCustomSerializerForCommonType()
         {
             var customSerializerMock = new Mock<IGraphSONSerializer>();
+            customSerializerMock.Setup(m => m.Dictify(It.IsAny<int>(), It.IsAny<GraphSONWriter>()))
+                .Returns(new Dictionary<string, dynamic>());
             var customSerializerByType = new Dictionary<Type, IGraphSONSerializer>
             {
                 {typeof(int), customSerializerMock.Object}
@@ -282,12 +284,12 @@
         public void ShouldSerializeGList(int version)
         {
             var writer = CreateGraphSONWriter(version);
-            var list = new List<object> {5, 6};
+            var list = new List<object> {5, 6, null};
 
             var serializedGraphSON = writer.WriteObject(list);
 
             var expectedGraphSON = "{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Int32\",\"@value\":5}," +
-                                   "{\"@type\":\"g:Int32\",\"@value\":6}]}";
+                                   "{\"@type\":\"g:Int32\",\"@value\":6},null]}";
             Assert.Equal(expectedGraphSON, serializedGraphSON);
         }
 
diff --git a/gremlin-dotnet/test/pom.xml b/gremlin-dotnet/test/pom.xml
index 67db676..e3565ff 100644
--- a/gremlin-dotnet/test/pom.xml
+++ b/gremlin-dotnet/test/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>gremlin-dotnet</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-dotnet-tests</artifactId>
     <name>Apache TinkerPop :: Gremlin.Net - Tests</name>
@@ -103,21 +103,27 @@
                         <artifactId>gmavenplus-plugin</artifactId>
                         <dependencies>
                             <dependency>
-                                <groupId>log4j</groupId>
-                                <artifactId>log4j</artifactId>
-                                <version>1.2.17</version>
-                                <scope>runtime</scope>
-                            </dependency>
-                            <dependency>
                                 <groupId>org.apache.tinkerpop</groupId>
                                 <artifactId>gremlin-server</artifactId>
                                 <version>${project.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.tinkerpop</groupId>
+                                <artifactId>gremlin-test</artifactId>
+                                <version>${project.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>log4j</groupId>
+                                <artifactId>log4j</artifactId>
+                                <version>${log4j.version}</version>
                                 <scope>runtime</scope>
                             </dependency>
                             <dependency>
                                 <groupId>org.codehaus.groovy</groupId>
-                                <artifactId>groovy-ant</artifactId>
+                                <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
+                                <type>pom</type>
+                                <scope>runtime</scope>
                             </dependency>
                         </dependencies>
                         <executions>
@@ -134,10 +140,6 @@
                                             <value>${skipTests}</value>
                                         </property>
                                         <property>
-                                            <name>python</name>
-                                            <value>false</value>
-                                        </property>
-                                        <property>
                                             <name>gremlinServerDir</name>
                                             <value>${gremlin.server.dir}</value>
                                         </property>
diff --git a/gremlin-driver/pom.xml b/gremlin-driver/pom.xml
index bd997a6..c63f7ed 100644
--- a/gremlin-driver/pom.xml
+++ b/gremlin-driver/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-driver</artifactId>
     <name>Apache TinkerPop :: Gremlin Driver</name>
@@ -95,7 +95,7 @@
         </dependency>
         <dependency>
             <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
+            <artifactId>hamcrest</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
index c739a15..69a0725 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
@@ -23,8 +23,6 @@
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
-import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder;
-import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketClientHandler;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketGremlinRequestEncoder;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketGremlinResponseDecoder;
@@ -231,23 +229,4 @@
             }
         }
     }
-
-    /**
-     * NIO {@link Channelizer} implementation.
-     *
-     * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
-     */
-    @Deprecated
-    public final class NioChannelizer extends AbstractChannelizer {
-        @Override
-        public void init(final Connection connection) {
-            super.init(connection);
-        }
-
-        @Override
-        public void configure(ChannelPipeline pipeline) {
-            pipeline.addLast("gremlin-decoder", new NioGremlinResponseDecoder(cluster.getSerializer()));
-            pipeline.addLast("gremlin-encoder", new NioGremlinRequestEncoder(true, cluster.getSerializer()));
-        }
-    }
 }
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
index 9cbc337..51b8ed6 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
@@ -340,7 +340,7 @@
                 .add(Tokens.ARGS_BATCH_SIZE, batchSize);
 
         // apply settings if they were made available
-        options.getTimeout().ifPresent(timeout -> request.add(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT, timeout));
+        options.getTimeout().ifPresent(timeout -> request.add(Tokens.ARGS_EVAL_TIMEOUT, timeout));
         options.getParameters().ifPresent(params -> request.addArg(Tokens.ARGS_BINDINGS, params));
         options.getAliases().ifPresent(aliases -> request.addArg(Tokens.ARGS_ALIASES, aliases));
         options.getOverrideRequestId().ifPresent(request::overrideRequestId);
@@ -564,7 +564,7 @@
 
                 // apply settings if they were made available
                 options.getBatchSize().ifPresent(batchSize -> request.add(Tokens.ARGS_BATCH_SIZE, batchSize));
-                options.getTimeout().ifPresent(timeout -> request.add(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT, timeout));
+                options.getTimeout().ifPresent(timeout -> request.add(Tokens.ARGS_EVAL_TIMEOUT, timeout));
                 options.getOverrideRequestId().ifPresent(request::overrideRequestId);
                 options.getUserAgent().ifPresent(userAgent -> request.add(Tokens.ARGS_USER_AGENT, userAgent));
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index 8af727d..44937c6 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -24,7 +24,7 @@
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import io.netty.bootstrap.Bootstrap;
@@ -181,11 +181,7 @@
                 .port(settings.port)
                 .path(settings.path)
                 .enableSsl(settings.connectionPool.enableSsl)
-                .trustCertificateChainFile(settings.connectionPool.trustCertChainFile)
                 .keepAliveInterval(settings.connectionPool.keepAliveInterval)
-                .keyCertChainFile(settings.connectionPool.keyCertChainFile)
-                .keyFile(settings.connectionPool.keyFile)
-                .keyPassword(settings.connectionPool.keyPassword)
                 .keyStore(settings.connectionPool.keyStore)
                 .keyStorePassword(settings.connectionPool.keyStorePassword)
                 .keyStoreType(settings.connectionPool.keyStoreType)
@@ -398,16 +394,6 @@
     }
 
     /**
-     * Gets how long a session will stay open assuming the current connection actually is configured for their use.
-     *
-     * @deprecated As of release 3.3.11, replaced in essence by {@link #getMaxWaitForClose()}.
-     */
-    @Deprecated
-    public int getMaxWaitForSessionClose() {
-        return manager.connectionPoolSettings.maxWaitForSessionClose;
-    }
-
-    /**
      * Gets how long a connection will wait for all pending messages to be returned from the server before closing.
      */
     public int getMaxWaitForClose() {
@@ -501,21 +487,6 @@
         final Settings.ConnectionPoolSettings connectionPoolSettings = connectionPoolSettings();
         final SslContextBuilder builder = SslContextBuilder.forClient();
 
-        if (connectionPoolSettings.trustCertChainFile != null) {
-            logger.warn("Using deprecated SSL trustCertChainFile support");
-            builder.trustManager(new File(connectionPoolSettings.trustCertChainFile));
-        }
-
-        if (null != connectionPoolSettings.keyCertChainFile && null != connectionPoolSettings.keyFile) {
-            logger.warn("Using deprecated SSL keyFile support");
-            final File keyCertChainFile = new File(connectionPoolSettings.keyCertChainFile);
-            final File keyFile = new File(connectionPoolSettings.keyFile);
-
-            // note that keyPassword may be null here if the keyFile is not
-            // password-protected.
-            builder.keyManager(keyCertChainFile, keyFile, connectionPoolSettings.keyPassword);
-        }
-
         // Build JSSE SSLContext
         try {
 
@@ -586,7 +557,6 @@
         private int maxInProcessPerConnection = Connection.MAX_IN_PROCESS;
         private int minInProcessPerConnection = Connection.MIN_IN_PROCESS;
         private int maxWaitForConnection = Connection.MAX_WAIT_FOR_CONNECTION;
-        private int maxWaitForSessionClose = Connection.MAX_WAIT_FOR_SESSION_CLOSE;
         private int maxWaitForClose = Connection.MAX_WAIT_FOR_CLOSE;
         private int maxContentLength = Connection.MAX_CONTENT_LENGTH;
         private int reconnectInterval = Connection.RECONNECT_INTERVAL;
@@ -594,10 +564,6 @@
         private long keepAliveInterval = Connection.KEEP_ALIVE_INTERVAL;
         private String channelizer = Channelizer.WebSocketChannelizer.class.getName();
         private boolean enableSsl = false;
-        private String trustCertChainFile = null;
-        private String keyCertChainFile = null;
-        private String keyFile = null;
-        private String keyPassword = null;
         private String keyStore = null;
         private String keyStorePassword = null;
         private String trustStore = null;
@@ -693,17 +659,6 @@
         }
 
         /**
-         * File location for a SSL Certificate Chain to use when SSL is enabled. If this value is not provided and
-         * SSL is enabled, the default {@link TrustManager} will be used.
-         * @deprecated As of release 3.2.10, replaced by {@link #trustStore}
-         */
-        @Deprecated
-        public Builder trustCertificateChainFile(final String certificateChainFile) {
-            this.trustCertChainFile = certificateChainFile;
-            return this;
-        }
-
-        /**
          * Length of time in milliseconds to wait on an idle connection before sending a keep-alive request. This
          * setting is only relevant to {@link Channelizer} implementations that return {@code true} for
          * {@link Channelizer#supportsKeepAlive()}.  Set to zero to disable this feature.
@@ -714,36 +669,6 @@
         }
 
         /**
-         * The X.509 certificate chain file in PEM format.
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStore}
-         */
-        @Deprecated
-        public Builder keyCertChainFile(final String keyCertChainFile) {
-            this.keyCertChainFile = keyCertChainFile;
-            return this;
-        }
-
-        /**
-         * The PKCS#8 private key file in PEM format.
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStore}
-         */
-        @Deprecated
-        public Builder keyFile(final String keyFile) {
-            this.keyFile = keyFile;
-            return this;
-        }
-
-        /**
-         * The password of the {@link #keyFile}, or {@code null} if it's not password-protected.
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStorePassword}
-         */
-        @Deprecated
-        public Builder keyPassword(final String keyPassword) {
-            this.keyPassword = keyPassword;
-            return this;
-        }
-
-        /**
          * The file location of the private key in JKS or PKCS#12 format.
          */
         public Builder keyStore(final String keyStore) {
@@ -901,29 +826,9 @@
         }
 
         /**
-         * If the connection is using a "session" this setting represents the amount of time in milliseconds to wait
-         * for that session to close before timing out where the default value is 3000. Note that the server will
-         * eventually clean up dead sessions itself on expiration of the session or during shutdown.
-         *
-         * @deprecated As of release 3.3.11, replaced in essence by {@link #maxWaitForClose(int)} though behavior
-         * described here is still maintained.
-         */
-        @Deprecated
-        public Builder maxWaitForSessionClose(final int maxWait) {
-            this.maxWaitForSessionClose = maxWait;
-            return this;
-        }
-
-        /**
          * The amount of time in milliseconds to wait the connection to close before timing out where the default
          * value is 3000. This timeout allows for a delay to occur in waiting for remaining messages that may still
          * be returning from the server while a {@link Client#close()} is called.
-         * <p/>
-         * This setting is related to {@link #maxWaitForSessionClose} to some degree. This setting refers to a wait
-         * for standard requests (i.e. queries) but the {@link #maxWaitForSessionClose} refers to a wait for the
-         * "session close" message that occurs after all standard requests have returned (or timed out). There is
-         * generally no need to set {@link #maxWaitForSessionClose} if the server is on 3.3.11 or later as the close
-         * of the connection will trigger the close of the session and the release of resources.
          */
         public Builder maxWaitForClose(final int maxWait) {
             this.maxWaitForClose = maxWait;
@@ -1053,7 +958,7 @@
 
         public Cluster create() {
             if (addresses.size() == 0) addContactPoint("localhost");
-            if (null == serializer) serializer = Serializers.GRYO_V3D0.simpleInstance();
+            if (null == serializer) serializer = Serializers.GRAPHBINARY_V1D0.simpleInstance();
             return new Cluster(this);
         }
     }
@@ -1115,16 +1020,11 @@
             connectionPoolSettings.maxSize = builder.maxConnectionPoolSize;
             connectionPoolSettings.minSize = builder.minConnectionPoolSize;
             connectionPoolSettings.maxWaitForConnection = builder.maxWaitForConnection;
-            connectionPoolSettings.maxWaitForSessionClose = builder.maxWaitForSessionClose;
             connectionPoolSettings.maxWaitForClose = builder.maxWaitForClose;
             connectionPoolSettings.maxContentLength = builder.maxContentLength;
             connectionPoolSettings.reconnectInterval = builder.reconnectInterval;
             connectionPoolSettings.resultIterationBatchSize = builder.resultIterationBatchSize;
             connectionPoolSettings.enableSsl = builder.enableSsl;
-            connectionPoolSettings.trustCertChainFile = builder.trustCertChainFile;
-            connectionPoolSettings.keyCertChainFile = builder.keyCertChainFile;
-            connectionPoolSettings.keyFile = builder.keyFile;
-            connectionPoolSettings.keyPassword = builder.keyPassword;
             connectionPoolSettings.keyStore = builder.keyStore;
             connectionPoolSettings.keyStorePassword = builder.keyStorePassword;
             connectionPoolSettings.trustStore = builder.trustStore;
@@ -1186,9 +1086,6 @@
             if (builder.maxWaitForConnection < 1)
                 throw new IllegalArgumentException("maxWaitForConnection must be greater than zero");
 
-            if (builder.maxWaitForSessionClose < 1)
-                throw new IllegalArgumentException("maxWaitForSessionClose must be greater than zero");
-
             if (builder.maxWaitForClose < 1)
                 throw new IllegalArgumentException("maxWaitForClose must be greater than zero");
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
index cc3a51d..a88a82c 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
@@ -63,7 +63,6 @@
     public static final int MAX_IN_PROCESS = 4;
     public static final int MIN_IN_PROCESS = 1;
     public static final int MAX_WAIT_FOR_CONNECTION = 16000;
-    public static final int MAX_WAIT_FOR_SESSION_CLOSE = 3000;
     public static final int MAX_WAIT_FOR_CLOSE = 3000;
     public static final int MAX_CONTENT_LENGTH = 65536;
 
@@ -332,40 +331,6 @@
         // messages at the server and leads to ugly log messages over there.
         if (shutdownInitiated.compareAndSet(false, true)) {
             final String connectionInfo = this.getConnectionInfo();
-            // this block of code that "closes" the session is deprecated as of 3.3.11 - this message is going to be
-            // removed at 3.5.0. we will instead bind session closing to the close of the channel itself and not have
-            // this secondary operation here which really only acts as a means for clearing resources in a functioning
-            // session. "functioning" in this context means that the session is not locked up with a long running
-            // operation which will delay this close execution which ideally should be more immediate, as in the user
-            // is annoyed that a long run operation is happening and they want an immediate cancellation. that's the
-            // most likely use case. we also get the nice benefit that this if/then code just goes away as the
-            // Connection really shouldn't care about the specific Client implementation.
-            if (client instanceof Client.SessionedClient && !isDead()) {
-                final boolean forceClose = client.getSettings().getSession().get().isForceClosed();
-                final RequestMessage closeMessage = client.buildMessage(
-                        RequestMessage.build(Tokens.OPS_CLOSE).addArg(Tokens.ARGS_FORCE, forceClose)).create();
-
-                final CompletableFuture<ResultSet> closed = new CompletableFuture<>();
-                write(closeMessage, closed);
-
-                try {
-                    // make sure we get a response here to validate that things closed as expected.  on error, we'll let
-                    // the server try to clean up on its own.  the primary error here should probably be related to
-                    // protocol issues which should not be something a user has to fuss with.
-                    closed.join().all().get(cluster.getMaxWaitForSessionClose(), TimeUnit.MILLISECONDS);
-                } catch (TimeoutException ex) {
-                    final String msg = String.format(
-                            "Timeout while trying to close connection on %s - force closing - server will close session on shutdown or expiration.",
-                            ((Client.SessionedClient) client).getSessionId());
-                    logger.warn(msg, ex);
-                } catch (Exception ex) {
-                    final String msg = String.format(
-                            "Encountered an error trying to close connection on %s - force closing - server will close session on shutdown or expiration.",
-                            ((Client.SessionedClient) client).getSessionId());
-                    logger.warn(msg, ex);
-                }
-            }
-
             channelizer.close(channel);
 
             final ChannelPromise promise = channel.newPromise();
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
index 74cf761..40231ec 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
@@ -223,29 +223,15 @@
                     final Object data = response.getResult().getData();
                     final Map<String,Object> meta = response.getResult().getMeta();
 
-                    if (!meta.containsKey(Tokens.ARGS_SIDE_EFFECT_KEY)) {
-                        // this is a "result" from the server which is either the result of a script or a
-                        // serialized traversal
-                        if (data instanceof List) {
-                            // unrolls the collection into individual results to be handled by the queue.
-                            final List<Object> listToUnroll = (List<Object>) data;
-                            listToUnroll.forEach(item -> queue.add(new Result(item)));
-                        } else {
-                            // since this is not a list it can just be added to the queue
-                            queue.add(new Result(response.getResult().getData()));
-                        }
+                    // this is a "result" from the server which is either the result of a script or a
+                    // serialized traversal
+                    if (data instanceof List) {
+                        // unrolls the collection into individual results to be handled by the queue.
+                        final List<Object> listToUnroll = (List<Object>) data;
+                        listToUnroll.forEach(item -> queue.add(new Result(item)));
                     } else {
-                        // this is the side-effect from the server which is generated from a serialized traversal
-                        final String aggregateTo = meta.getOrDefault(Tokens.ARGS_AGGREGATE_TO, Tokens.VAL_AGGREGATE_TO_NONE).toString();
-                        if (data instanceof List) {
-                            // unrolls the collection into individual results to be handled by the queue.
-                            final List<Object> listOfSideEffects = (List<Object>) data;
-                            listOfSideEffects.forEach(sideEffect -> queue.addSideEffect(aggregateTo, sideEffect));
-                        } else {
-                            // since this is not a list it can just be added to the queue. this likely shouldn't occur
-                            // however as the protocol will typically push everything to list first.
-                            queue.addSideEffect(aggregateTo, data);
-                        }
+                        // since this is not a list it can just be added to the queue
+                        queue.add(new Result(response.getResult().getData()));
                     }
                 } else {
                     // this is a "success" but represents no results otherwise it is an error
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/RequestOptions.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/RequestOptions.java
index 06bce18..70c0618 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/RequestOptions.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/RequestOptions.java
@@ -127,7 +127,7 @@
         }
 
         /**
-         * The per client request override in milliseconds for the server configured {@code scriptEvaluationTimeout}.
+         * The per client request override in milliseconds for the server configured {@code evaluationTimeout}.
          * If this value is not set, then the configuration for the server is used.
          */
         public Builder timeout(final long timeout) {
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
index 29a6453..8ce4fba 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
@@ -18,21 +18,15 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.javatuples.Pair;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
-import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -74,65 +68,6 @@
         tryDrainNextWaiting(false);
     }
 
-    /**
-     * Adds a side-effect to the queue which may later be read by the {@link ResultSet}. Note that the side-effect
-     * is only returned when a {@link Traversal} is submitted and refers to the side-effects defined in that traversal.
-     * A "script" will not return side-effects.
-     *
-     * @param aggregateTo the value of the {@link ResponseMessage} metadata for {@link Tokens#ARGS_AGGREGATE_TO}.
-     * @param sideEffectValue the value of the side-effect itself
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public void addSideEffect(final String aggregateTo, final Object sideEffectValue) {
-        switch (aggregateTo) {
-            case Tokens.VAL_AGGREGATE_TO_BULKSET:
-                if (!(sideEffectValue instanceof Traverser.Admin))
-                    throw new IllegalStateException(String.format("Side-effect value %s is a %s which does not aggregate to %s",
-                            sideEffectValue, sideEffectValue.getClass().getSimpleName(), aggregateTo));
-
-                if (null == aggregatedResult) aggregatedResult = new BulkSet();
-
-                final BulkSet<Object> bs = validate(aggregateTo, BulkSet.class);
-                final Traverser.Admin traverser = (Traverser.Admin) sideEffectValue;
-                bs.add(traverser.get(), traverser.bulk());
-                break;
-            case Tokens.VAL_AGGREGATE_TO_LIST:
-                if (null == aggregatedResult) aggregatedResult = new ArrayList();
-                final List<Object> list = validate(aggregateTo, List.class);
-                list.add(sideEffectValue);
-                break;
-            case Tokens.VAL_AGGREGATE_TO_SET:
-                if (null == aggregatedResult) aggregatedResult = new HashSet();
-                final Set<Object> set = validate(aggregateTo, Set.class);
-                set.add(sideEffectValue);
-                break;
-            case Tokens.VAL_AGGREGATE_TO_MAP:
-                if (!(sideEffectValue instanceof Map.Entry) && !(sideEffectValue instanceof Map))
-                    throw new IllegalStateException(String.format("Side-effect value %s is a %s which does not aggregate to %s",
-                            sideEffectValue, sideEffectValue.getClass().getSimpleName(), aggregateTo));
-
-                // some serialization formats (e.g. graphson) may deserialize a Map.Entry to a Map with a single entry
-                if (sideEffectValue instanceof Map && ((Map) sideEffectValue).size() != 1)
-                    throw new IllegalStateException(String.format("Side-effect value %s is a %s which does not aggregate to %s as it is a Map that does not have one entry",
-                            sideEffectValue, sideEffectValue.getClass().getSimpleName(), aggregateTo));
-
-                if (null == aggregatedResult) aggregatedResult =  new HashMap();
-
-                final Map<Object,Object > m = validate(aggregateTo, Map.class);
-                final Map.Entry entry = sideEffectValue instanceof Map.Entry ?
-                        (Map.Entry) sideEffectValue : (Map.Entry) ((Map) sideEffectValue).entrySet().iterator().next();
-                m.put(entry.getKey(), entry.getValue());
-                break;
-            case Tokens.VAL_AGGREGATE_TO_NONE:
-                if (null == aggregatedResult) aggregatedResult = sideEffectValue;
-                break;
-            default:
-                throw new IllegalStateException(String.format("%s is an invalid value for %s", aggregateTo, Tokens.ARGS_AGGREGATE_TO));
-        }
-    }
-
     private <V> V validate(final String aggregateTo, final Class<?> expected) {
         if (!(expected.isAssignableFrom(aggregatedResult.getClass())))
             throw new IllegalStateException(String.format("Side-effect \"%s\" contains the type %s that is not acceptable for %s",
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
index 5a9cd90..5f3424d 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.yaml.snakeyaml.TypeDescription;
 import org.yaml.snakeyaml.Yaml;
@@ -156,9 +156,7 @@
             final Configuration serializerConfigConf = conf.subset("serializer.config");
             if (IteratorUtils.count(serializerConfigConf.getKeys()) > 0) {
                 final Map<String,Object> m = new HashMap<>();
-                serializerConfigConf.getKeys().forEachRemaining(name -> {
-                    m.put(name, serializerConfigConf.getProperty(name));
-                });
+                serializerConfigConf.getKeys().forEachRemaining(name -> m.put(name, serializerConfigConf.getProperty(name)));
                 serializerSettings.config = m;
             }
             settings.serializer = serializerSettings;
@@ -174,18 +172,6 @@
             if (connectionPoolConf.containsKey("enableSsl"))
                 cpSettings.enableSsl = connectionPoolConf.getBoolean("enableSsl");
 
-            if (connectionPoolConf.containsKey("keyCertChainFile"))
-                cpSettings.keyCertChainFile = connectionPoolConf.getString("keyCertChainFile");
-
-            if (connectionPoolConf.containsKey("keyFile"))
-                cpSettings.keyFile = connectionPoolConf.getString("keyFile");
-
-            if (connectionPoolConf.containsKey("keyPassword"))
-                cpSettings.keyPassword = connectionPoolConf.getString("keyPassword");
-
-            if (connectionPoolConf.containsKey("trustCertChainFile"))
-                cpSettings.trustCertChainFile = connectionPoolConf.getString("trustCertChainFile");
-
             if (connectionPoolConf.containsKey("keyStore"))
                 cpSettings.keyStore = connectionPoolConf.getString("keyStore");
 
@@ -236,9 +222,6 @@
             if (connectionPoolConf.containsKey("maxWaitForConnection"))
                 cpSettings.maxWaitForConnection = connectionPoolConf.getInt("maxWaitForConnection");
 
-            if (connectionPoolConf.containsKey("maxWaitForSessionClose"))
-                cpSettings.maxWaitForSessionClose = connectionPoolConf.getInt("maxWaitForSessionClose");
-
             if (connectionPoolConf.containsKey("maxWaitForClose"))
                 cpSettings.maxWaitForClose = connectionPoolConf.getInt("maxWaitForClose");
 
@@ -270,34 +253,6 @@
         public boolean enableSsl = false;
 
         /**
-         * The trusted certificate in PEM format.
-         * @deprecated As of release 3.2.10, replaced by {@link #trustStore}
-         */
-        @Deprecated
-        public String trustCertChainFile = null;
-
-        /**
-         * The X.509 certificate chain file in PEM format.
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStore}
-         */
-        @Deprecated
-        public String keyCertChainFile = null;
-
-        /**
-         * The PKCS#8 private key file in PEM format.
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStore}
-         */
-        @Deprecated
-        public String keyFile = null;
-
-        /**
-         * The password of the {@link #keyFile}, or {@code null} if it's not password-protected.
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStorePassword}
-         */
-        @Deprecated
-        public String keyPassword = null;
-
-        /**
          * JSSE keystore file path. Similar to setting JSSE property
          * {@code javax.net.ssl.keyStore}.
          */
@@ -401,16 +356,6 @@
         public int maxWaitForConnection = Connection.MAX_WAIT_FOR_CONNECTION;
 
         /**
-         * If the connection is using a "session" this setting represents the amount of time in milliseconds to wait
-         * for that session to close before timing out where the default value is 3000. Note that the server will
-         * eventually clean up dead sessions itself on expiration of the session or during shutdown.
-         *
-         * @deprecated As of release 3.3.11, replaced in essence by {@link #maxWaitForClose}.
-         */
-        @Deprecated
-        public int maxWaitForSessionClose = Connection.MAX_WAIT_FOR_SESSION_CLOSE;
-
-        /**
          * The amount of time in milliseconds to wait the connection to close before timing out where the default
          * value is 3000. This timeout allows for a delay to occur in waiting for remaining messages that may still
          * be returning from the server while a {@link Client#close()} is called.
@@ -452,8 +397,9 @@
         /**
          * The fully qualified class name of the {@link MessageSerializer} that will be used to communicate with the
          * server. Note that the serializer configured on the client should be supported by the server configuration.
+         * By default the setting is configured to {@link GraphBinaryMessageSerializerV1}.
          */
-        public String className = GryoMessageSerializerV3d0.class.getCanonicalName();
+        public String className = GraphBinaryMessageSerializerV1.class.getCanonicalName();
 
         /**
          * The configuration for the specified serializer with the {@link #className}.
@@ -461,7 +407,7 @@
         public Map<String, Object> config = null;
 
         public MessageSerializer create() throws Exception {
-            final Class clazz = Class.forName(className);
+            final Class<?> clazz = Class.forName(className);
             final MessageSerializer serializer = (MessageSerializer) clazz.newInstance();
             Optional.ofNullable(config).ifPresent(c -> serializer.configure(c, null));
             return serializer;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
index d7a4215..867edf2 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
@@ -32,97 +32,22 @@
     public static final String OPS_INVALID = "invalid";
     public static final String OPS_CLOSE = "close";
 
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String OPS_GATHER = "gather";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String OPS_KEYS = "keys";
-
     public static final String REQUEST_ID = "requestId";
+
     public static final String ARGS_BATCH_SIZE = "batchSize";
     public static final String ARGS_BINDINGS = "bindings";
     public static final String ARGS_ALIASES = "aliases";
     public static final String ARGS_FORCE = "force";
     public static final String ARGS_GREMLIN = "gremlin";
     public static final String ARGS_LANGUAGE = "language";
-
-    /**
-     * @deprecated As of release 3.3.9, replaced by {@link #ARGS_EVAL_TIMEOUT}.
-     */
-    @Deprecated
-    public static final String ARGS_SCRIPT_EVAL_TIMEOUT = "scriptEvaluationTimeout";
     public static final String ARGS_EVAL_TIMEOUT = "evaluationTimeout";
     public static final String ARGS_HOST = "host";
     public static final String ARGS_SESSION = "session";
     public static final String ARGS_MANAGE_TRANSACTION = "manageTransaction";
     public static final String ARGS_SASL = "sasl";
     public static final String ARGS_SASL_MECHANISM = "saslMechanism";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String ARGS_SIDE_EFFECT = "sideEffect";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String ARGS_AGGREGATE_TO = "aggregateTo";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String ARGS_SIDE_EFFECT_KEY = "sideEffectKey";
     public static final String ARGS_USER_AGENT = "userAgent";
 
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String VAL_AGGREGATE_TO_BULKSET = "bulkset";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String VAL_AGGREGATE_TO_LIST = "list";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String VAL_AGGREGATE_TO_MAP = "map";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String VAL_AGGREGATE_TO_NONE = "none";
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String VAL_AGGREGATE_TO_SET = "set";
-
     public static final String VAL_TRAVERSAL_SOURCE_ALIAS = "g";
 
     public static final String STATUS_ATTRIBUTE_EXCEPTIONS = "exceptions";
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/NioGremlinRequestEncoder.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/NioGremlinRequestEncoder.java
deleted file mode 100644
index 1330a7e..0000000
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/NioGremlinRequestEncoder.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.driver.handler;
-
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.MessageToByteEncoder;
-import io.netty.util.CharsetUtil;
-import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
- */
-@Deprecated
-public final class NioGremlinRequestEncoder extends MessageToByteEncoder<Object> {
-    private boolean binaryEncoding = false;
-
-    private final MessageSerializer serializer;
-
-    public NioGremlinRequestEncoder(final boolean binaryEncoding, final MessageSerializer serializer) {
-        this.binaryEncoding = binaryEncoding;
-        this.serializer = serializer;
-    }
-
-    @Override
-    protected void encode(final ChannelHandlerContext channelHandlerContext, final Object msg, final ByteBuf byteBuf) throws Exception {
-        final RequestMessage requestMessage = (RequestMessage) msg;
-        try {
-            if (binaryEncoding) {
-                // wrap the serialized message/payload inside of a "frame".  this works around the problem where
-                // the length of the payload is not encoded into the general protocol.  that length isn't needed
-                // for websockets because under that protocol, the message is wrapped in a "websocket frame". this
-                // is not the optimal way to deal with this really, but it does prevent a protocol change in this
-                // immediate moment trying to get the NioChannelizer working.
-                final ByteBuf bytes = serializer.serializeRequestAsBinary(requestMessage, channelHandlerContext.alloc());
-                byteBuf.writeInt(bytes.capacity());
-                byteBuf.writeBytes(bytes);
-            } else {
-                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
-                final byte [] bytes = textSerializer.serializeRequestAsString(requestMessage).getBytes(CharsetUtil.UTF_8);
-                byteBuf.writeInt(bytes.length);
-                byteBuf.writeBytes(bytes);
-            }
-        } catch (Exception ex) {
-            throw new ResponseException(ResponseStatusCode.REQUEST_ERROR_SERIALIZATION, String.format(
-                    "An error occurred during serialization of this request [%s] - it could not be sent to the server - Reason: %s",
-                    requestMessage, ex));
-        }
-    }
-}
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/NioGremlinResponseDecoder.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/NioGremlinResponseDecoder.java
deleted file mode 100644
index 25e3a1c..0000000
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/NioGremlinResponseDecoder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.driver.handler;
-
-import io.netty.handler.codec.ReplayingDecoder;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient;
-
-import java.util.List;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
- */
-@Deprecated
-public final class NioGremlinResponseDecoder extends ReplayingDecoder<NioGremlinResponseDecoder.DecoderState> {
-    private final MessageSerializer serializer;
-    private int messageLength;
-
-    public NioGremlinResponseDecoder(final MessageSerializer serializer) {
-        super(DecoderState.MESSAGE_LENGTH);
-        this.serializer = serializer;
-    }
-
-    @Override
-    protected void decode(final ChannelHandlerContext channelHandlerContext, final ByteBuf byteBuf, final List<Object> objects) throws Exception {
-        switch (state()) {
-            case MESSAGE_LENGTH:
-                messageLength = byteBuf.readInt();
-                checkpoint(DecoderState.MESSAGE);
-            case MESSAGE:
-                final ByteBuf messageFrame = byteBuf.readBytes(messageLength);
-                objects.add(serializer.deserializeResponse(messageFrame));
-                checkpoint(DecoderState.MESSAGE_LENGTH);
-                break;
-            default:
-                throw new Error("Invalid message received from Gremlin Server");
-        }
-    }
-
-    public enum DecoderState {
-        MESSAGE_LENGTH,
-        MESSAGE
-    }
-}
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java
index c83493a..9daee96 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java
@@ -91,7 +91,7 @@
      * The request submitted for processing evaluated by the server with errors and could not be processed.
      * Check the script or remote traversal submitted for errors or other problems and then resubmit.
      */
-    SERVER_ERROR_SCRIPT_EVALUATION(597),
+    SERVER_ERROR_EVALUATION(597),
 
     /**
      * The server exceeded one of the timeout settings for the request and could therefore only partially responded
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java
index 114c596..9afa330 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver.remote;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.RequestOptions;
@@ -38,7 +38,6 @@
 import java.util.concurrent.CompletableFuture;
 
 import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_BATCH_SIZE;
-import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_SCRIPT_EVAL_TIMEOUT;
 import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_EVAL_TIMEOUT;
 import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_USER_AGENT;
 import static org.apache.tinkerpop.gremlin.driver.Tokens.REQUEST_ID;
@@ -236,8 +235,6 @@
             final Map<String,Object> options = optionsStrategy.getOptions();
             if (options.containsKey(ARGS_EVAL_TIMEOUT))
                 builder.timeout((long) options.get(ARGS_EVAL_TIMEOUT));
-            if (options.containsKey(ARGS_SCRIPT_EVAL_TIMEOUT))
-                builder.timeout((long) options.get(ARGS_SCRIPT_EVAL_TIMEOUT));
             if (options.containsKey(REQUEST_ID))
                 builder.overrideRequestId((UUID) options.get(REQUEST_ID));
             if (options.containsKey(ARGS_BATCH_SIZE))
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
index e47b07b..54e7cc8 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
@@ -18,17 +18,15 @@
  */
 package org.apache.tinkerpop.gremlin.driver.remote;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Result;
 import org.apache.tinkerpop.gremlin.driver.ResultSet;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.AbstractRemoteTraversal;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.step.map.RemoteStep;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -53,7 +51,6 @@
 
     private final Iterator<Traverser.Admin<E>> traversers;
     private Traverser.Admin<E> lastTraverser = EmptyTraverser.instance();
-    private final RemoteTraversalSideEffects sideEffects;
 
     public DriverRemoteTraversal(final ResultSet rs, final Client client, final boolean attach, final Optional<Configuration> conf) {
         // attaching is really just for testing purposes. it doesn't make sense in any real-world scenario as it would
@@ -66,23 +63,6 @@
         } else {
             this.traversers = new TraverserIterator<>(rs.iterator());
         }
-
-        this.sideEffects = new DriverRemoteTraversalSideEffects(client,rs);
-    }
-
-    /**
-     * Gets a side-effect from the server. Do not call this method prior to completing the iteration of the
-     * {@link DriverRemoteTraversal} that spawned this as the side-effect will not be ready. Generally
-     * speaking, the common user would not get side-effects this way - they would use a call to {@code cap()}.
-     *
-     * @deprecated as of release 3.3.8, not directly replaced, see {@link Admin#getSideEffects()} for more information,
-     * but further note that this method is not being removed, but will not be functional for remote execution. Prefer
-     * {@link GraphTraversal#cap(String, String...)} to get side-effects as part of traversal iteration.
-     */
-    @Override
-    @Deprecated
-    public RemoteTraversalSideEffects getSideEffects() {
-        return this.sideEffects;
     }
 
     @Override
@@ -117,17 +97,6 @@
         }
     }
 
-    /**
-     * Releases server-side resources related to this traversal (i.e. clearing the side-effect cache of data related to
-     * this traversal.
-     */
-    @Override
-    public void close() throws Exception {
-        sideEffects.close();
-
-        // leave the client open as it is owned by the DriverRemoteConnection not the traversal or side-effects
-    }
-
     static class TraverserIterator<E> implements Iterator<Traverser.Admin<E>> {
 
         private final Iterator<Result> inner;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
deleted file mode 100644
index baf54f3..0000000
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.driver.remote;
-
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.tinkerpop.gremlin.driver.Client;
-import org.apache.tinkerpop.gremlin.driver.Host;
-import org.apache.tinkerpop.gremlin.driver.Result;
-import org.apache.tinkerpop.gremlin.driver.ResultSet;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.AbstractRemoteTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Java driver implementation of {@link TraversalSideEffects}. This class is not thread safe.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.8, not directly replaced, prefer use of {@link GraphTraversal#cap(String, String...)}
- * to return the result as part of the traversal iteration.
- */
-@Deprecated
-public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSideEffects {
-
-    private final Client client;
-    private Set<String> keys = Collections.emptySet();
-    private final UUID serverSideEffect;
-    private final Host host;
-
-    private final Map<String, Object> sideEffects = new HashMap<>();
-
-    private boolean closed = false;
-    private boolean retrievedAllKeys = false;
-    private final CompletableFuture<Void> ready;
-    private final CompletableFuture<Map<String,Object>> statusAttributes;
-
-    /**
-     * @deprecated As of release 3.4.0, replaced by {@link #DriverRemoteTraversalSideEffects(Client, ResultSet)}
-     */
-    @Deprecated
-    public DriverRemoteTraversalSideEffects(final Client client, final UUID serverSideEffect, final Host host,
-                                            final CompletableFuture<Void> ready) {
-        this.client = client;
-        this.serverSideEffect = serverSideEffect;
-        this.host = host;
-        this.ready = ready;
-        this.statusAttributes = CompletableFuture.completedFuture(Collections.emptyMap());
-    }
-
-    public DriverRemoteTraversalSideEffects(final Client client, final ResultSet rs) {
-        this.client = client;
-        this.serverSideEffect = rs.getOriginalRequestMessage().getRequestId();
-        this.host = rs.getHost();
-        this.ready = rs.allItemsAvailableAsync();
-        this.statusAttributes = rs.statusAttributes();
-    }
-
-    /**
-     * Gets the status attributes from the response from the server. This method will block until all results have
-     * been retrieved.
-     */
-    public Map<String,Object> statusAttributes() {
-        // wait for the read to complete (i.e. iteration on the server) before allowing the caller to get the
-        // attribute. simply following the pattern from other methods here for now.
-        return statusAttributes.join();
-    }
-
-    @Override
-    public <V> V get(final String key) throws IllegalArgumentException {
-        // wait for the read to complete (i.e. iteration on the server) before allowing the caller to get the
-        // side-effect. calling prior to this will result in the side-effect not being found. of course, the
-        // bad part here is that the method blocks indefinitely waiting for the result, but it prevents the
-        // test failure problems that happen on slower systems. in practice, it's unlikely that a user would
-        // try to get a side-effect prior to iteration, but since the API allows it, this at least prevents
-        // the error.
-        ready.join();
-
-        if (!keys().contains(key)) throw TraversalSideEffects.Exceptions.sideEffectKeyDoesNotExist(key);
-
-        if (!sideEffects.containsKey(key)) {
-
-            if (closed) throw new IllegalStateException("Traversal has been closed - no new side-effects can be retrieved");
-
-            // specify the ARGS_HOST so that the LoadBalancingStrategy is subverted and the connection is forced
-            // from the specified host (i.e. the host from the previous request as that host will hold the side-effects)
-            final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)
-                    .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect)
-                    .addArg(Tokens.ARGS_SIDE_EFFECT_KEY, key)
-                    .addArg(Tokens.ARGS_HOST, host)
-                    .processor("traversal").create();
-            try {
-                final Result result = client.submitAsync(msg).get().all().get().get(0);
-                sideEffects.put(key, null == result ? null : result.getObject());
-            } catch (Exception ex) {
-                // we use to try to catch "no found" situations returned from the server here and then null the
-                // side-effect for the requested key. doesn't seem like there is a need for that now because calls
-                // to get() now initially trigger a call the keys() so you would know all of the keys available on
-                // the server and would validate them up front throwing sideEffectKeyDoesNotExist(key) which thus
-                // produces behavior similar to the non-remote side-effect implementations. if we get an exception
-                // here at this point then we likely have a legit error in communicating to the remote server.
-                throw new RuntimeException("Could not get side-effect for " + serverSideEffect + " with key of " + key, ex);
-            }
-        }
-
-        return (V) sideEffects.get(key);
-    }
-
-    @Override
-    public Set<String> keys() {
-        // wait for the read to complete (i.e. iteration on the server) before allowing the caller to get the
-        // side-effect. calling prior to this will result in the side-effect not being found. of course, the
-        // bad part here is that the method blocks indefinitely waiting for the result, but it prevents the
-        // test failure problems that happen on slower systems. in practice, it's unlikely that a user would
-        // try to get a side-effect prior to iteration, but since the API allows it, this at least prevents
-        // the error.
-        ready.join();
-
-        if (closed && !retrievedAllKeys) throw new IllegalStateException("Traversal has been closed - side-effect keys cannot be retrieved");
-
-        if (!retrievedAllKeys) {
-            // specify the ARGS_HOST so that the LoadBalancingStrategy is subverted and the connection is forced
-            // from the specified host (i.e. the host from the previous request as that host will hold the side-effects)
-            final RequestMessage msg = RequestMessage.build(Tokens.OPS_KEYS)
-                    .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect)
-                    .addArg(Tokens.ARGS_HOST, host)
-                    .processor("traversal").create();
-            try {
-                if (keys.equals(Collections.emptySet()))
-                    keys = new HashSet<>();
-
-                client.submitAsync(msg).get().all().get().forEach(r -> keys.add(r.getString()));
-
-                // only need to retrieve all keys once
-                retrievedAllKeys = true;
-            } catch (Exception ex) {
-                final Throwable root = ExceptionUtils.getRootCause(ex);
-                throw new RuntimeException("Could not get keys", null == root ? ex : root);
-            }
-        }
-
-        return keys;
-    }
-
-    @Override
-    public void close() throws Exception {
-        if (!closed) {
-            final RequestMessage msg = RequestMessage.build(Tokens.OPS_CLOSE)
-                    .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect)
-                    .addArg(Tokens.ARGS_HOST, host)
-                    .processor("traversal").create();
-            try {
-                client.submitAsync(msg).get();
-                closed = true;
-            } catch (Exception ex) {
-                final Throwable root = ExceptionUtils.getRootCause(ex);
-                throw new RuntimeException("Error on closing side effects", null == root ? ex : root);
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        // have to override the implementation from TraversalSideEffects because it relies on calls to keys() as
-        // calling that too early can cause unintended failures (i.e. in the debugger, toString() gets called when
-        // introspecting the object from the moment of construction).
-        return "sideEffects[size:" + keys.size() + "]";
-    }
-}
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java
index bf4e76f..44125e1 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java
@@ -84,13 +84,12 @@
 
         if (builderClassName != null) {
             try {
-                Class<?> clazz = Class.forName(builderClassName);
-                Constructor<?> ctor = clazz.getConstructor();
+                final Class<?> clazz = Class.forName(builderClassName);
+                final Constructor<?> ctor = clazz.getConstructor();
                 builder = (TypeSerializerRegistry.Builder) ctor.newInstance();
             } catch (Exception ex) {
                 throw new IllegalStateException(ex);
             }
-
         } else {
             builder = TypeSerializerRegistry.build();
         }
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
index 47af647..c1cf305 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
@@ -27,6 +27,7 @@
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public enum Serializers {
+
     /**
      * GraphSON 3.0.
      */
@@ -56,24 +57,6 @@
 
     private String value;
 
-    /**
-     * Default serializer for results returned from Gremlin Server. This implementation must be of type
-     * {@link MessageTextSerializer} so that it can be compatible with text-based websocket messages.
-     *
-     * @deprecated As of release 3.3.5, not replaced, simply specify the exact version of the serializer to use.
-     */
-    @Deprecated
-    public static final MessageSerializer DEFAULT_RESULT_SERIALIZER = new GraphSONMessageSerializerV1d0();
-
-    /**
-     * Default serializer for requests received by Gremlin Server. This implementation must be of type
-     * {@link MessageTextSerializer} so that it can be compatible with text-based websocket messages.
-     *
-     * @deprecated As of release 3.3.5, not replaced, simply specify the exact version of the serializer to use.
-     */
-    @Deprecated
-    public static final MessageSerializer DEFAULT_REQUEST_SERIALIZER = new GraphSONMessageSerializerV1d0();
-
     Serializers(final String mimeType) {
         this.value = mimeType;
     }
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/NioClient.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/NioClient.java
deleted file mode 100644
index 3904b20..0000000
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/NioClient.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.driver.simple;
-
-import io.netty.buffer.PooledByteBufAllocator;
-import io.netty.channel.ChannelOption;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder;
-import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import io.netty.bootstrap.Bootstrap;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelInitializer;
-import io.netty.channel.ChannelPipeline;
-import io.netty.channel.socket.SocketChannel;
-import io.netty.channel.socket.nio.NioSocketChannel;
-import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0;
-
-import java.io.IOException;
-import java.net.URI;
-
-/**
- * A simple, non-thread safe Gremlin Server client using NIO.  Typical use is for testing and demonstration.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
- */
-@Deprecated
-public class NioClient extends AbstractClient {
-    private final Channel channel;
-
-    public NioClient() {
-        this(URI.create("gs://localhost:8182"));
-    }
-
-    public NioClient(final URI uri) {
-        super("nio-client-%d");
-        final Bootstrap b = new Bootstrap().group(group);
-        b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
-
-        try {
-            final MessageSerializer serializer = new GryoMessageSerializerV3d0();
-            b.channel(NioSocketChannel.class)
-                    .handler(new ChannelInitializer<SocketChannel>() {
-                        @Override
-                        protected void initChannel(final SocketChannel ch) {
-                            final ChannelPipeline p = ch.pipeline();
-                            p.addLast(
-                                    new NioGremlinResponseDecoder(serializer),
-                                    new NioGremlinRequestEncoder(true, serializer),
-                                    callbackResponseHandler);
-                        }
-                    });
-
-            channel = b.connect(uri.getHost(), uri.getPort()).sync().channel();
-        } catch (Exception ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @Override
-    public void writeAndFlush(final RequestMessage requestMessage) throws Exception {
-        channel.writeAndFlush(requestMessage).get();
-    }
-
-    @Override
-    public void close() throws IOException {
-        try {
-            channel.close().get();
-        } catch (Exception ignored) {
-
-        } finally {
-            group.shutdownGracefully().awaitUninterruptibly();
-        }
-    }
-}
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/WebSocketClient.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/WebSocketClient.java
index 3950339..b1a47a6 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/WebSocketClient.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/WebSocketClient.java
@@ -21,7 +21,6 @@
 import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.channel.ChannelOption;
 import io.netty.handler.codec.http.EmptyHttpHeaders;
-import io.netty.handler.codec.http.HttpHeaders;
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketClientHandler;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketGremlinRequestEncoder;
@@ -37,7 +36,7 @@
 import io.netty.handler.codec.http.HttpObjectAggregator;
 import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
 import io.netty.handler.codec.http.websocketx.WebSocketVersion;
-import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
 
 import java.io.IOException;
 import java.net.URI;
@@ -69,7 +68,7 @@
                     new WebSocketClientHandler(
                             WebSocketClientHandshakerFactory.newHandshaker(
                                     uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 65536));
-            final MessageSerializer serializer = new GryoMessageSerializerV3d0();
+            final MessageSerializer serializer = new GraphBinaryMessageSerializerV1();
             b.channel(NioSocketChannel.class)
                     .handler(new ChannelInitializer<SocketChannel>() {
                         @Override
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/util/ProfilingApplication.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/util/ProfilingApplication.java
index b3d20d7..3766460 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/util/ProfilingApplication.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/util/ProfilingApplication.java
@@ -158,7 +158,7 @@
         final int workerPoolSize = Integer.parseInt(options.getOrDefault("workerPoolSize", "2").toString());
         final int tooSlowThreshold = Integer.parseInt(options.getOrDefault("tooSlowThreshold", "125").toString());
         final String channelizer = options.getOrDefault("channelizer", Channelizer.WebSocketChannelizer.class.getName()).toString();
-        final String serializer = options.getOrDefault("serializer", Serializers.GRYO_V1D0.name()).toString();
+        final String serializer = options.getOrDefault("serializer", Serializers.GRAPHBINARY_V1D0.name()).toString();
 
         final boolean exercise = Boolean.parseBoolean(options.getOrDefault("exercise", "false").toString());
         final String script = options.getOrDefault("script", "1+1").toString();
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java
index 0bf317d..e494397 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java
@@ -52,8 +52,8 @@
                 {"minConnectionPoolSizeLteMax", Cluster.build().minConnectionPoolSize(100).maxConnectionPoolSize(99), "maxConnectionPoolSize cannot be less than minConnectionPoolSize"},
                 {"minConnectionPoolSizeLteMax", Cluster.build().minConnectionPoolSize(100).maxConnectionPoolSize(99), "maxConnectionPoolSize cannot be less than minConnectionPoolSize"},
                 {"maxConnectionPoolSize0", Cluster.build().maxWaitForConnection(0), "maxWaitForConnection must be greater than zero"},
-                {"maxWaitForSessionClose0", Cluster.build().maxWaitForSessionClose(0), "maxWaitForSessionClose must be greater than zero"},
-                {"maxWaitForSessionCloseNeg1", Cluster.build().maxWaitForSessionClose(-1), "maxWaitForSessionClose must be greater than zero"},
+                {"maxWaitForClose0", Cluster.build().maxWaitForClose(0), "maxWaitForClose must be greater than zero"},
+                {"maxWaitForCloseNeg1", Cluster.build().maxWaitForClose(-1), "maxWaitForClose must be greater than zero"},
                 {"maxContentLength0", Cluster.build().maxContentLength(0), "maxContentLength must be greater than zero"},
                 {"maxContentLengthNeg1", Cluster.build().maxContentLength(-1), "maxContentLength must be greater than zero"},
                 {"reconnectInterval0", Cluster.build().reconnectInterval(0), "reconnectInterval must be greater than zero"},
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/MockitoHamcrestMatcherAdapter.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/MockitoHamcrestMatcherAdapter.java
new file mode 100644
index 0000000..252d9a9
--- /dev/null
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/MockitoHamcrestMatcherAdapter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.driver;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
+
+/**
+ * Adapts a Mockito {@code ArgumentMatcher} to a Hamcrest {@code Matcher} so that it can be used with the Hamcrest
+ * {@code assertThat}.
+ */
+public class MockitoHamcrestMatcherAdapter extends BaseMatcher {
+
+    private final ArgumentMatcher<Object> mockitoMatcher;
+
+    public MockitoHamcrestMatcherAdapter(final ArgumentMatcher<Object> mockitoMatcher) {
+        this.mockitoMatcher = mockitoMatcher;
+    }
+
+    public static MockitoHamcrestMatcherAdapter reflectionEquals(final Object wanted, final String... excludeFields) {
+        return new MockitoHamcrestMatcherAdapter(new ReflectionEquals(wanted, excludeFields));
+    }
+
+    @Override
+    public boolean matches(final Object o) {
+        return mockitoMatcher.matches(o);
+    }
+
+    @Override
+    public void describeTo(final Description description) {
+        description.appendValue(mockitoMatcher.toString());
+    }
+}
\ No newline at end of file
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
index 75afb74..4ca4664 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
@@ -19,16 +19,12 @@
 package org.apache.tinkerpop.gremlin.driver;
 
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -153,7 +149,7 @@
     }
 
     @Test
-    public void shouldAwaitFailTheFutureOnMarkError() throws Exception {
+    public void shouldAwaitFailTheFutureOnMarkError() {
         final CompletableFuture<List<Result>> future = resultQueue.await(4);
         resultQueue.add(new Result("test1"));
         resultQueue.add(new Result("test2"));
@@ -298,128 +294,4 @@
             t.interrupt();
         }
     }
-
-    @Test
-    public void shouldHandleBulkSetSideEffects() throws Exception  {
-        final CompletableFuture<List<Result>> o = resultQueue.await(1);
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_BULKSET, new DefaultRemoteTraverser<>("brian", 2));
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_BULKSET, new DefaultRemoteTraverser<>("brian", 2));
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_BULKSET, new DefaultRemoteTraverser<>("belinda", 6));
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.markComplete(ATTRIBUTES);
-
-        assertThat(o.isDone(), is(true));
-        final BulkSet<String> bulkSet = o.get().get(0).get(BulkSet.class);
-        assertEquals(4, bulkSet.get("brian"));
-        assertEquals(6, bulkSet.get("belinda"));
-
-        assertEquals("that", resultQueue.getStatusAttributes().get("this"));
-    }
-
-    @Test
-    public void shouldHandleListSideEffects() throws Exception {
-        final CompletableFuture<List<Result>> o = resultQueue.await(1);
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_LIST, "stephen");
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_LIST, "daniel");
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_LIST, "dave");
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.markComplete(ATTRIBUTES);
-
-        assertThat(o.isDone(), is(true));
-        final List<String> list = o.get().get(0).get(ArrayList.class);
-        assertEquals("stephen", list.get(0));
-        assertEquals("daniel", list.get(1));
-        assertEquals("dave", list.get(2));
-
-        assertEquals("that", resultQueue.getStatusAttributes().get("this"));
-    }
-
-    @Test
-    public void shouldHandleSetSideEffects() throws Exception {
-        final CompletableFuture<List<Result>> o = resultQueue.await(1);
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_SET, "stephen");
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_SET, "daniel");
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_SET, "dave");
-        assertThat(o.isDone(), is(false));
-
-        resultQueue.markComplete(ATTRIBUTES);
-
-        assertThat(o.isDone(), is(true));
-        final Set<String> set = o.get().get(0).get(HashSet.class);
-        assertThat(set.contains("stephen"), is(true));
-        assertThat(set.contains("daniel"), is(true));
-        assertThat(set.contains("dave"), is(true));
-
-        assertEquals("that", resultQueue.getStatusAttributes().get("this"));
-    }
-
-    @Test
-    public void shouldHandleMapSideEffects() throws Exception {
-        final CompletableFuture<List<Result>> o = resultQueue.await(1);
-        assertThat(o.isDone(), is(false));
-
-        final Map<String,String> m = new HashMap<>();
-        m.put("s", "stephen");
-        m.put("m", "marko");
-        m.put("d", "daniel");
-
-        m.entrySet().forEach(e -> {
-            resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_MAP, e);
-            assertThat(o.isDone(), is(false));
-        });
-
-        resultQueue.markComplete(ATTRIBUTES);
-
-        assertThat(o.isDone(), is(true));
-        final Map<String, String> list = o.get().get(0).get(HashMap.class);
-        assertEquals("stephen", list.get("s"));
-        assertEquals("daniel", list.get("d"));
-        assertEquals("marko", list.get("m"));
-
-        assertEquals("that", resultQueue.getStatusAttributes().get("this"));
-    }
-
-
-    @Test
-    public void shouldHandleNotAggregateSideEffects() throws Exception  {
-        final CompletableFuture<List<Result>> o = resultQueue.await(1);
-        assertThat(o.isDone(), is(false));
-
-        final Map<String,String> m = new HashMap<>();
-        m.put("s", "stephen");
-        m.put("m", "marko");
-        m.put("d", "daniel");
-
-        resultQueue.addSideEffect(Tokens.VAL_AGGREGATE_TO_NONE, m);
-
-        resultQueue.markComplete(ATTRIBUTES);
-
-        assertThat(o.isDone(), is(true));
-        final Map<String, String> list = o.get().get(0).get(HashMap.class);
-        assertEquals("stephen", list.get("s"));
-        assertEquals("daniel", list.get("d"));
-        assertEquals("marko", list.get("m"));
-
-        assertEquals("that", resultQueue.getStatusAttributes().get("this"));
-    }
 }
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SettingsTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SettingsTest.java
index adf2d1b..ddfbe16 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SettingsTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SettingsTest.java
@@ -22,8 +22,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -47,10 +47,6 @@
         conf.setProperty("serializer.className", "my.serializers.MySerializer");
         conf.setProperty("serializer.config.any", "thing");
         conf.setProperty("connectionPool.enableSsl", true);
-        conf.setProperty("connectionPool.keyCertChainFile", "X.509");
-        conf.setProperty("connectionPool.keyFile", "PKCS#8");
-        conf.setProperty("connectionPool.keyPassword", "password1");
-        conf.setProperty("connectionPool.trustCertChainFile", "pem");
         conf.setProperty("connectionPool.keyStore", "server.jks");
         conf.setProperty("connectionPool.keyStorePassword", "password2");
         conf.setProperty("connectionPool.keyStoreType", "pkcs12");
@@ -86,10 +82,6 @@
         assertEquals("my.serializers.MySerializer", settings.serializer.className);
         assertEquals("thing", settings.serializer.config.get("any"));
         assertThat(settings.connectionPool.enableSsl, is(true));
-        assertEquals("X.509", settings.connectionPool.keyCertChainFile);
-        assertEquals("PKCS#8", settings.connectionPool.keyFile);
-        assertEquals("password1", settings.connectionPool.keyPassword);
-        assertEquals("pem", settings.connectionPool.trustCertChainFile);
         assertEquals("server.jks", settings.connectionPool.keyStore);
         assertEquals("password2", settings.connectionPool.keyStorePassword);
         assertEquals("pkcs12", settings.connectionPool.keyStoreType);
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
index 820a0d3..a161ddf 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
@@ -42,7 +42,7 @@
                         with("y", 100).
                         with(Tokens.ARGS_BATCH_SIZE, 1000).
                         with(Tokens.REQUEST_ID, requestId).
-                        with(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT, 100000L).
+                        with(Tokens.ARGS_EVAL_TIMEOUT, 100000L).
                         with(Tokens.ARGS_USER_AGENT, "test").
                         V().asAdmin().getBytecode());
         assertEquals(requestId, options.getOverrideRequestId().get());
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
deleted file mode 100644
index 4e6df93..0000000
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.driver.remote;
-
-import org.apache.tinkerpop.gremlin.driver.AbstractResultQueueTest;
-import org.apache.tinkerpop.gremlin.driver.Client;
-import org.apache.tinkerpop.gremlin.driver.ResultSet;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
-import org.junit.Test;
-import org.mockito.stubbing.Answer;
-
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class DriverRemoteTraversalSideEffectsTest extends AbstractResultQueueTest {
-
-    @Test
-    public void shouldNotContactRemoteForKeysAfterCloseIsCalled() throws Exception {
-        final Client client = mock(Client.class);
-        mockClientForCall(client);
-        mockClientForCall(client);
-
-        final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
-        final CompletableFuture<Void> ready = new CompletableFuture<>();
-        ready.complete(null);
-        final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null, ready);
-
-        assertEquals(1, sideEffects.keys().size());
-        sideEffects.close();
-
-        // call this again and again and it will only hit the cached keys - no more server calls
-        assertEquals(1, sideEffects.keys().size());
-        assertEquals(1, sideEffects.keys().size());
-        assertEquals(1, sideEffects.keys().size());
-        assertEquals(1, sideEffects.keys().size());
-
-        // once for the keys and once for the close message
-        verify(client, times(2)).submitAsync(any(RequestMessage.class));
-    }
-
-    @Test
-    public void shoudlNotContactRemoteForGetAfterCloseIsCalled() throws Exception {
-        final Client client = mock(Client.class);
-        mockClientForCall(client);
-        mockClientForCall(client);
-        final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
-        final CompletableFuture<Void> ready = new CompletableFuture<>();
-        ready.complete(null);
-        final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null, ready);
-
-        assertNotNull(sideEffects.get("test-0"));
-        sideEffects.close();
-
-        // Side effect 'a' should be cached locally
-        assertNotNull(sideEffects.get("test-0"));
-        assertNotNull(sideEffects.get("test-0"));
-        assertNotNull(sideEffects.get("test-0"));
-
-        // Once for keys, once for get and once for close
-        verify(client, times(3)).submitAsync(any(RequestMessage.class));
-    }
-
-    @Test
-    public void shouldNotContactRemoteMoreThanOnceForClose() throws Exception {
-        final Client client = mock(Client.class);
-        mockClientForCall(client);
-
-        final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
-        final CompletableFuture<Void> ready = new CompletableFuture<>();
-        ready.complete(null);
-        final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null, ready);
-
-        sideEffects.close();
-        sideEffects.close();
-        sideEffects.close();
-        sideEffects.close();
-        sideEffects.close();
-
-        try {
-            sideEffects.keys();
-            fail("The traversal is closed");
-        } catch (Exception ex) {
-            assertThat(ex, instanceOf(IllegalStateException.class));
-            assertEquals("Traversal has been closed - side-effect keys cannot be retrieved", ex.getMessage());
-        }
-
-        try {
-            sideEffects.get("a");
-            fail("The traversal is closed");
-        } catch (Exception ex) {
-            assertThat(ex, instanceOf(IllegalStateException.class));
-            assertEquals("Traversal has been closed - side-effect keys cannot be retrieved", ex.getMessage());
-        }
-
-        // once for the close message
-        verify(client, times(1)).submitAsync(any(RequestMessage.class));
-    }
-
-    private void mockClientForCall(final Client client) throws Exception {
-        // the return is just generic garbage from addToQueue for any call to submitAsync().
-        when(client.submitAsync(any(RequestMessage.class))).thenAnswer((Answer<Object>) invocationOnMock -> {
-            final ResultSet returnedResultSet = new ResultSet(resultQueue, pool, readCompleted, RequestMessage.build("traversal").create(), null);
-            addToQueue(1, 0, true, true, 1);
-            final CompletableFuture<ResultSet> returnedFuture = new CompletableFuture<>();
-            returnedFuture.complete(returnedResultSet);
-            return returnedFuture;
-        });
-    }
-}
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java
index d0042ff..2772cb1 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java
@@ -27,7 +27,6 @@
 import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 import org.junit.Test;
-import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -35,6 +34,7 @@
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import static org.apache.tinkerpop.gremlin.driver.MockitoHamcrestMatcherAdapter.reflectionEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
@@ -54,7 +54,7 @@
         final int mimeLen = buffer.readByte();
         buffer.readBytes(new byte[mimeLen]);
         final RequestMessage deserialized = serializer.deserializeRequest(buffer);
-        assertThat(request, new ReflectionEquals(deserialized));
+        assertThat(request, reflectionEquals(deserialized));
     }
 
     @Test
@@ -68,7 +68,7 @@
         final int mimeLen = buffer.readByte();
         buffer.readBytes(new byte[mimeLen]);
         final RequestMessage deserialized = serializer.deserializeRequest(buffer);
-        assertThat(request, new ReflectionEquals(deserialized));
+        assertThat(request, reflectionEquals(deserialized));
     }
 
     @Test
@@ -82,7 +82,7 @@
         final int mimeLen = buffer.readByte();
         buffer.readBytes(new byte[mimeLen]);
         final RequestMessage deserialized = serializer.deserializeRequest(buffer);
-        assertThat(request, new ReflectionEquals(deserialized));
+        assertThat(request, reflectionEquals(deserialized));
     }
 
     @Test
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java
index ea7254d..f248bc9 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java
@@ -61,7 +61,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
-import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -86,6 +85,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
+import static org.apache.tinkerpop.gremlin.driver.MockitoHamcrestMatcherAdapter.reflectionEquals;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
@@ -265,19 +265,19 @@
                 new Object[] {"BulkSet", bulkSet, null},
                 new Object[] {"Tree", tree, null},
                 new Object[] {"EmptyMetrics", new MutableMetrics("idEmpty", "nameEmpty"), (Consumer<Metrics>) m -> {
-                    assertThat(m, new ReflectionEquals(new MutableMetrics("idEmpty", "nameEmpty")));
+                    assertThat(m, reflectionEquals(new MutableMetrics("idEmpty", "nameEmpty")));
                 }},
                 new Object[] {"Metrics", metrics, (Consumer<Metrics>) m -> {
-                    assertThat(m, new ReflectionEquals(metrics, "nested", "counts"));
+                    assertThat(m, reflectionEquals(metrics, "nested", "counts"));
                     assertEquals(new ArrayList(metrics.getCounts().values()), new ArrayList(m.getCounts().values()));
-                    assertThat(m.getNested(), new ReflectionEquals(metrics.getNested()));
+                    assertThat(m.getNested(), reflectionEquals(metrics.getNested()));
                 }},
                 new Object[] {"EmptyTraversalMetrics", emptyTraversalMetrics, (Consumer<TraversalMetrics>) m -> {
-                    assertThat(m, new ReflectionEquals(emptyTraversalMetrics));
+                    assertThat(m, reflectionEquals(emptyTraversalMetrics));
                 }},
                 new Object[] {"TraversalMetrics", traversalMetrics, (Consumer<TraversalMetrics>) m -> {
                     assertEquals(m.toString(), traversalMetrics.toString());
-                    assertThat(m, new ReflectionEquals(traversalMetrics, "stepIndexedMetrics", "positionIndexedMetrics"));
+                    assertThat(m, reflectionEquals(traversalMetrics, "stepIndexedMetrics", "positionIndexedMetrics"));
                 }},
 
                 // collections
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java
index 3d6bef3..5ca3c46 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java
@@ -30,7 +30,6 @@
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
 import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 import org.junit.Test;
-import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
 
 import java.io.IOException;
 import java.time.LocalDateTime;
@@ -41,6 +40,7 @@
 import java.util.Map;
 import java.util.UUID;
 
+import static org.apache.tinkerpop.gremlin.driver.MockitoHamcrestMatcherAdapter.reflectionEquals;
 import static org.apache.tinkerpop.gremlin.driver.ser.AbstractMessageSerializer.TOKEN_IO_REGISTRIES;
 import static org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1.TOKEN_CUSTOM;
 import static org.junit.Assert.assertThat;
@@ -93,7 +93,7 @@
             writer.writeValue(person, buffer, nullable);
             final SamplePerson actual = reader.readValue(buffer, SamplePerson.class, nullable);
 
-            assertThat(actual, new ReflectionEquals(person));
+            assertThat(actual, reflectionEquals(person));
             buffer.release();
         }
     }
@@ -108,7 +108,7 @@
         final ResponseMessage deserialized = serializer.deserializeResponse(serialized);
 
         final SamplePerson actual = (SamplePerson) deserialized.getResult().getData();
-        assertThat(actual, new ReflectionEquals(person));
+        assertThat(actual, reflectionEquals(person));
     }
 
     public static class CustomIoRegistry extends AbstractIoRegistry {
diff --git a/gremlin-groovy/pom.xml b/gremlin-groovy/pom.xml
index 9f98ecf..9384b24 100644
--- a/gremlin-groovy/pom.xml
+++ b/gremlin-groovy/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-groovy</artifactId>
     <name>Apache TinkerPop :: Gremlin Groovy</name>
@@ -34,7 +34,7 @@
         <dependency>
             <groupId>org.apache.ivy</groupId>
             <artifactId>ivy</artifactId>
-            <version>2.3.0</version>
+            <version>2.4.0</version>
         </dependency>
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
@@ -57,6 +57,20 @@
         </dependency>
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-cli-picocli</artifactId>
+            <version>${groovy.version}</version>
+            <classifier>indy</classifier>
+        </dependency>
+        <!--
+        not sure why jline won't come in with groovy-groovysh but it messes up build of gremlin-console
+        -->
+        <dependency>
+            <groupId>jline</groupId>
+            <artifactId>jline</artifactId>
+            <version>2.14.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
             <artifactId>groovy-json</artifactId>
             <version>${groovy.version}</version>
             <classifier>indy</classifier>
@@ -159,4 +173,29 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <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.
+                            -->
+                            <sourcepath>${pom.basedir}/src/main/java:${project.build.directory}/generated-sources/annotations:${project.build.directory}/generated-sources/groovy-stubs/main</sourcepath>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/InterpreterModeASTTransformation.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/InterpreterModeASTTransformation.groovy
index e7a3c62..f6e1b88 100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/InterpreterModeASTTransformation.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/InterpreterModeASTTransformation.groovy
@@ -61,7 +61,7 @@
         ClassNode scriptNode = (ClassNode) astNodes[1]
 
         // need to check that object is a Script to call run(). this scriptNode may be a user defined class via
-        // "def class" in which case it can be ignored as there are no variables to promote to global status there
+        // "class" in which case it can be ignored as there are no variables to promote to global status there
         if (scriptNode.isDerivedFrom(ClassHelper.make(Script))) {
             def runMethodOfScript = scriptNode.declaredMethodsMap["java.lang.Object run()"]
             runMethodOfScript.code = wrap(runMethodOfScript)
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
index d8c71e6..3edabee 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
@@ -505,21 +505,6 @@
         }
 
         /**
-         * Amount of time a script has before it times out. Note that the time required covers both script evaluation
-         * as well as any time needed for a post result transformation (if the transformation function is supplied
-         * to the {@link GremlinExecutor#eval}).
-         *
-         * @param scriptEvaluationTimeout Time in milliseconds that an evaluation is allowed to run and its
-         *                                results potentially transformed. Set to zero to have no timeout set.
-         * @deprecated As of release 3.3.9, replaced by {@link #evaluationTimeout}.
-         */
-        @Deprecated
-        public Builder scriptEvaluationTimeout(final long scriptEvaluationTimeout) {
-            this.evaluationTimeout = scriptEvaluationTimeout;
-            return this;
-        }
-
-        /**
          * Amount of time an evaluation has before it times out. Note that the time required covers both evaluation
          * as well as any time needed for a post result transformation (if the transformation function is supplied
          * to the {@link GremlinExecutor#eval}).
@@ -636,14 +621,6 @@
             evaluationTimeoutOverride = Optional.ofNullable(builder.evaluationTimeoutOverride);
         }
 
-        /**
-         * @deprecated As of release 3.3.9, replaced by {@link #getEvaluationTimeoutOverride()}.
-         */
-        @Deprecated
-        public Optional<Long> getScriptEvaluationTimeoutOverride() {
-            return evaluationTimeoutOverride;
-        }
-
         public Optional<Long> getEvaluationTimeoutOverride() {
             return evaluationTimeoutOverride;
         }
@@ -743,18 +720,6 @@
             /**
              * An override to the global {@code evaluationTimeout} setting on the script engine. If this value
              * is set to {@code null} (the default) it will use the global setting.
-             *
-             * @deprecated As of release 3.3.9, replaced by {@link #evaluationTimeoutOverride}
-             */
-            @Deprecated
-            public Builder scriptEvaluationTimeoutOverride(final Long scriptEvaluationTimeoutOverride) {
-                this.evaluationTimeoutOverride = scriptEvaluationTimeoutOverride;
-                return this;
-            }
-
-            /**
-             * An override to the global {@code evaluationTimeout} setting on the script engine. If this value
-             * is set to {@code null} (the default) it will use the global setting.
              */
             public Builder evaluationTimeoutOverride(final Long evaluationTimeoutOverride) {
                 this.evaluationTimeoutOverride = evaluationTimeoutOverride;
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
index 6e6857f..438b5c6 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
@@ -215,11 +215,12 @@
         // initialize the global scope in case this scriptengine was instantiated outside of the ScriptEngineManager
         setBindings(new ConcurrentBindings(), ScriptContext.GLOBAL_SCOPE);
 
-        final List<Customizer> listOfCustomizers = new ArrayList<>(Arrays.asList(customizers));
+        final List<Customizer> listOfCustomizers = new ArrayList<>();
 
         // always need this plugin for a scriptengine to be "Gremlin-enabled"
         CoreGremlinPlugin.instance().getCustomizers("gremlin-groovy").ifPresent(c -> listOfCustomizers.addAll(Arrays.asList(c)));
-
+        listOfCustomizers.addAll(Arrays.asList(customizers));
+        
         GremlinLoader.load();
 
         final List<ImportCustomizer> importCustomizers = listOfCustomizers.stream()
@@ -258,7 +259,7 @@
                 filter(p -> p instanceof TranslatorCustomizer).
                 map(p -> (TranslatorCustomizer) p).findFirst();
         typeTranslator = translatorCustomizer.map(TranslatorCustomizer::createTypeTranslator).
-                orElseGet(GroovyTranslator.DefaultTypeTranslator::new);
+                orElseGet(() -> new GroovyTranslator.DefaultTypeTranslator(false));
 
         createClassLoader();
     }
@@ -292,8 +293,9 @@
         inner.putAll(bindings);
         inner.putAll(bytecode.getBindings());
         inner.put(HIDDEN_G, b);
-
-        return (Traversal.Admin) this.eval(GroovyTranslator.of(HIDDEN_G, typeTranslator).translate(bytecode), inner);
+        org.apache.tinkerpop.gremlin.process.traversal.Script script = GroovyTranslator.of(HIDDEN_G, typeTranslator).translate(bytecode);
+        script.getParameters().ifPresent(inner::putAll);
+        return (Traversal.Admin) this.eval(script.getScript(), inner);
     }
 
     /**
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
index 505f88a..3971577 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
@@ -20,10 +20,11 @@
 package org.apache.tinkerpop.gremlin.groovy.jsr223;
 
 import groovy.json.StringEscapeUtils;
-import org.apache.commons.configuration.ConfigurationConverter;
+import org.apache.commons.configuration2.ConfigurationConverter;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.Script;
 import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
@@ -41,14 +42,13 @@
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
 
 import java.sql.Timestamp;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
+import java.util.stream.Collectors;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
@@ -58,6 +58,7 @@
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @author Stark Arya (sandszhou.zj@alibaba-inc.com)
  */
 public final class GroovyTranslator implements Translator.ScriptTranslator {
 
@@ -69,20 +70,32 @@
         this.typeTranslator = typeTranslator;
     }
 
+    /**
+     * Creates the translator with a {@code false} argument to {@code withParameters} using
+     * {@link #of(String, boolean)}.
+     */
     public static final GroovyTranslator of(final String traversalSource) {
-        return of(traversalSource, null);
+        return of(traversalSource, false);
+    }
+
+    /**
+     * Creates the translator with the {@link DefaultTypeTranslator} passing the {@code withParameters} option to it
+     * which will handle type translation in a fashion that should typically increase cache hits and reduce
+     * compilation times if enabled at the sacrifice to rewriting of the script that could reduce readability.
+     */
+    public static final GroovyTranslator of(final String traversalSource, final boolean withParameters) {
+        return of(traversalSource, new DefaultTypeTranslator(withParameters));
     }
 
     public static final GroovyTranslator of(final String traversalSource, final TypeTranslator typeTranslator) {
-        return new GroovyTranslator(traversalSource,
-                Optional.ofNullable(typeTranslator).orElseGet(DefaultTypeTranslator::new));
+        return new GroovyTranslator(traversalSource, typeTranslator);
     }
 
     ///////
 
     @Override
-    public String translate(final Bytecode bytecode) {
-        return typeTranslator.apply(traversalSource, bytecode).toString();
+    public Script translate(final Bytecode bytecode) {
+        return typeTranslator.apply(traversalSource, bytecode);
     }
 
     @Override
@@ -104,127 +117,197 @@
      * Performs standard type translation for the TinkerPop types to Groovy.
      */
     public static class DefaultTypeTranslator implements TypeTranslator {
+        protected final boolean withParameters;
+        protected final Script script;
 
-        @Override
-        public Object apply(final String traversalSource, final Object o) {
-            if (o instanceof Bytecode)
-                return internalTranslate(traversalSource, (Bytecode) o);
-            else
-                return convertToString(o);
+        public DefaultTypeTranslator(final boolean withParameters) {
+           this.withParameters = withParameters;
+           this.script = new Script();
         }
 
-        protected String convertToString(final Object object) {
-            if (object instanceof Bytecode.Binding)
-                return ((Bytecode.Binding) object).variable();
-            else if (object instanceof Bytecode)
+        @Override
+        public Script apply(final String traversalSource, final Object o) {
+            this.script.init();
+            if (o instanceof Bytecode) {
+                return internalTranslate(traversalSource, (Bytecode) o);
+            } else {
+                return convertToScript(o);
+            }
+        }
+
+        /**
+         *  For each operator argument, if withParameters set true, try parametrization as follows:
+         *
+         *  -----------------------------------------------
+         *  if unpack, why ?     ObjectType
+         *  -----------------------------------------------
+         * (Yes)                Bytecode.Binding
+         * (Recursion, No)      Bytecode
+         *  (Recursion, No)      Traversal
+         * (Yes)                String
+         * (Recursion, No)      Set
+         * (Recursion, No)      List
+         * (Recursion, No)      Map
+         * (Yes)                Long
+         * (Yes)                Double
+         * (Yes)                Float
+         * (Yes)                Integer
+         * (Yes)                Timestamp
+         * (Yes)                Date
+         * (Yes)                Uuid
+         * (Recursion, No)      P
+         * (Enumeration, No)    SackFunctions.Barrier
+         * (Enumeration, No)    VertexProperty.Cardinality
+         * (Enumeration, No)    TraversalOptionParent.Pick
+         * (Enumeration, No)    Enum
+         * (Recursion, No)      Vertex
+         * (Recursion, No)      Edge
+         * (Recursion, No)      VertexProperty
+         * (Yes)                Lambda
+         * (Recursion, No)      TraversalStrategyProxy
+         * (Enumeration, No)    TraversalStrategy
+         *  (Yes)                 Other
+         *  -------------------------------------------------
+         * @param object
+         * @return String Repres
+         */
+        protected Script convertToScript(final Object object) {
+            if (object instanceof Bytecode.Binding) {
+                return script.getBoundKeyOrAssign(withParameters, ((Bytecode.Binding) object).variable());
+            } else if (object instanceof Bytecode) {
                 return internalTranslate("__", (Bytecode) object);
-            else if (object instanceof Traversal)
-                return convertToString(((Traversal) object).asAdmin().getBytecode());
-            else if (object instanceof String) {
-                return (((String) object).contains("\"") ? "\"\"\"" + StringEscapeUtils.escapeJava((String) object) + "\"\"\"" : "\"" + StringEscapeUtils.escapeJava((String) object) + "\"")
+            } else if (object instanceof Traversal) {
+                return convertToScript(((Traversal) object).asAdmin().getBytecode());
+            } else if (object instanceof String) {
+                final String wrapper = (((String) object).contains("\"") ? "\"\"\"" + StringEscapeUtils.escapeJava((String) object) + "\"\"\"" : "\"" + StringEscapeUtils.escapeJava((String) object) + "\"")
                         .replace("$", "\\$");
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper);
             } else if (object instanceof Set) {
-                final Set<String> set = new HashSet<>(((Set) object).size());
-                for (final Object item : (Set) object) {
-                    set.add(convertToString(item));
-                }
-                return set.toString() + " as Set";
+                convertToScript(((Set)object).stream().collect(Collectors.toList()));
+                return script.append(" as Set");
             } else if (object instanceof List) {
-                final List<String> list = new ArrayList<>(((List) object).size());
-                for (final Object item : (List) object) {
-                    list.add(convertToString(item));
+                Iterator<?> iterator = ((List)object).iterator();
+                if (! iterator.hasNext()) {
+                    return script.append("[]");
+                } else {
+                    script.append("[");
+                    for (;;)  {
+                        Object e =  iterator.next();
+                        convertToScript(e);
+                        if (! iterator.hasNext()) {
+                            return script.append("]");
+                        } else {
+                            script.append(",").append(" ");
+                        }
+                    }
                 }
-                return list.toString();
             } else if (object instanceof Map) {
-                final StringBuilder map = new StringBuilder("[");
+                script.append("[");
                 for (final Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
-                    map.append("(").
-                            append(convertToString(entry.getKey())).
-                            append("):(").
-                            append(convertToString(entry.getValue())).
-                            append("),");
+                    script.append("(");
+                    convertToScript(entry.getKey());
+                    script.append("):(");
+                    convertToScript(entry.getValue());
+                    script.append("),");
                 }
 
                 // only need to remove this last bit if entries were added
-                if (!((Map<?, ?>) object).isEmpty())
-                    map.deleteCharAt(map.length() - 1);
-
-                return map.append("]").toString();
-            } else if (object instanceof Long)
-                return object + "L";
-            else if (object instanceof Double)
-                return object + "d";
-            else if (object instanceof Float)
-                return object + "f";
-            else if (object instanceof Integer)
-                return "(int) " + object;
-            else if (object instanceof Class)
-                return ((Class) object).getCanonicalName();
-            else if (object instanceof Timestamp)
-                return "new java.sql.Timestamp(" + ((Timestamp) object).getTime() + ")";
-            else if (object instanceof Date)
-                return "new java.util.Date(" + ((Date) object).getTime() + ")";
-            else if (object instanceof UUID)
-                return "java.util.UUID.fromString('" + object.toString() + "')";
-            else if (object instanceof P)
-                return convertPToString((P) object, new StringBuilder()).toString();
-            else if (object instanceof SackFunctions.Barrier)
-                return "SackFunctions.Barrier." + object.toString();
-            else if (object instanceof VertexProperty.Cardinality)
-                return "VertexProperty.Cardinality." + object.toString();
-            else if (object instanceof TraversalOptionParent.Pick)
-                return "TraversalOptionParent.Pick." + object.toString();
-            else if (object instanceof Enum)
-                return ((Enum) object).getDeclaringClass().getSimpleName() + "." + object.toString();
-            else if (object instanceof Element) {
+                if (!((Map<?, ?>) object).isEmpty()) {
+                    return script.setCharAtEnd(']');
+                } else {
+                    return script.append("]");
+                }
+            } else if (object instanceof Long) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object + "L");
+            } else if (object instanceof Double) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object + "d");
+            } else if (object instanceof Float) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object + "f");
+            } else if (object instanceof Integer) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "(int) " + object);
+            } else if (object instanceof Class) {
+                return script.append(((Class) object).getCanonicalName());
+            } else if (object instanceof Timestamp) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "new java.sql.Timestamp(" + ((Timestamp) object).getTime() + ")");
+            } else if (object instanceof Date) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "new java.util.Date(" + ((Date) object).getTime() + ")");
+            } else if (object instanceof UUID) {
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "java.util.UUID.fromString('" + object.toString() + "')");
+            } else if (object instanceof P) {
+                return convertPToScript((P) object);
+            } else if (object instanceof SackFunctions.Barrier) {
+                return script.append("SackFunctions.Barrier." + object.toString());
+            } else if (object instanceof VertexProperty.Cardinality) {
+                return script.append("VertexProperty.Cardinality." + object.toString());
+            } else if (object instanceof TraversalOptionParent.Pick) {
+                return script.append("TraversalOptionParent.Pick." + object.toString());
+            } else if (object instanceof Enum) {
+                return script.append(((Enum) object).getDeclaringClass().getSimpleName() + "." + object.toString());
+            } else if (object instanceof Element) {
                 if (object instanceof Vertex) {
                     final Vertex vertex = (Vertex) object;
-                    return "new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(" +
-                            convertToString(vertex.id()) + "," +
-                            convertToString(vertex.label()) + ", Collections.emptyMap())";
+                    script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(");
+                    convertToScript(vertex.id());
+                    script.append(",");
+                    convertToScript(vertex.label());
+                    return script.append(", Collections.emptyMap())");
                 } else if (object instanceof Edge) {
                     final Edge edge = (Edge) object;
-                    return "new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(" +
-                            convertToString(edge.id()) + "," +
-                            convertToString(edge.label()) + "," +
-                            "Collections.emptyMap()," +
-                            convertToString(edge.outVertex().id()) + "," +
-                            convertToString(edge.outVertex().label()) + "," +
-                            convertToString(edge.inVertex().id()) + "," +
-                            convertToString(edge.inVertex().label()) + ")";
+                    script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(");
+                    convertToScript(edge.id());
+                    script.append(",");
+                    convertToScript(edge.label());
+                    script.append(",");
+                    script.append("Collections.emptyMap(),");
+                    convertToScript(edge.outVertex().id());
+                    script.append(",");
+                    convertToScript(edge.outVertex().label());
+                    script.append(",");
+                    convertToScript(edge.inVertex().id());
+                    script.append(",");
+                    convertToScript(edge.inVertex().label());
+                    return script.append(")");
                 } else {// VertexProperty
                     final VertexProperty vertexProperty = (VertexProperty) object;
-                    return "new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty(" +
-                            convertToString(vertexProperty.id()) + "," +
-                            convertToString(vertexProperty.label()) + "," +
-                            convertToString(vertexProperty.value()) + "," +
-                            "Collections.emptyMap()," +
-                            convertToString(vertexProperty.element()) + ")";
+                    script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty(");
+                    convertToScript(vertexProperty.id());
+                    script.append(",");
+                    convertToScript(vertexProperty.label());
+                    script.append(",");
+                    convertToScript(vertexProperty.value());
+                    script.append(",");
+                    script.append("Collections.emptyMap(),");
+                    convertToScript(vertexProperty.element());
+                    return script.append(")");
                 }
             } else if (object instanceof Lambda) {
                 final String lambdaString = ((Lambda) object).getLambdaScript().trim();
-                return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
+                final String wrapper = lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
+                return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper);
             } else if (object instanceof TraversalStrategyProxy) {
                 final TraversalStrategyProxy proxy = (TraversalStrategyProxy) object;
-                if (proxy.getConfiguration().isEmpty())
-                    return proxy.getStrategyClass().getCanonicalName() + ".instance()";
-                else
-                    return proxy.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration.MapConfiguration(" + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + "))";
+                if (proxy.getConfiguration().isEmpty()) {
+                    return script.append(proxy.getStrategyClass().getCanonicalName() + ".instance()");
+                } else {
+                    script.append(proxy.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration2.MapConfiguration(");
+                    convertToScript(ConfigurationConverter.getMap(proxy.getConfiguration()));
+                    return script.append("))");
+                }
             } else if (object instanceof TraversalStrategy) {
-                return convertToString(new TraversalStrategyProxy(((TraversalStrategy) object)));
-            } else
-                return null == object ? "null" : object.toString();
+                return convertToScript(new TraversalStrategyProxy(((TraversalStrategy) object)));
+            } else {
+                return null == object ? script.append("null") : script.getBoundKeyOrAssign(withParameters, object);
+            }
         }
 
-        protected String internalTranslate(final String start, final Bytecode bytecode) {
-            final StringBuilder traversalScript = new StringBuilder(start);
+        protected Script internalTranslate(final String start, final Bytecode bytecode) {
+            script.append(start);
             for (final Bytecode.Instruction instruction : bytecode.getInstructions()) {
                 final String methodName = instruction.getOperator();
-                if (0 == instruction.getArguments().length)
-                    traversalScript.append(".").append(methodName).append("()");
-                else {
-                    traversalScript.append(".");
-                    String temp = methodName + "(";
+                if (0 == instruction.getArguments().length) {
+                    script.append(".").append(methodName).append("()");
+                } else {
+                    script.append(".").append(methodName).append("(");
 
                     // have to special case withSack() for Groovy because UnaryOperator and BinaryOperator signatures
                     // make it impossible for the interpreter to figure out which function to call. specifically we need
@@ -242,39 +325,49 @@
                         final String castSecondArgTo = secondArg.getLambdaArguments() == 1 ? UnaryOperator.class.getName() :
                                 BinaryOperator.class.getName();
                         if (!castFirstArgTo.isEmpty())
-                            temp = temp + String.format("(%s) ", castFirstArgTo);
-                        temp = temp + String.format("%s, (%s) %s,",
-                                convertToString(instruction.getArguments()[0]), castSecondArgTo,
-                                convertToString(instruction.getArguments()[1]));
+                            script.append(String.format("(%s) ", castFirstArgTo));
+                        convertToScript(instruction.getArguments()[0]);
+                        script.append(", (").append(castSecondArgTo).append(") ");
+                        convertToScript(instruction.getArguments()[1]);
+                        script.append(",");
                     } else {
                         for (final Object object : instruction.getArguments()) {
-                            temp = temp + convertToString(object) + ",";
+                            convertToScript(object);
+                            script.append(",");
                         }
                     }
-                    traversalScript.append(temp.substring(0, temp.length() - 1)).append(")");
+                    script.setCharAtEnd(')');
                 }
             }
-            return traversalScript.toString();
+            return script;
         }
 
-        protected StringBuilder convertPToString(final P p, final StringBuilder current) {
-            if (p instanceof TextP) return convertTextPToString((TextP) p, current);
+        protected Script convertPToScript(final P p) {
+            if (p instanceof TextP) {
+                return convertTextPToScript((TextP) p);
+            }
             if (p instanceof ConnectiveP) {
                 final List<P<?>> list = ((ConnectiveP) p).getPredicates();
                 for (int i = 0; i < list.size(); i++) {
-                    convertPToString(list.get(i), current);
-                    if (i < list.size() - 1)
-                        current.append(p instanceof OrP ? ".or(" : ".and(");
+                    convertPToScript(list.get(i));
+                    if (i < list.size() - 1) {
+                        script.append(p instanceof OrP ? ".or(" : ".and(");
+                    }
                 }
-                current.append(")");
-            } else
-                current.append("P.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
-            return current;
+                script.append(")");
+            } else {
+                script.append("P.").append(p.getBiPredicate().toString()).append("(");
+                convertToScript(p.getValue());
+                script.append(")");
+            }
+            return script;
         }
 
-        protected StringBuilder convertTextPToString(final TextP p, final StringBuilder current) {
-            current.append("TextP.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
-            return current;
+        protected Script convertTextPToScript(final TextP p) {
+            script.append("TextP.").append(p.getBiPredicate().toString()).append("(");
+            convertToScript(p.getValue());
+            script.append(")");
+            return script;
         }
     }
 }
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
index 226a3f7..50e1aec 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
@@ -267,7 +267,7 @@
         final CountDownLatch timeOutCount = new CountDownLatch(1);
 
         final GremlinExecutor gremlinExecutor = GremlinExecutor.build()
-                .scriptEvaluationTimeout(250)
+                .evaluationTimeout(250)
                 .afterFailure((b, e) -> failureCalled.set(true))
                 .afterSuccess((b) -> successCalled.set(true))
                 .afterTimeout((b) -> timeOutCount.countDown()).create();
@@ -321,13 +321,13 @@
         final CountDownLatch timeOutCount = new CountDownLatch(1);
 
         final GremlinExecutor gremlinExecutor = GremlinExecutor.build()
-                .scriptEvaluationTimeout(10000)
+                .evaluationTimeout(10000)
                 .afterFailure((b, e) -> failureCalled.set(true))
                 .afterSuccess((b) -> successCalled.set(true))
                 .afterTimeout((b) -> timeOutCount.countDown()).create();
         try {
             final GremlinExecutor.LifeCycle lifeCycle = GremlinExecutor.LifeCycle.build()
-                    .scriptEvaluationTimeoutOverride(250L).create();
+                    .evaluationTimeoutOverride(250L).create();
             gremlinExecutor.eval("Thread.sleep(1000);10", "gremlin-groovy", new SimpleBindings(), lifeCycle).get();
             fail("This script should have timed out with an exception");
         } catch (Exception ex) {
@@ -460,15 +460,15 @@
 
     @Test
     public void shouldCancelTimeoutOnSuccessfulScript() throws Exception {
-        final long scriptEvaluationTimeout = 5_000;
+        final long evaluationTimeout = 5_000;
         final GremlinExecutor gremlinExecutor = GremlinExecutor.build()
-                .scriptEvaluationTimeout(scriptEvaluationTimeout)
+                .evaluationTimeout(evaluationTimeout)
                 .create();
 
         final long now = System.currentTimeMillis();
         assertEquals(2, gremlinExecutor.eval("1+1").get());
         gremlinExecutor.close();
-        assertTrue(System.currentTimeMillis() - now < scriptEvaluationTimeout);
+        assertTrue(System.currentTimeMillis() - now < evaluationTimeout);
     }
 
     @Test
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
index d40dc19..a2b8127 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
@@ -23,6 +23,7 @@
 import groovy.lang.MissingPropertyException;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.javatuples.Pair;
 import org.junit.Test;
@@ -103,7 +104,7 @@
     public void shouldPromoteDefinedVarsInInterpreterModeWithNoBindings() throws Exception {
         final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(new InterpreterModeGroovyCustomizer());
         engine.eval("def addItUp = { x, y -> x + y }");
-        engine.eval("def class A { def sub(int x, int y) {x - y}}");
+        engine.eval("class A { def sub(int x, int y) {x - y}}");
         assertEquals(3, engine.eval("int xxx = 1 + 2"));
         assertEquals(4, engine.eval("yyy = xxx + 1"));
         assertEquals(7, engine.eval("def zzz = yyy + xxx"));
@@ -413,4 +414,16 @@
         final Lambda l = (Lambda) engine.eval(" org.apache.tinkerpop.gremlin.util.function.Lambda.function(\"{ it.get() }\")");
         assertEquals("{ it.get() }", l.getLambdaScript());
     }
+
+    /**
+     * Test for TINKERPOP-2394 Unable to use __ class of a custom DSL when passing a script even if this class is imported
+     */
+	@Test
+	public void customizerShouldOverrideCoreImports() throws Exception {
+		DefaultImportCustomizer customizer = DefaultImportCustomizer.build()
+				.addClassImports(org.apache.tinkerpop.gremlin.groovy.jsr223.dsl.credential.__.class)
+				.create();
+		final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(customizer);
+		engine.eval("__.users();[]");
+	}
 }
\ No newline at end of file
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java
index 5f556b8..b4d2452 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java
@@ -207,10 +207,6 @@
         method = "shouldNeverPropagateANoBulkTraverser",
         reason = "Reason requires investigation")
 @Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.CoreTraversalTest",
-        method = "shouldNeverPropagateANullValuedTraverser",
-        reason = "Reason requires investigation")
-@Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
         method = "*",
         reason = "read and write tests don't translate locally well because of calling iterate() inside read()/write() add a none()")
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
index 71f79ec..523c19f 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
@@ -19,11 +19,12 @@
 
 package org.apache.tinkerpop.gremlin.groovy.jsr223;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.jsr223.TranslatorCustomizer;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Script;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -107,22 +108,22 @@
         final GraphTraversalSource g = graph.traversal();
 
         final Traversal<Vertex,Double> tConstantUnary = g.withSack(1.0, Lambda.unaryOperator("it + 1")).V().sack();
-        final String scriptConstantUnary = GroovyTranslator.of("g").translate(tConstantUnary.asAdmin().getBytecode());
+        final String scriptConstantUnary = GroovyTranslator.of("g").translate(tConstantUnary.asAdmin().getBytecode()).getScript();
         assertEquals("g.withSack(1.0d, (java.util.function.UnaryOperator) {it + 1}).V().sack()", scriptConstantUnary);
         assertThatScriptOk(scriptConstantUnary, "g", g);
 
         final Traversal<Vertex,Double> tSupplierUnary = g.withSack(Lambda.supplier("1.0d"), Lambda.<Double>unaryOperator("it + 1")).V().sack();
-        final String scriptSupplierUnary = GroovyTranslator.of("g").translate(tSupplierUnary.asAdmin().getBytecode());
+        final String scriptSupplierUnary = GroovyTranslator.of("g").translate(tSupplierUnary.asAdmin().getBytecode()).getScript();
         assertEquals("g.withSack((java.util.function.Supplier) {1.0d}, (java.util.function.UnaryOperator) {it + 1}).V().sack()", scriptSupplierUnary);
         assertThatScriptOk(scriptSupplierUnary, "g", g);
 
         final Traversal<Vertex,Double> tConstantBinary = g.withSack(1.0, Lambda.binaryOperator("x,y -> x + y + 1")).V().sack();
-        final String scriptConstantBinary = GroovyTranslator.of("g").translate(tConstantBinary.asAdmin().getBytecode());
+        final String scriptConstantBinary = GroovyTranslator.of("g").translate(tConstantBinary.asAdmin().getBytecode()).getScript();
         assertEquals("g.withSack(1.0d, (java.util.function.BinaryOperator) {x,y -> x + y + 1}).V().sack()", scriptConstantBinary);
         assertThatScriptOk(scriptConstantBinary, "g", g);
 
         final Traversal<Vertex,Double> tSupplierBinary = g.withSack(Lambda.supplier("1.0d"), Lambda.<Double>binaryOperator("x,y -> x + y + 1")).V().sack();
-        final String scriptSupplierBinary = GroovyTranslator.of("g").translate(tSupplierBinary.asAdmin().getBytecode());
+        final String scriptSupplierBinary = GroovyTranslator.of("g").translate(tSupplierBinary.asAdmin().getBytecode()).getScript();
         assertEquals("g.withSack((java.util.function.Supplier) {1.0d}, (java.util.function.BinaryOperator) {x,y -> x + y + 1}).V().sack()", scriptSupplierBinary);
         assertThatScriptOk(scriptSupplierBinary, "g", g);
     }
@@ -168,7 +169,7 @@
         //
         assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
 
-        final String script = GroovyTranslator.of("g").translate(t.getBytecode());
+        final String script = GroovyTranslator.of("g").translate(t.getBytecode()).getScript();
         assertEquals("g.withStrategies(org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy.instance())" +
                         ".withSideEffect(\"lengthSum\",(int) 0).withSack((int) 1)" +
                         ".V()" +
@@ -188,7 +189,7 @@
         final String script = GroovyTranslator.of("g").translate(g.V().id().is(new LinkedHashMap<Object,Object>() {{
             put(3, "32");
             put(Arrays.asList(1, 2, 3.1d), 4);
-        }}).asAdmin().getBytecode());
+        }}).asAdmin().getBytecode()).getScript();
         assertEquals("g.V().id().is([((int) 3):(\"32\"),([(int) 1, (int) 2, 3.1d]):((int) 4)])", script);
         assertThatScriptOk(script, "g", g);
     }
@@ -198,7 +199,7 @@
         final TinkerGraph graph = TinkerFactory.createModern();
         final GraphTraversalSource g = graph.traversal();
         final Function identity = new Lambda.OneArgLambda("it.get()", "gremlin-groovy");
-        final String script = GroovyTranslator.of("g").translate(g.inject(Collections.emptyMap()).map(identity).asAdmin().getBytecode());
+        final String script = GroovyTranslator.of("g").translate(g.inject(Collections.emptyMap()).map(identity).asAdmin().getBytecode()).getScript();
         assertEquals("g.inject([]).map({it.get()})", script);
         assertThatScriptOk(script, "g", g);
     }
@@ -237,7 +238,7 @@
 
     @Test
     public void shouldHandleOrder() {
-        assertTranslation("Order.decr", Order.decr);
+        assertTranslation("Order.shuffle", Order.shuffle);
     }
 
     @Test
@@ -258,12 +259,12 @@
 
         // without type translation we get uglinesss
         final String scriptBad = GroovyTranslator.of("g").
-                translate(g.inject(notSillyEnough).asAdmin().getBytecode());
+                translate(g.inject(notSillyEnough).asAdmin().getBytecode()).getScript();
         assertEquals(String.format("g.inject(%s)", "not silly enough:100"), scriptBad);
 
         // with type translation we get valid gremlin
-        final String scriptGood = GroovyTranslator.of("g", new SillyClassTranslator()).
-                translate(g.inject(notSillyEnough).asAdmin().getBytecode());
+        final String scriptGood = GroovyTranslator.of("g", new SillyClassTranslator(false)).
+                translate(g.inject(notSillyEnough).asAdmin().getBytecode()).getScript();
         assertEquals(String.format("g.inject(org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslatorTest.SillyClass.from('%s', (int) %s))", notSillyEnough.getX(), notSillyEnough.getY()), scriptGood);
         assertThatScriptOk(scriptGood, "g", g);
 
@@ -291,7 +292,7 @@
                 .property("name", "Foo\u0020Bar")
                 .property("age", 25)
                 .property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
-                .asAdmin().getBytecode());
+                .asAdmin().getBytecode()).getScript();
 
         assertEquals("g.addV(\"customer\")" +
                         ".property(\"customer_id\",501L)" +
@@ -309,7 +310,7 @@
         final Object id1 = "customer:10:foo\u0020bar\u0020\u0024100#90"; // customer:10:foo bar $100#90
         final Vertex vertex1 = DetachedVertex.build().setLabel("customer").setId(id1)
                 .create();
-        final String script1 = GroovyTranslator.of("g").translate(g.inject(vertex1).asAdmin().getBytecode());
+        final String script1 = GroovyTranslator.of("g").translate(g.inject(vertex1).asAdmin().getBytecode()).getScript();
         assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(" +
                         "\"customer:10:foo bar \\$100#90\"," +
                         "\"customer\", Collections.emptyMap()))",
@@ -319,7 +320,7 @@
         final Object id2 = "user:20:foo\\u0020bar\\u005c\\u0022mr\\u005c\\u0022\\u00241000#50"; // user:20:foo\u0020bar\u005c\u0022mr\u005c\u0022\u00241000#50
         final Vertex vertex2 = DetachedVertex.build().setLabel("user").setId(id2)
                 .create();
-        final String script2 = GroovyTranslator.of("g").translate(g.inject(vertex2).asAdmin().getBytecode());
+        final String script2 = GroovyTranslator.of("g").translate(g.inject(vertex2).asAdmin().getBytecode()).getScript();
         assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(" +
                         "\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\"," +
                         "\"user\", Collections.emptyMap()))",
@@ -331,7 +332,7 @@
                 .setOutV((DetachedVertex) vertex1)
                 .setInV((DetachedVertex) vertex2)
                 .create();
-        final String script3 = GroovyTranslator.of("g").translate(g.inject(edge).asAdmin().getBytecode());
+        final String script3 = GroovyTranslator.of("g").translate(g.inject(edge).asAdmin().getBytecode()).getScript();
         assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(" +
                         "\"knows:30:foo bar \\$100:\\\\u0020\\\\u0024500#70\"," +
                         "\"knows\",Collections.emptyMap()," +
@@ -342,7 +343,7 @@
 
         final String script4 = GroovyTranslator.of("g").translate(
                 g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
-                        .asAdmin().getBytecode());
+                        .asAdmin().getBytecode()).getScript();
         assertEquals("g.addE(\"knows\")" +
                         ".from(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(\"customer:10:foo bar \\$100#90\",\"customer\", Collections.emptyMap()))" +
                         ".to(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\",\"user\", Collections.emptyMap()))" +
@@ -359,9 +360,9 @@
     }
 
     private void assertTranslation(final String expectedTranslation, final Object... objs) {
-        final String script = GroovyTranslator.of("g").translate(g.inject(objs).asAdmin().getBytecode());
-        assertEquals(String.format("g.inject(%s)", expectedTranslation), script);
-        assertThatScriptOk(script, "g", g);
+        final Script script = GroovyTranslator.of("g").translate(g.inject(objs).asAdmin().getBytecode());
+        assertEquals(String.format("g.inject(%s)", expectedTranslation), script.getScript());
+        assertThatScriptOk(script.getScript(), "g", g);
     }
 
     private void assertThatScriptOk(final String s, final Object... args) {
@@ -403,13 +404,18 @@
 
     public static class SillyClassTranslator extends GroovyTranslator.DefaultTypeTranslator {
 
+        public SillyClassTranslator(final boolean withParameters) {
+            super(withParameters);
+        }
+
         @Override
-        protected String convertToString(final Object object) {
-            if (object instanceof SillyClass)
-                return String.format("org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslatorTest.SillyClass.from('%s', (int) %s)",
-                        ((SillyClass) object).getX(), ((SillyClass) object).getY());
-            else
-                return super.convertToString(object);
+        protected Script convertToScript(final Object object) {
+            if (object instanceof SillyClass) {
+                return script.append(String.format("org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslatorTest.SillyClass.from('%s', (int) %s)",
+                        ((SillyClass) object).getX(), ((SillyClass) object).getY()));
+            } else {
+                return super.convertToScript(object);
+            }
         }
     }
 
@@ -417,7 +423,7 @@
 
         @Override
         public Translator.ScriptTranslator.TypeTranslator createTypeTranslator() {
-            return new SillyClassTranslator();
+            return new SillyClassTranslator(false);
         }
     }
 }
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorComputerProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorComputerProvider.java
new file mode 100644
index 0000000..3c948fa
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorComputerProvider.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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.GraphProvider;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.computer.GraphComputerTest",
+        method = "shouldSucceedWithProperTraverserRequirements",
+        reason = "Reason requires investigation")
+@GraphProvider.Descriptor(computer = TinkerGraphComputer.class)
+public class ParameterizedGroovyTranslatorComputerProvider extends ParameterizedGroovyTranslatorProvider {
+
+    @Override
+    public GraphTraversalSource traversal(final Graph graph) {
+        return super.traversal(graph).withComputer();
+    }
+}
\ No newline at end of file
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProcessComputerTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProcessComputerTest.java
new file mode 100644
index 0000000..e0cad35
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProcessComputerTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.process.ProcessComputerSuite;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(ProcessComputerSuite.class)
+@GraphProviderClass(provider = ParameterizedGroovyTranslatorComputerProvider.class, graph = TinkerGraph.class)
+public class ParameterizedGroovyTranslatorProcessComputerTest {
+}
\ No newline at end of file
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProcessStandardTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProcessStandardTest.java
new file mode 100644
index 0000000..d00a53c
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProcessStandardTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(ProcessStandardSuite.class)
+@GraphProviderClass(provider = ParameterizedGroovyTranslatorProvider.class, graph = TinkerGraph.class)
+public class ParameterizedGroovyTranslatorProcessStandardTest {
+}
\ No newline at end of file
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProvider.java
new file mode 100644
index 0000000..56466a5
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorProvider.java
@@ -0,0 +1,223 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.util.TinkerGraphProvider;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ProfileTest",
+        method = "*",
+        reason = "Tests for profile() are not supported for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchTest",
+        method = "g_V_branchXlabel_eq_person__a_bX_optionXa__ageX_optionXb__langX_optionXb__nameX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseTest",
+        method = "g_V_chooseXlabel_eqXpersonX__outXknowsX__inXcreatedXX_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_both_name_order_byXa_bX_dedup_value",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_E_filterXfalseX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_E_filterXtrueX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXfalseX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXlang_eq_javaX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXname_startsWith_m_OR_name_startsWith_pX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXtrueX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_VX1X_filterXage_gt_30X",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_VX1X_out_filterXage_gt_30X",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_VX2X_filterXage_gt_30X",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXname_substring_1X_byXconstantX1XX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_outXcreatedX_hasXname__mapXlengthX_isXgtX3XXX_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
+        method = "g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MapTest",
+        method = "g_VX1X_mapXnameX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MapTest",
+        method = "g_VX1X_out_mapXnameX_mapXlengthX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MapTest",
+        method = "g_VX1X_outE_label_mapXlengthX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MapTest",
+        method = "g_withPath_V_asXaX_out_mapXa_nameX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MapTest",
+        method = "g_withPath_V_asXaX_out_out_mapXa_name_it_nameX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_hasLabelXpersonX_order_byXvalueXageX_descX_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_name_order_byXa1_b1X_byXb2_a2X",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_order_byXname_a1_b1X_byXname_b2_a2X_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXbothX_untilXname_eq_marko_or_loops_gt_1X_groupCount_byXnameX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackTest",
+        method = "g_withSackXmap__map_cloneX_V_out_out_sackXmap_a_nameX_sack",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_VX1X_out_sideEffectXincr_cX_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_VX1X_out_sideEffectXX_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_VX1X_sideEffectXstore_aX_name",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_withSideEffectsXa__linkedhashmapX_withSideEffectXb__arraylist__addAllX_withSideEffectXc__arrayList__addAllX_V_groupXaX_byXlabelX_byXcountX_sideEffectXb__1_2_3X_out_out_out_sideEffectXc__bob_danielX_capXaX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_withSideEffectXa_0_sumX_V_out_sideEffectXsideEffectsXa_bulkXX_capXaX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_withSideEffectXa_0X_V_out_sideEffectXsideEffectsXa_1XX_capXaX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectTest",
+        method = "g_withSideEffectXa__linkedhashmapX_V_out_groupCountXaX_byXlabelX_out_out_capXaX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTest",
+        method = "g_V_withSideEffectXsgX_outEXknowsX_subgraphXsgX_name_capXsgX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTest",
+        method = "g_V_withSideEffectXsgX_repeatXbothEXcreatedX_subgraphXsgX_outVX_timesX5X_name_dedup",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTest",
+        method = "g_withSideEffectXsgX_V_hasXname_danielXout_capXsgX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldTest",
+        method = "g_V_valueMap_unfold_mapXkeyX",
+        reason = "Tests that include lambdas are not supported by the test suite for remotes")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ProgramTest",
+        method = "*",
+        reason = "Reason requires investigation")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionTest",
+        method = "*",
+        reason = "Reason requires investigation")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionComputerTest",
+        method = "*",
+        reason = "Reason requires investigation")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategyProcessTest",
+        method = "*",
+        reason = "Strategy not properly supported by Bytecode based traversals")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategyProcessTest",
+        method = "*",
+        reason = "Strategy not properly supported by Bytecode based traversals")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.CoreTraversalTest",
+        method = "shouldNeverPropagateANoBulkTraverser",
+        reason = "Reason requires investigation")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
+        method = "*",
+        reason = "read and write tests don't translate locally well because of calling iterate() inside read()/write() add a none()")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.WriteTest",
+        method = "*",
+        reason = "read and write tests don't translate locally well because of calling iterate() inside read()/write() add a none()")
+public class ParameterizedGroovyTranslatorProvider extends TinkerGraphProvider {
+    @Override
+    public GraphTraversalSource traversal(final Graph graph) {
+        final GraphTraversalSource g = graph.traversal();
+        return g.withStrategies(new TranslationStrategy(g, GroovyTranslator.of("g", true), true));
+    }
+}
\ No newline at end of file
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorTest.java
new file mode 100644
index 0000000..2d07b52
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ParameterizedGroovyTranslatorTest.java
@@ -0,0 +1,664 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.jsr223.TranslatorCustomizer;
+import org.apache.tinkerpop.gremlin.process.traversal.Compare;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Script;
+import org.apache.tinkerpop.gremlin.process.traversal.Translator;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
+import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.junit.Test;
+
+import javax.script.Bindings;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ *  test {@link GroovyTranslator} which return parameterized result, covers:
+ *   - parameterized script checking
+ *   - binding checking
+ *   - eval result checking
+ *
+ *  <p>
+ *  {@link GroovyTranslatorTest } is used to test {@link GroovyTranslator}, both test cases looks the same
+ *  <p>
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @author Stark Arya (sandszhou.zj@alibaba-inc.com)
+ */
+public class ParameterizedGroovyTranslatorTest {
+
+    private Graph graph = TinkerGraph.open();
+    private GraphTraversalSource g = graph.traversal();
+    private static final GremlinGroovyScriptEngine parameterizedEngine = new GremlinGroovyScriptEngine(new TranslatorCustomizer() {
+        @Override
+        public Translator.ScriptTranslator.TypeTranslator createTypeTranslator() {
+            return new GroovyTranslator.DefaultTypeTranslator(true);
+        }
+    });
+
+    @Test
+    public void shouldHandleStrategies() throws Exception {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal().withStrategies(SubgraphStrategy.create(new MapConfiguration(new HashMap<String, Object>() {{
+            put(SubgraphStrategy.VERTICES, __.has("name", "marko"));
+        }})));
+        final Bindings bindings = new SimpleBindings();
+        bindings.put("g", g);
+        Traversal.Admin<Vertex, Object> traversal = parameterizedEngine.eval(g.V().values("name").asAdmin().getBytecode(), bindings, "g");
+        assertEquals("marko", traversal.next());
+        assertFalse(traversal.hasNext());
+        //
+        traversal = parameterizedEngine.eval(g.withoutStrategies(SubgraphStrategy.class).V().count().asAdmin().getBytecode(), bindings, "g");
+        assertEquals(new Long(6), traversal.next());
+        assertFalse(traversal.hasNext());
+        //
+        traversal = parameterizedEngine.eval(g.withStrategies(SubgraphStrategy.create(new MapConfiguration(new HashMap<String, Object>() {{
+            put(SubgraphStrategy.VERTICES, __.has("name", "marko"));
+        }})), ReadOnlyStrategy.instance()).V().values("name").asAdmin().getBytecode(), bindings, "g");
+        assertEquals("marko", traversal.next());
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    public void shouldSupportStringSupplierLambdas() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        GraphTraversalSource g = graph.traversal();
+        g = g.withStrategies(new TranslationStrategy(g, GroovyTranslator.of("g", true), false));
+        final GraphTraversal.Admin<Vertex, Integer> t = g.withSideEffect("lengthSum", 0).withSack(1)
+                .V()
+                .filter(Lambda.predicate("it.get().label().equals('person')"))
+                .flatMap(Lambda.function("it.get().vertices(Direction.OUT)"))
+                .map(Lambda.<Traverser<Object>, Integer>function("it.get().value('name').length()"))
+                .sideEffect(Lambda.consumer("{ x -> x.sideEffects(\"lengthSum\", x.<Integer>sideEffects('lengthSum') + x.get()) }"))
+                .order().by(Lambda.comparator("a,b -> a <=> b"))
+                .sack(Lambda.biFunction("{ a,b -> a + b }"))
+                .asAdmin();
+
+        final List<Integer> sacks = new ArrayList<>();
+        final List<Integer> lengths = new ArrayList<>();
+        while (t.hasNext()) {
+            final Traverser.Admin<Integer> traverser = t.nextTraverser();
+            sacks.add(traverser.sack());
+            lengths.add(traverser.get());
+        }
+        assertFalse(t.hasNext());
+        //
+        assertEquals(6, lengths.size());
+        assertEquals(3, lengths.get(0).intValue());
+        assertEquals(3, lengths.get(1).intValue());
+        assertEquals(3, lengths.get(2).intValue());
+        assertEquals(4, lengths.get(3).intValue());
+        assertEquals(5, lengths.get(4).intValue());
+        assertEquals(6, lengths.get(5).intValue());
+        ///
+        assertEquals(6, sacks.size());
+        assertEquals(4, sacks.get(0).intValue());
+        assertEquals(4, sacks.get(1).intValue());
+        assertEquals(4, sacks.get(2).intValue());
+        assertEquals(5, sacks.get(3).intValue());
+        assertEquals(6, sacks.get(4).intValue());
+        assertEquals(7, sacks.get(5).intValue());
+        //
+        assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
+
+        final Script script = GroovyTranslator.of("g", true).translate(t.getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(9, bindings.size());
+        assertEquals("lengthSum", bindings.get("_args_0"));
+        assertEquals(Integer.valueOf(0), bindings.get("_args_1"));
+        assertEquals(Integer.valueOf(1), bindings.get("_args_2"));
+        assertEquals(Lambda.predicate("it.get().label().equals('person')"), bindings.get("_args_3"));
+        assertEquals(Lambda.function("it.get().vertices(Direction.OUT)"), bindings.get("_args_4"));
+        assertEquals(Lambda.<Traverser<Object>, Integer>function("it.get().value('name').length()"), bindings.get("_args_5"));
+        assertEquals(Lambda.consumer("{ x -> x.sideEffects(\"lengthSum\", x.<Integer>sideEffects('lengthSum') + x.get()) }"), bindings.get("_args_6"));
+        assertEquals(Lambda.comparator("a,b -> a <=> b"), bindings.get("_args_7"));
+        assertEquals(Lambda.biFunction("{ a,b -> a + b }"), bindings.get("_args_8"));
+        assertEquals("g.withStrategies(org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy.instance())" +
+                        ".withSideEffect(_args_0,_args_1).withSack(_args_2)" +
+                        ".V()" +
+                        ".filter(_args_3)" +
+                        ".flatMap(_args_4)" +
+                        ".map(_args_5)" +
+                        ".sideEffect(_args_6)" +
+                        ".order().by(_args_7)" +
+                        ".sack(_args_8)",
+                script.getScript());
+    }
+
+    @Test
+    public void shouldHandleArray() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final Script script = GroovyTranslator.of("g", true).translate(g.V().has(T.id, P.within(new ArrayList() {{
+            add(1);
+            add(2);
+            add(3);
+            add(4);
+            add(5);
+        }})).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(5, bindings.size());
+        assertEquals(Integer.valueOf(1), bindings.get("_args_0"));
+        assertEquals(Integer.valueOf(2), bindings.get("_args_1"));
+        assertEquals(Integer.valueOf(3), bindings.get("_args_2"));
+        assertEquals(Integer.valueOf(4), bindings.get("_args_3"));
+        assertEquals(Integer.valueOf(5), bindings.get("_args_4"));
+        assertEquals("g.V().has(T.id,P.within([_args_0, _args_1, _args_2, _args_3, _args_4]))", script.getScript());
+
+        final Script standard = GroovyTranslator.of("g").translate(g.V().has(T.id, P.within(new ArrayList() {{
+            add(1);
+            add(2);
+            add(3);
+            add(4);
+            add(5);
+        }})).asAdmin().getBytecode());
+
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
+    }
+
+    @Test
+    public void shouldHandleSet() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final Script script = GroovyTranslator.of("g", true).translate(g.V().id().is(new HashSet<Object>() {{
+            add(3);
+            add(Arrays.asList(1, 2, 3.1d));
+            add(3);
+            add("3");
+        }}).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(5, bindings.size());
+        assertEquals(Integer.valueOf(3), bindings.get("_args_0"));
+        assertEquals("3", bindings.get("_args_1"));
+        assertEquals(Integer.valueOf(1), bindings.get("_args_2"));
+        assertEquals(Integer.valueOf(2), bindings.get("_args_3"));
+        assertEquals(Double.valueOf(3.1), bindings.get("_args_4"));
+        assertEquals("g.V().id().is([_args_0, _args_1, [_args_2, _args_3, _args_4]] as Set)", script.getScript());
+
+        final Script standard = GroovyTranslator.of("g" ).translate(g.V().id().is(new HashSet<Object>() {{
+            add(3);
+            add(Arrays.asList(1, 2, 3.1d));
+            add(3);
+            add("3");
+        }}).asAdmin().getBytecode());
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
+    }
+
+    @Test
+    public void shouldHandleMaps() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final Script script = GroovyTranslator.of("g", true).translate(g.V().id().is(new LinkedHashMap<Object,Object>() {{
+            put(3, "32");
+            put(Arrays.asList(1, 2, 3.1d), 4);
+        }}).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(6, bindings.size());
+        assertEquals(Integer.valueOf(3), bindings.get("_args_0"));
+        assertEquals("32", bindings.get("_args_1"));
+        assertEquals(Integer.valueOf(1), bindings.get("_args_2"));
+        assertEquals(Integer.valueOf(2), bindings.get("_args_3"));
+        assertEquals(Double.valueOf(3.1), bindings.get("_args_4"));
+        assertEquals(Integer.valueOf(4), bindings.get("_args_5"));
+        assertEquals("g.V().id().is([(_args_0):(_args_1),([_args_2, _args_3, _args_4]):(_args_5)])", script.getScript());
+        final Script standard = GroovyTranslator.of("g").translate(g.V().id().is(new LinkedHashMap<Object,Object>() {{
+            put(3, "32");
+            put(Arrays.asList(1, 2, 3.1d), 4);
+        }}).asAdmin().getBytecode());
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
+    }
+
+    @Test
+    public void shouldHandleEmptyMaps() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final Function identity = new Lambda.OneArgLambda("it.get()", "gremlin-groovy");
+        final Script script = GroovyTranslator.of("g", true).translate(g.inject(Collections.emptyMap()).map(identity).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(1, bindings.size());
+        assertEquals(identity, bindings.get("_args_0"));
+        assertEquals("g.inject([]).map(_args_0)", script.getScript());
+        bindings.put("g", g);
+        assertThatScriptOk(script.getScript(), bindings);
+    }
+
+    @Test
+    public void shouldHandleDate() {
+        final Calendar c = Calendar.getInstance();
+        c.set(1975, Calendar.SEPTEMBER, 7);
+        final Date d = c.getTime();
+        assertParameterizedTranslation(String.format("new java.util.Date(%s)", d.getTime()), d);
+    }
+
+    @Test
+    public void shouldHandlePredicate() {
+        P p = new P(Compare.eq, 10);
+        assertParameterizedTranslation(String.format("new java.util.Date(%s)", p.toString()), 10);
+    }
+
+    @Test
+    public void shouldHandleTimestamp() {
+        final Calendar c = Calendar.getInstance();
+        c.set(1975, Calendar.SEPTEMBER, 7);
+        final Timestamp t = new Timestamp(c.getTime().getTime());
+        assertParameterizedTranslation(String.format("new java.sql.Timestamp(%s)", t.getTime()), t);
+    }
+
+    @Test
+    public void shouldHandleUuid() {
+        final UUID uuid = UUID.fromString("ffffffff-fd49-1e4b-0000-00000d4b8a1d");
+        assertParameterizedTranslation(String.format("java.util.UUID.fromString('%s')", uuid), uuid);
+    }
+
+    @Test
+    public void shouldHandleClass() {
+        Class cls = Vertex.class;
+        assertParameterizedTranslation(String.format("%s", cls), cls.getCanonicalName());
+    }
+
+    @Test
+    public void shouldHandleBarrier() {
+        SackFunctions.Barrier barrier = SackFunctions.Barrier.normSack;
+        assertNonParameterizedTranslation(String.format("SackFunctions.Barrier.%s", barrier), barrier);
+    }
+
+    @Test
+    public void shouldHandleCardinality() {
+        VertexProperty.Cardinality cardinality = VertexProperty.Cardinality.set;
+        assertNonParameterizedTranslation(String.format("VertexProperty.Cardinality.%s", cardinality), cardinality);
+    }
+
+    @Test
+    public void shouldHandlePick() {
+        TraversalOptionParent.Pick pick = TraversalOptionParent.Pick.any;
+        assertNonParameterizedTranslation(String.format("TraversalOptionParent.Pick.%s", pick), pick);
+    }
+
+    @Test
+    public void shouldHandleColumn() {
+        assertNonParameterizedTranslation("Column.keys", Column.keys);
+    }
+
+    @Test
+    public void shouldHandleDirection() {
+        assertNonParameterizedTranslation("Direction.BOTH", Direction.BOTH);
+    }
+
+    @Test
+    public void shouldHandleOrder() {
+        assertNonParameterizedTranslation("Order.shuffle", Order.shuffle);
+    }
+
+    @Test
+    public void shouldHandlePop() {
+        assertNonParameterizedTranslation("Pop.last", Pop.last);
+    }
+
+    @Test
+    public void shouldHandleScope() {
+        assertNonParameterizedTranslation("Scope.local", Scope.local);
+    }
+
+    @Test
+    public void shouldIncludeCustomTypeTranslationForSomethingSilly() throws Exception {
+        final TinkerGraph graph = TinkerGraph.open();
+        final ParameterizedSillyClass notSillyEnough = ParameterizedSillyClass.from("not silly enough", 100);
+        final GraphTraversalSource g = graph.traversal();
+
+        // without type translation we get uglinesss
+        final Script parameterizedScriptBad = GroovyTranslator.of("g", true).
+                translate(g.inject(notSillyEnough).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        parameterizedScriptBad.getParameters().ifPresent(bindings::putAll);
+        assertEquals(String.format("g.inject(%s)", "_args_0"), parameterizedScriptBad.getScript());
+        assertEquals(1, bindings.size());
+        assertEquals(notSillyEnough, bindings.get("_args_0"));
+        bindings.clear();
+
+        // with type translation we get valid gremlin
+        final Script parameterizedScriptGood = GroovyTranslator.of("g", new ParameterizedSillyClassTranslatorCustomizer().createTypeTranslator()).
+                translate(g.inject(notSillyEnough).asAdmin().getBytecode());
+        parameterizedScriptGood.getParameters().ifPresent(bindings::putAll);
+        assertEquals(2, bindings.size());
+        assertEquals(notSillyEnough.getX(), bindings.get("_args_0"));
+        assertEquals(notSillyEnough.getY(), bindings.get("_args_1"));
+        assertEquals("g.inject(org.apache.tinkerpop.gremlin.groovy.jsr223.ParameterizedGroovyTranslatorTest.ParameterizedSillyClass.from(_args_0,_args_1))", parameterizedScriptGood.getScript());
+        bindings.put("g", g);
+        assertThatScriptOk(parameterizedScriptGood.getScript(), bindings);
+
+        final GremlinGroovyScriptEngine customEngine = new GremlinGroovyScriptEngine(new ParameterizedSillyClassTranslatorCustomizer());
+        final Traversal t = customEngine.eval(g.inject(notSillyEnough).asAdmin().getBytecode(), bindings, "g");
+        final ParameterizedSillyClass sc = (ParameterizedSillyClass) t.next();
+        assertEquals(notSillyEnough.getX(), sc.getX());
+        assertEquals(notSillyEnough.getY(), sc.getY());
+        assertThat(t.hasNext(), is(false));
+    }
+
+    @Test
+    public void shouldHaveValidToString() {
+        assertEquals("translator[h:gremlin-groovy]", GroovyTranslator.of("h", true).toString());
+    }
+
+    @Test
+    public void shouldEscapeStrings() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final Script script = GroovyTranslator.of("g", true).translate(g.addV("customer")
+                .property("customer_id", 501L)
+                .property("name", "Foo\u0020Bar")
+                .property("age", 25)
+                .property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
+                .asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(9, bindings.size());
+        assertEquals("customer", bindings.get("_args_0"));
+        assertEquals("customer_id", bindings.get("_args_1"));
+        assertEquals(Long.valueOf(501), bindings.get("_args_2"));
+        assertEquals("name", bindings.get("_args_3"));
+        assertEquals("Foo\u0020Bar", bindings.get("_args_4"));
+        assertEquals("age", bindings.get("_args_5"));
+        assertEquals(Integer.valueOf(25), bindings.get("_args_6"));
+        assertEquals("special", bindings.get("_args_7"));
+        assertEquals("`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?", bindings.get("_args_8"));
+        assertEquals("g.addV(_args_0).property(_args_1,_args_2).property(_args_3,_args_4).property(_args_5,_args_6).property(_args_7,_args_8)", script.getScript());
+
+        final Script standard = GroovyTranslator.of("g").translate(g.addV("customer")
+                .property("customer_id", 501L)
+                .property("name", "Foo\u0020Bar")
+                .property("age", 25)
+                .property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
+                .asAdmin().getBytecode());
+
+        bindings.put("g", g);
+        //add vertex will return different vertex id
+        assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, false);
+    }
+
+    @Test
+    public void shouldHandleVertexAndEdge() {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+
+        final Object id1 = "customer:10:foo\u0020bar\u0020\u0024100#90"; // customer:10:foo bar $100#90
+        final Vertex vertex1 = DetachedVertex.build().setLabel("customer").setId(id1)
+                .create();
+        final Script script1 = GroovyTranslator.of("g", true).translate(g.inject(vertex1).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script1.getParameters().ifPresent(bindings::putAll);
+        assertEquals(2, bindings.size());
+        assertEquals(id1, bindings.get("_args_0"));
+        assertEquals("customer", bindings.get("_args_1"));
+        assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_0,_args_1, Collections.emptyMap()))", script1.getScript());
+        final Script standard1 = GroovyTranslator.of("g").translate(g.inject(vertex1).asAdmin().getBytecode());
+        bindings.put("g", g);
+        // TinkerGraph not support string id
+        assertParameterizedScriptOk(standard1.getScript(), script1.getScript(), bindings, false);
+        bindings.clear();
+
+        final Object id2 = "user:20:foo\\u0020bar\\u005c\\u0022mr\\u005c\\u0022\\u00241000#50"; // user:20:foo\u0020bar\u005c\u0022mr\u005c\u0022\u00241000#50
+        final Vertex vertex2 = DetachedVertex.build().setLabel("user").setId(id2)
+                .create();
+        final Script script2 = GroovyTranslator.of("g", true).translate(g.inject(vertex2).asAdmin().getBytecode());
+        script2.getParameters().ifPresent(bindings::putAll);
+        assertEquals(2, bindings.size());
+        assertEquals(id2, bindings.get("_args_0"));
+        assertEquals("user", bindings.get("_args_1"));
+        assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_0,_args_1, Collections.emptyMap()))", script2.getScript());
+        final Script standard2 = GroovyTranslator.of("g").translate(g.inject(vertex2).asAdmin().getBytecode());
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard2.getScript(), script2.getScript(), bindings, false);
+        bindings.clear();
+
+        final Object id3 = "knows:30:foo\u0020bar\u0020\u0024100:\\u0020\\u0024500#70";
+        final Edge edge = DetachedEdge.build().setLabel("knows").setId(id3)
+                .setOutV((DetachedVertex) vertex1)
+                .setInV((DetachedVertex) vertex2)
+                .create();
+        final Script script3 = GroovyTranslator.of("g", true).translate(g.inject(edge).asAdmin().getBytecode());
+        script3.getParameters().ifPresent(bindings::putAll);
+        assertEquals(6, bindings.size());
+        assertEquals(id3, bindings.get("_args_0"));
+        assertEquals("knows", bindings.get("_args_1"));
+        assertEquals(id1, bindings.get("_args_2"));
+        assertEquals("customer", bindings.get("_args_3"));
+        assertEquals(id2, bindings.get("_args_4"));
+        assertEquals("user", bindings.get("_args_5"));
+        assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(_args_0,_args_1,Collections.emptyMap(),_args_2,_args_3,_args_4,_args_5))", script3.getScript());
+        final Script standard3 = GroovyTranslator.of("g").translate(g.inject(edge).asAdmin().getBytecode());
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard3.getScript(), script3.getScript(), bindings, false);
+        bindings.clear();
+
+        final Script script4 = GroovyTranslator.of("g", true).translate(
+                g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
+                        .asAdmin().getBytecode());
+        script4.getParameters().ifPresent(bindings::putAll);
+        assertEquals(7, bindings.size());
+        assertEquals("knows", bindings.get("_args_0"));
+        assertEquals(id1, bindings.get("_args_1"));
+        assertEquals("customer", bindings.get("_args_2"));
+        assertEquals(id2, bindings.get("_args_3"));
+        assertEquals("user", bindings.get("_args_4"));
+        assertEquals("when", bindings.get("_args_5"));
+        assertEquals("2018/09/21", bindings.get("_args_6"));
+        assertEquals("g.addE(_args_0).from(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_1,_args_2, Collections.emptyMap())).to(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_3,_args_4, Collections.emptyMap())).property(_args_5,_args_6)", script4.getScript());
+        final Script standard4 = GroovyTranslator.of("g").translate(
+                g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
+                        .asAdmin().getBytecode());
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard4.getScript(), script4.getScript(), bindings, false);
+        bindings.clear();
+
+        final Script script5 = GroovyTranslator.of("g", true).translate(g.V().has("age").asAdmin().getBytecode());
+        script5.getParameters().ifPresent(bindings::putAll);
+        assertEquals(1, bindings.size());
+        assertEquals("age", bindings.get("_args_0"));
+        assertEquals("g.V().has(_args_0)", script5.getScript());
+        final Script standard5 = GroovyTranslator.of("g").translate(g.V().has("age").asAdmin().getBytecode());
+        bindings.put("g", g);
+        // Ok, here we checking all the result
+        assertParameterizedScriptOk(standard5.getScript(), script5.getScript(), bindings, true);
+        bindings.clear();
+    }
+
+    private Object eval(final String s, final Bindings b) throws ScriptException {
+        return parameterizedEngine.eval(s, b);
+    }
+
+    private void assertParameterizedTranslation(final String expectedTranslation, final Object... objs) {
+        final Script script = GroovyTranslator.of("g", true).translate(g.inject(objs).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(1, bindings.size());
+        assertEquals(objs[0], bindings.get("_args_0"));
+        assertEquals(String.format("g.inject(_args_0)", expectedTranslation), script.getScript());
+
+        final Script standard = GroovyTranslator.of("g").translate(g.inject(objs).asAdmin().getBytecode());
+        bindings.put("g", g);
+        assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
+    }
+
+    private void assertNonParameterizedTranslation(final String expectedTranslation, final Object... objs) {
+        final Script script = GroovyTranslator.of("g", true).translate(g.inject(objs).asAdmin().getBytecode());
+        Bindings bindings = new SimpleBindings();
+        script.getParameters().ifPresent(bindings::putAll);
+        assertEquals(0, bindings.size());
+        assertEquals(String.format("g.inject(%s)", expectedTranslation),  script.getScript());
+
+        final Script standard = GroovyTranslator.of("g").translate(g.inject(objs).asAdmin().getBytecode());
+        assertEquals(standard.getScript(), script.getScript());
+    }
+
+    private void assertThatScriptOk(final String s, Bindings bindings) {
+        try {
+            assertNotNull(eval(s, bindings));
+        } catch (ScriptException se) {
+            se.printStackTrace();
+            fail("Script should have eval'd");
+        }
+    }
+
+    private void assertParameterizedScriptOk(final String standardScript, final String checkingScript, final Bindings bindings, final boolean resultChecking) {
+        try {
+            System.out.println(standardScript + " " + checkingScript);
+            assertTrue(!standardScript.equals(checkingScript));
+            assertThatScriptOk(checkingScript, bindings);
+            assertEquals(eval(standardScript, bindings), eval(checkingScript, bindings));
+            if (resultChecking) {
+                Traversal.Admin<Vertex, Object> standardTraversal = (Traversal.Admin) eval(standardScript, bindings);
+                Traversal.Admin<Vertex, Object> checkingTraversal = (Traversal.Admin) eval(checkingScript, bindings);
+                while (standardTraversal.hasNext() && checkingTraversal.hasNext()) {
+                    // assertEquals(standardTraversal.next(), checkingTraversal.next());
+                    System.out.println(standardTraversal.next() +  " " + checkingTraversal.next());
+                }
+                assertEquals(standardTraversal.hasNext(), checkingTraversal.hasNext());
+            }
+        } catch (ScriptException se) {
+            se.printStackTrace();
+            fail("Script should have eval'd");
+        }
+    }
+
+    public static class ParameterizedSillyClass {
+
+        private final String x;
+        private final int y;
+
+        private ParameterizedSillyClass(final String x, final int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        public static ParameterizedSillyClass from(final String x, final int y) {
+            return new ParameterizedSillyClass(x, y);
+        }
+
+        public String getX() {
+            return x;
+        }
+
+        public int getY() {
+            return y;
+        }
+
+        public Object[] getArguments() {
+            return new Object[] {x,y};
+        }
+
+        @Override
+        public String toString() {
+            return String.format("org.apache.tinkerpop.gremlin.groovy.jsr223.ParameterizedGroovyTranslatorTest.ParameterizedSillyClass.from('%s', (int) %s)", getX(), getY());
+        }
+    }
+
+    public static class ParameterizedSillyClassTranslator extends  GroovyTranslator.DefaultTypeTranslator {
+        public ParameterizedSillyClassTranslator(final boolean withParameters) {
+           super(withParameters);
+        }
+
+        @Override
+        protected Script convertToScript(final Object object) {
+            if (object instanceof ParameterizedSillyClass) {
+                ParameterizedSillyClass obj = (ParameterizedSillyClass) object;
+                script.append(obj.getClass().getCanonicalName());
+                if (0 == obj.getArguments().length) {
+                    script.append(".").append("from").append("()");
+                } else {
+                    script.append(".").append("from").append("(");
+                    for (final Object argument: obj.getArguments()) {
+                        convertToScript(argument);
+                        script.append(",");
+                    }
+                    script.setCharAtEnd(')');
+                }
+                return script;
+            } else {
+                return super.convertToScript(object);
+            }
+        }
+    }
+
+    public static class ParameterizedSillyClassTranslatorCustomizer implements TranslatorCustomizer {
+
+        @Override
+        public Translator.ScriptTranslator.TypeTranslator createTypeTranslator() {
+            return new ParameterizedSillyClassTranslator(true);
+        }
+    }
+}
+
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/util/DependencyGrabberIntegrateTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/util/DependencyGrabberIntegrateTest.java
index 850a62f..a0d5549 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/util/DependencyGrabberIntegrateTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/util/DependencyGrabberIntegrateTest.java
@@ -36,7 +36,7 @@
  */
 public class DependencyGrabberIntegrateTest {
     private static final String GROUP_ID = "org.apache.tinkerpop";
-    private static final String VERSION = "3.3.7";
+    private static final String VERSION = "3.3.9";
 
     private static final GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
     private static final File extTestDir = TestHelper.makeTestDataPath(DependencyGrabberIntegrateTest.class);
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java
index 89fdb11..29230bb 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.util;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGraphProvider;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.TestHelper;
diff --git a/gremlin-javascript/glv/GraphTraversalSource.template b/gremlin-javascript/glv/GraphTraversalSource.template
deleted file mode 100644
index 80476f1..0000000
--- a/gremlin-javascript/glv/GraphTraversalSource.template
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  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.
- */
-
-/**
- * @author Jorge Bay Gondra
- */
-'use strict';
-
-const { Traversal } = require('./traversal');
-const remote = require('../driver/remote-connection');
-const utils = require('../utils');
-const Bytecode = require('./bytecode');
-const { TraversalStrategies, VertexProgramStrategy } = require('./traversal-strategy');
-
-
-/**
- * Represents the primary DSL of the Gremlin traversal machine.
- */
-class GraphTraversalSource {
-
-  /**
-   * Creates a new instance of {@link GraphTraversalSource}.
-   * @param {Graph} graph
-   * @param {TraversalStrategies} traversalStrategies
-   * @param {Bytecode} [bytecode]
-   * @param {Function} [graphTraversalSourceClass] Optional {@link GraphTraversalSource} constructor.
-   * @param {Function} [graphTraversalClass] Optional {@link GraphTraversal} constructor.
-   */
-  constructor(graph, traversalStrategies, bytecode, graphTraversalSourceClass, graphTraversalClass) {
-    this.graph = graph;
-    this.traversalStrategies = traversalStrategies;
-    this.bytecode = bytecode || new Bytecode();
-    this.graphTraversalSourceClass = graphTraversalSourceClass || GraphTraversalSource;
-    this.graphTraversalClass = graphTraversalClass || GraphTraversal;
-  }
-
-  /**
-   * @param remoteConnection
-   * @returns {GraphTraversalSource}
-   */
-  withRemote(remoteConnection) {
-    const traversalStrategy = new TraversalStrategies(this.traversalStrategies);
-    traversalStrategy.addStrategy(new remote.RemoteStrategy(remoteConnection));
-    return new this.graphTraversalSourceClass(this.graph, traversalStrategy, new Bytecode(this.bytecode), this.graphTraversalSourceClass, this.graphTraversalClass);
-  }
-
-  /**
-   * @param graphComputer
-   * @param workers
-   * @param result
-   * @param persist
-   * @param vertices
-   * @param edges
-   * @param configuration
-   * @returns {GraphTraversalSource}
-   */
-  withComputer(graphComputer, workers, result, persist, vertices, edges, configuration) {
-    return this.withStrategies(new VertexProgramStrategy(graphComputer, workers, result, persist, vertices, edges, configuration));
-  }
-
-  /**
-   * Returns the string representation of the GraphTraversalSource.
-   * @returns {string}
-   */
-  toString() {
-    return 'graphtraversalsource[' + this.graph.toString() + ']';
-  }
-  <% sourceStepMethods.each{ method -> %>
-  /**
-   * Graph Traversal Source <%= method %> method.
-   * @param {...Object} args
-   * @returns {GraphTraversalSource}
-   */
-  <%= toJs.call(method) %>(...args) {
-    const b = new Bytecode(this.bytecode).addSource('<%= method %>', args);
-    return new this.graphTraversalSourceClass(this.graph, new TraversalStrategies(this.traversalStrategies), b, this.graphTraversalSourceClass, this.graphTraversalClass);
-  }
-  <%
-  }
-  sourceSpawnMethods.each{ method -> %>
-  /**
-   * <%= method %> GraphTraversalSource step method.
-   * @param {...Object} args
-   * @returns {GraphTraversal}
-   */
-  <%= toJs.call(method) %>(...args) {
-    const b = new Bytecode(this.bytecode).addStep('<%= method %>', args);
-    return new this.graphTraversalClass(this.graph, new TraversalStrategies(this.traversalStrategies), b);
-  }
-  <% } %>
-}
-
-/**
- * Represents a graph traversal.
- */
-class GraphTraversal extends Traversal {
-  constructor(graph, traversalStrategies, bytecode) {
-    super(graph, traversalStrategies, bytecode);
-  }
-
-  /**
-   * Copy a traversal so as to reset and re-use it.
-   */
-  clone() {
-    return new GraphTraversal(this.graph, this.traversalStrategies, this.getBytecode());
-  }
-
-  <% graphStepMethods.each{ method -> %>
-  /**
-   * Graph traversal <%= method %> method.
-   * @param {...Object} args
-   * @returns {GraphTraversal}
-   */
-  <%= toJs.call(method) %>(...args) {
-    this.bytecode.addStep('<%= method %>', args);
-    return this;
-  }
-  <% } %>
-}
-
-function callOnEmptyTraversal(fnName, args) {
-  const g = new GraphTraversal(null, null, new Bytecode());
-  return g[fnName].apply(g, args);
-}
-
-/**
- * Contains the static method definitions
- * @type {Object}
- */
-const statics = {<% anonStepMethods.eachWithIndex { method, i -> %>
-  <%= toJs.call(method) %>: (...args) => callOnEmptyTraversal('<%= toJs.call(method) %>', args)<%= i < anonStepMethods.size() - 1 ? "," : ""%><% } %>
-};
-
-module.exports = {
-  GraphTraversal,
-  GraphTraversalSource,
-  statics
-};
\ No newline at end of file
diff --git a/gremlin-javascript/glv/PackageJson.template b/gremlin-javascript/glv/PackageJson.template
deleted file mode 100644
index 4089dc2..0000000
--- a/gremlin-javascript/glv/PackageJson.template
+++ /dev/null
@@ -1,62 +0,0 @@
-<%
-/*
-    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.
-*/
-%>{
-  "name": "gremlin",
-  "version": "<%= version %>",
-  "description": "JavaScript Gremlin Language Variant",
-  "author": "Apache TinkerPop team",
-  "keywords": [
-    "graph",
-    "gremlin",
-    "tinkerpop",
-    "connection",
-    "glv",
-    "driver",
-    "graphdb"
-  ],
-  "license": "Apache-2.0",
-  "dependencies": {
-    "ws": "^6.2.1"
-  },
-  "devDependencies": {
-    "chai": "~4.1.2",
-    "cucumber": "~4.2.1",
-    "grunt": "~1.0.4",
-    "grunt-cli": "~1.3.2",
-    "grunt-jsdoc": "~2.3.1",
-    "mocha": "~5.2.0"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/apache/tinkerpop.git"
-  },
-  "homepage": "https://tinkerpop.apache.org/",
-  "bugs": {
-    "url": "https://issues.apache.org/jira/browse/TINKERPOP"
-  },
-  "scripts": {
-    "test": "./node_modules/mocha/bin/mocha test/unit test/integration -t 5000",
-    "features": "./node_modules/.bin/cucumber-js --require test/cucumber ../../../../../gremlin-test/features/",
-    "unit-test": "./node_modules/mocha/bin/mocha test/unit"
-  },
-  "engines": {
-    "node": ">=6"
-  }
-}
\ No newline at end of file
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
deleted file mode 100644
index 1cae123..0000000
--- a/gremlin-javascript/glv/TraversalSource.template
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *  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.
- */
-
-/**
- * @author Jorge Bay Gondra
- */
-'use strict';
-
-const utils = require('../utils');
-const itemDone = Object.freeze({ value: null, done: true });
-const asyncIteratorSymbol = Symbol.asyncIterator || Symbol('@@asyncIterator');
-
-class Traversal {
-  constructor(graph, traversalStrategies, bytecode) {
-    this.graph = graph;
-    this.traversalStrategies = traversalStrategies;
-    this.bytecode = bytecode;
-    /** @type {Array<Traverser>} */
-    this.traversers = null;
-    this.sideEffects = null;
-    this._traversalStrategiesPromise = null;
-    this._traversersIteratorIndex = 0;
-  }
-
-  /**
-   * Async iterable method implementation.
-   */
-  [asyncIteratorSymbol]() {
-    return this;
-  }
-
-  /** @returns {Bytecode} */
-  getBytecode() {
-    return this.bytecode;
-  }
-
-  /**
-   * Returns an Array containing the traverser objects.
-   * @returns {Promise.<Array>}
-   */
-  toList() {
-    return this._applyStrategies().then(() => {
-      const result = [];
-      let it;
-      while ((it = this._getNext()) && !it.done) {
-        result.push(it.value);
-      }
-      return result;
-    });
-  };
-
-  /**
-   * Determines if there are any more items to iterate from the traversal.
-   * @returns {Promise.<boolean>}
-   */
-   hasNext() {
-     return this._applyStrategies().then(() => {
-       return this.traversers && this.traversers.length > 0 &&
-              this._traversersIteratorIndex < this.traversers.length &&
-              this.traversers[this._traversersIteratorIndex].bulk > 0;
-     });
-   }
-
-  /**
-   * Iterates all Traverser instances in the traversal.
-   * @returns {Promise}
-   */
-  iterate() {
-    this.bytecode.addStep('none');
-    return this._applyStrategies().then(() => {
-      let it;
-      while ((it = this._getNext()) && !it.done) {
-      }
-    });
-  }
-
-  /**
-   * Async iterator method implementation.
-   * Returns a promise containing an iterator item.
-   * @returns {Promise.<{value, done}>}
-   */
-  next() {
-    return this._applyStrategies().then(() => this._getNext());
-  }
-
-  /**
-   * Synchronous iterator of traversers including
-   * @private
-   */
-  _getNext() {
-    while (this.traversers && this._traversersIteratorIndex < this.traversers.length) {
-      let traverser = this.traversers[this._traversersIteratorIndex];
-      if (traverser.bulk > 0) {
-        traverser.bulk--;
-        return { value: traverser.object, done: false };
-      }
-      this._traversersIteratorIndex++;
-    }
-    return itemDone;
-  }
-
-  _applyStrategies() {
-    if (this._traversalStrategiesPromise) {
-      // Apply strategies only once
-      return this._traversalStrategiesPromise;
-    }
-    return this._traversalStrategiesPromise = this.traversalStrategies.applyStrategies(this);
-  }
-
-  /**
-   * Returns the Bytecode JSON representation of the traversal
-   * @returns {String}
-   */
-  toString() {
-    return this.bytecode.toString();
-  };
-}
-
-<% tokens.each { k,v -> %>
-class <%= k %> {
-<% v.each {a,b -> %>
- static get <%= a %>() {
-   return "<%= b %>"
- }
-<% } %>}
-<% } %>
-
-class P {
-  /**
-   * Represents an operation.
-   * @constructor
-   */
-  constructor(operator, value, other) {
-    this.operator = operator;
-    this.value = value;
-    this.other = other;
-  }
-
-  /**
-   * Returns the string representation of the instance.
-   * @returns {string}
-   */
-  toString() {
-    if (this.other === undefined) {
-      return this.operator + '(' + this.value + ')';
-    }
-    return this.operator + '(' + this.value + ', ' + this.other + ')';
-  }
-
-  and(arg) {
-    return new P('and', this, arg);
-  }
-
-  or(arg) {
-    return new P('or', this, arg);
-  }
-
-  static within(...args) {
-    if (args.length === 1 && Array.isArray(args[0])) {
-      return new P("within", args[0], null);
-    } else {
-      return new P("within", args, null);
-    }
-  }
-
-  static without(...args) {
-    if (args.length === 1 && Array.isArray(args[0])) {
-      return new P("without", args[0], null);
-    } else {
-      return new P("without", args, null);
-    }
-  }
-
-<% pmethods.findAll{!(it in ["within","without"])}.each{ method -> %>
-  /** @param {...Object} args */
-  static <%= toJs.call(method) %>(...args) {
-    return createP('<%= method %>', args);
-  }
-<% } %>
-}
-
-function createP(operator, args) {
-  args.unshift(null, operator);
-  return new (Function.prototype.bind.apply(P, args));
-}
-
-class TextP {
-  /**
-   * Represents an operation.
-   * @constructor
-   */
-  constructor(operator, value, other) {
-    this.operator = operator;
-    this.value = value;
-    this.other = other;
-  }
-
-  /**
-   * Returns the string representation of the instance.
-   * @returns {string}
-   */
-  toString() {
-    if (this.other === undefined) {
-      return this.operator + '(' + this.value + ')';
-    }
-    return this.operator + '(' + this.value + ', ' + this.other + ')';
-  }
-
-  and(arg) {
-    return new P('and', this, arg);
-  }
-
-  or(arg) {
-    return new P('or', this, arg);
-  }
-<% tpmethods.each{ method -> %>
-  /** @param {...Object} args */
-  static <%= toJs.call(method) %>(...args) {
-    return createTextP('<%= method %>', args);
-  }
-<% } %>
-}
-
-function createTextP(operator, args) {
-  args.unshift(null, operator);
-  return new (Function.prototype.bind.apply(TextP, args));
-}
-
-class Traverser {
-  constructor(object, bulk) {
-    this.object = object;
-    this.bulk = bulk || 1;
-  }
-}
-
-class TraversalSideEffects {
-
-}
-
-const withOptions = {
-  <%= withOptions.collect { it.name + ": " + it.value }.join(",\n  ")%>
-};
-
-function toEnum(typeName, keys) {
-  const result = {};
-  keys.split(' ').forEach(k => {
-    let jsKey = k;
-    if (jsKey === jsKey.toUpperCase()) {
-      jsKey = jsKey.toLowerCase();
-    }
-    result[jsKey] = new EnumValue(typeName, k);
-  });
-  return result;
-}
-
-class EnumValue {
-  constructor(typeName, elementName) {
-    this.typeName = typeName;
-    this.elementName = elementName;
-  }
-
-  toString() {
-    return this.elementName;
-  }
-}
-
-module.exports = {
-  EnumValue,
-  P,
-  TextP,
-  withOptions,
-  IO,
-  Traversal,
-  TraversalSideEffects,
-  Traverser<%
-enums.each{ enumClass ->
-    out.print ",\n  " + decapitalize.call(enumClass.simpleName) + ": toEnum('" + enumClass.simpleName + "', '" +
-        enumClass.getEnumConstants().sort { a, b -> a.name() <=> b.name() }.collect { toJs.call(it.name()) }.join(' ') + "')"
-}
-%>
-};
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
deleted file mode 100644
index cd3e899..0000000
--- a/gremlin-javascript/glv/generate.groovy
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.
- */
-
-
-import groovy.text.GStringTemplateEngine
-import org.apache.tinkerpop.gremlin.jsr223.CoreImports
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ConnectedComponent
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressure
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPath
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
-import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.TextP
-import org.apache.tinkerpop.gremlin.process.traversal.IO
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
-import java.lang.reflect.Modifier
-
-def toJsMap = ["in": "in_",
-               "from": "from_",
-               "with": "with_"]
-
-def toJs = { symbol -> toJsMap.getOrDefault(symbol, symbol) }
-
-def toJSValue = { type, value ->
-  type == String.class && value != null ? ('"' + value + '"') : value
-}
-
-def decapitalize = {
-    String string = it;
-    if (string == null || string.length() == 0) {
-        return string;
-    }
-    def c = string.toCharArray();
-    c[0] = Character.toLowerCase(c[0]);
-    return new String(c);
-}
-
-def determineVersion = {
-    def env = System.getenv()
-    def mavenVersion = env.containsKey("TP_RELEASE_VERSION") ? env.get("JS_RELEASE_VERSION") : project.version
-    return mavenVersion.replace("-SNAPSHOT", "-alpha1")
-}
-
-def gatherTokensFrom = { tokenClasses ->
-    def m = [:]
-    tokenClasses.each { tc -> m << [(tc.simpleName) : tc.getFields().sort{ a, b -> a.name <=> b.name }.collectEntries{ f -> [(f.name) : f.get(null)]}]}
-    return m
-}
-
-def binding = ["enums": CoreImports.getClassImports()
-        .findAll { Enum.class.isAssignableFrom(it) }
-        .sort { a, b -> a.getSimpleName() <=> b.getSimpleName() },
-               "pmethods": P.class.getMethods().
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { P.class.isAssignableFrom(it.returnType) }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "tpmethods": TextP.class.getMethods().
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { TextP.class.isAssignableFrom(it.returnType) }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS
-                       findAll { GraphTraversalSource.class.equals(it.returnType) }.
-                       findAll {
-                           !it.name.equals("clone") &&
-                                   // Use hardcoded name to be for forward-compatibility
-                                   !it.name.equals("withBindings") &&
-                                   !it.name.equals(TraversalSource.Symbols.withRemote) &&
-                                   !it.name.equals(TraversalSource.Symbols.withComputer)
-                       }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS
-                       findAll { GraphTraversal.class.equals(it.returnType) }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "graphStepMethods": GraphTraversal.getMethods().
-                       findAll { GraphTraversal.class.equals(it.returnType) }.
-                       findAll { !it.name.equals("clone") && !it.name.equals("iterate") }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "anonStepMethods": __.class.getMethods().
-                       findAll { GraphTraversal.class.equals(it.returnType) }.
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { !it.name.equals("__") && !it.name.equals("start") }.
-                       collect { it.name }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
-               "toJs": toJs,
-               "version": determineVersion(),
-               "decapitalize": decapitalize,
-               "withOptions": WithOptions.getDeclaredFields().
-                        collect {["name": it.name, "value": toJSValue(it.type, it.get(null))]}]
-
-def engine = new GStringTemplateEngine()
-def graphTraversalTemplate = engine.createTemplate(new File("${project.basedir}/glv/GraphTraversalSource.template"))
-        .make(binding)
-def graphTraversalFile =
-        new File("${project.basedir}/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js")
-graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate }
-
-def traversalTemplate = engine.createTemplate(new File("${project.basedir}/glv/TraversalSource.template")).make(binding)
-def traversalFile = new File("${project.basedir}/src/main/javascript/gremlin-javascript/lib/process/traversal.js")
-traversalFile.newWriter().withWriter{ it << traversalTemplate }
-
-def packageJsonTemplate = engine.createTemplate(new File("${project.basedir}/glv/PackageJson.template")).make(binding)
-def packageJsonFile = new File("${project.basedir}/src/main/javascript/gremlin-javascript/package.json")
-packageJsonFile.newWriter().withWriter{ it << packageJsonTemplate }
diff --git a/gremlin-javascript/pom.xml b/gremlin-javascript/pom.xml
index 98ffbd1..2e8b355 100644
--- a/gremlin-javascript/pom.xml
+++ b/gremlin-javascript/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-javascript</artifactId>
     <name>Apache TinkerPop :: Gremlin Javascript</name>
@@ -29,10 +29,21 @@
         <maven.test.skip>false</maven.test.skip>
         <skipTests>${maven.test.skip}</skipTests>
         <gremlin.server.dir>${project.parent.basedir}/gremlin-server</gremlin.server.dir>
+        <npm.version>6.14.6</npm.version>
+        <node.version>v10.22.0</node.version>
     </properties>
     <build>
         <directory>${basedir}/target</directory>
         <finalName>${project.artifactId}-${project.version}</finalName>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>com.github.eirslett</groupId>
+                    <artifactId>frontend-maven-plugin</artifactId>
+                    <version>1.10.0</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
         <plugins>
             <plugin>
                 <!--
@@ -49,6 +60,11 @@
                         <version>${project.version}</version>
                     </dependency>
                     <dependency>
+                        <groupId>org.apache.tinkerpop</groupId>
+                        <artifactId>gremlin-test</artifactId>
+                        <version>${project.version}</version>
+                    </dependency>
+                    <dependency>
                         <groupId>log4j</groupId>
                         <artifactId>log4j</artifactId>
                         <version>${log4j.version}</version>
@@ -64,24 +80,19 @@
                 </dependencies>
                 <executions>
                     <execution>
-                        <id>generate-javascript</id>
+                        <id>update-version</id>
                         <phase>generate-sources</phase>
                         <goals>
                             <goal>execute</goal>
                         </goals>
                         <configuration>
-                            <properties>
-                                <property>
-                                    <name>projectBaseDir</name>
-                                    <value>${project.basedir}</value>
-                                </property>
-                                <property>
-                                    <name>projectVersion</name>
-                                    <value>${project.version}</value>
-                                </property>
-                            </properties>
                             <scripts>
-                                <script>${project.basedir}/glv/generate.groovy</script>
+                                <script>
+def mavenVersion = "${project.version}"
+def versionForJs = mavenVersion.replace("-SNAPSHOT", "-alpha1")
+def file = new File("${project.basedir}/src/main/javascript/gremlin-javascript/package.json")
+file.write(file.getText("UTF-8").replaceFirst(/"version": "(.*)",/, "\"version\": \"" + versionForJs + "\","))
+                                </script>
                             </scripts>
                         </configuration>
                     </execution>
@@ -98,10 +109,6 @@
                                     <value>${skipTests}</value>
                                 </property>
                                 <property>
-                                    <name>python</name>
-                                    <value>false</value>
-                                </property>
-                                <property>
                                     <name>gremlinServerDir</name>
                                     <value>${gremlin.server.dir}</value>
                                 </property>
@@ -161,7 +168,6 @@
             <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
-                <version>1.7.6</version>
                 <executions>
                     <execution>
                         <id>install node and npm</id>
@@ -217,7 +223,8 @@
                 </executions>
                 <configuration>
                     <workingDirectory>src/main/javascript/gremlin-javascript</workingDirectory>
-                    <nodeVersion>v6.12.3</nodeVersion>
+                    <nodeVersion>${node.version}</nodeVersion>
+                    <npmVersion>${npm.version}</npmVersion>
                 </configuration>
             </plugin>
             <!--
@@ -273,7 +280,6 @@
                     <plugin>
                         <groupId>com.github.eirslett</groupId>
                         <artifactId>frontend-maven-plugin</artifactId>
-                        <version>1.4</version>
                         <executions>
                             <execution>
                                 <id>npm publish</id>
@@ -294,7 +300,8 @@
                             -->
                             <skip>false</skip>
                             <workingDirectory>src/main/javascript/gremlin-javascript</workingDirectory>
-                            <nodeVersion>v6.12.3</nodeVersion>
+                            <nodeVersion>${node.version}</nodeVersion>
+                            <npmVersion>${npm.version}</npmVersion>
                         </configuration>
                     </plugin>
                 </plugins>
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js
index eaa9db1..262a96b 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js
@@ -69,17 +69,18 @@
    * Send a request to the Gremlin Server, can send a script or bytecode steps.
    * @param {Bytecode|string} message The bytecode or script to send
    * @param {Object} [bindings] The script bindings, if any.
+   * @param {Object} [extraArgs] The extra arguments, if any.
    * @returns {Promise}
    */
-  submit(message, bindings) {
+  submit(message, bindings, extraArgs) {
     if (typeof message === 'string') {
-      const args = {
+      const args = Object.assign({}, extraArgs, {
         'gremlin': message,
         'bindings': bindings,
         'language': 'gremlin-groovy',
         'accept': this._connection.mimeType,
         'aliases': { 'g': this._options.traversalSource || 'g' }
-      };
+      });
       if (this._options.session && this._options.processor === 'session') {
         args['session'] = this._options.session;
       }
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/bytecode.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/bytecode.js
index e7fdd40..4c0e94c 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/bytecode.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/bytecode.js
@@ -22,6 +22,8 @@
  */
 'use strict';
 
+const { Traversal } = require('./traversal');
+
 class Bytecode {
   /**
    * Creates a new instance of Bytecode
@@ -76,7 +78,11 @@
     const instruction = new Array(length);
     instruction[0] = name;
     for (let i = 1; i < length; i++) {
-      instruction[i] = values[i - 1];
+      const val = values[i - 1];
+      if (val instanceof Traversal && val.graph != null)
+        throw new Error("The child traversal of ${val} was not spawned anonymously - use " +
+            "the __ class rather than a TraversalSource to construct the child traversal");
+      instruction[i] = val;
     }
     return instruction;
   }
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index 9062433..254bf74 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -468,7 +468,7 @@
   graphSONVersion: toEnum('GraphSONVersion', 'V1_0 V2_0 V3_0'),
   gryoVersion: toEnum('GryoVersion', 'V1_0 V3_0'),
   operator: toEnum('Operator', 'addAll and assign div max min minus mult or sum sumLong'),
-  order: toEnum('Order', 'asc decr desc incr shuffle'),
+  order: toEnum('Order', 'asc desc shuffle'),
   pick: toEnum('Pick', 'any none'),
   pop: toEnum('Pop', 'all first last mixed'),
   scope: toEnum('Scope', 'global local'),
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
index b67708a..cf24a9b 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
@@ -1,6 +1,6 @@
 {
   "name": "gremlin",
-  "version": "3.4.9-alpha1",
+  "version": "3.5.0-alpha1",
   "description": "JavaScript Gremlin Language Variant",
   "author": "Apache TinkerPop team",
   "keywords": [
@@ -19,9 +19,9 @@
   "devDependencies": {
     "chai": "~4.1.2",
     "cucumber": "~4.2.1",
-    "grunt": "~1.0.4",
+    "grunt": "~1.2.0",
     "grunt-cli": "~1.3.2",
-    "grunt-jsdoc": "~2.3.1",
+    "grunt-jsdoc": "~2.4.1",
     "mocha": "~5.2.0"
   },
   "repository": {
@@ -38,6 +38,6 @@
     "unit-test": "./node_modules/mocha/bin/mocha test/unit"
   },
   "engines": {
-    "node": ">=6"
+    "node": ">=10"
   }
-}
\ No newline at end of file
+}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 5193ec7..768b366 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -58,6 +58,7 @@
 ].map(x => [ new RegExp('^' + x[0] + '$'), x[1] ]);
 
 const ignoreReason = {
+  nullKeysInMapNotSupportedWell: "Javascript does not nicely support 'null' as a key in Map instances",
   setNotSupported: "There is no Set support in gremlin-javascript",
   needsFurtherInvestigation: '',
 };
@@ -66,6 +67,7 @@
   // An associative array containing the scenario name as key, for example:
   'g_withSideEffectXa_setX_V_both_name_storeXaX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
   'g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
+  'g_V_group_byXageX': new IgnoreError(ignoreReason.nullKeysInMapNotSupportedWell),
   'g_V_shortestPath_edgesIncluded': new IgnoreError(ignoreReason.needsFurtherInvestigation),
   'g_V_shortestPath_edgesIncluded_edgesXoutEX': new IgnoreError(ignoreReason.needsFurtherInvestigation)
 };
@@ -223,6 +225,10 @@
 }
 
 function parseValue(stringValue) {
+
+  if(stringValue === "null")
+    return null;
+
   let extractedValue = null;
   let parser = null;
   for (let item of parsers) {
@@ -234,6 +240,7 @@
       break;
     }
   }
+
   return parser !== null ? parser.call(this, extractedValue) : stringValue;
 }
 
@@ -279,7 +286,7 @@
 }
 
 function toDirection(value) {
-    return direction[value.toLowerCase()];
+  return direction[value.toLowerCase()];
 }
 
 function toArray(stringList) {
@@ -294,6 +301,9 @@
 }
 
 function parseMapValue(value) {
+  if (value === null)
+    return null;
+
   if (typeof value === 'string') {
     return parseValue.call(this, value);
   }
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js
index 956a01a..a86409f 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js
@@ -55,4 +55,20 @@
     customClient._connection = connectionMock;
     customClient.submit(query)
   });
+
+  it('should allow to submit extra arguments', function () {
+    const connectionMock = {
+      submit: function (bytecode, op, args, requestId, processor) {
+        assert.strictEqual(args.gremlin, query);
+        assert.strictEqual(args.scriptEvaluationTimeout, 123);
+        assert.strictEqual(processor, customOpProcessor);
+
+        return Promise.resolve();
+      }
+    };
+
+    const customClient = new Client('ws://localhost:9321', {traversalSource: 'g', processor: customOpProcessor});
+    customClient._connection = connectionMock;
+    customClient.submit(query, null, {"scriptEvaluationTimeout": 123})
+  });
 });
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphson-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphson-test.js
index f355fb5..2942d01 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphson-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphson-test.js
@@ -32,6 +32,11 @@
 const P = t.P;
 
 describe('GraphSONReader', function () {
+  it('should parse GraphSON null', function () {
+    const reader = new GraphSONReader();
+    const result = reader.read(null);
+    assert.equal(result, null);
+  });
   it('should parse GraphSON int32, float and double to Number from GraphSON', function () {
     const reader = new GraphSONReader();
     [
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/translator-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/translator-test.js
index 91c903e..9f42cd1 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/translator-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/translator-test.js
@@ -55,9 +55,9 @@
 
     it('should produce valid script representation from bytecode glv steps containing enum', function () {
       const g = new graph.Graph().traversal();
-      const script = new Translator('g').translate(g.V().order().by('age', t.order.decr).getBytecode());
+      const script = new Translator('g').translate(g.V().order().by('age', t.order.shuffle).getBytecode());
       assert.ok(script);
-      assert.strictEqual(script, 'g.V().order().by(\'age\', decr)');
+      assert.strictEqual(script, 'g.V().order().by(\'age\', shuffle)');
     });
 
     it('should produce valid script representation from bytecode glv steps containing a predicate', function () {
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js
index acdcdd4..22ebf17 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js
@@ -25,7 +25,10 @@
 const assert = require('assert');
 const expect = require('chai').expect;
 const graph = require('../../lib/structure/graph');
+const anon = require('../../lib/process/anonymous-traversal');
 const t = require('../../lib/process/traversal');
+const gt = require('../../lib/process/graph-traversal');
+const V = gt.statics.V;
 const Bytecode = require('../../lib/process/bytecode');
 const TraversalStrategies = require('../../lib/process/traversal-strategy').TraversalStrategies;
 
@@ -33,7 +36,7 @@
 
   describe('#getByteCode()', function () {
     it('should add steps for with a string parameter', function () {
-      const g = new graph.Graph().traversal();
+      const g = anon.traversal().withGraph(new graph.Graph());
       const bytecode = g.V().out('created').getBytecode();
       assert.ok(bytecode);
       assert.strictEqual(bytecode.sourceInstructions.length, 0);
@@ -44,7 +47,7 @@
     });
 
     it('should add steps with an enum value', function () {
-      const g = new graph.Graph().traversal();
+      const g = anon.traversal().withGraph(new graph.Graph());
       const bytecode = g.V().order().by('age', t.order.desc).getBytecode();
       assert.ok(bytecode);
       assert.strictEqual(bytecode.sourceInstructions.length, 0);
@@ -237,4 +240,17 @@
       });
     });
   });
+
+  describe("build", function() {
+    it('should only allow anonymous child traversals', function() {
+      const g = anon.traversal().withGraph(new graph.Graph());
+      assert.doesNotThrow(function() {
+        g.V(0).addE("self").to(V(1))
+      });
+
+      assert.throws(function() {
+        g.V(0).addE("self").to(g.V(1))
+      });
+    })
+  });
 });
\ No newline at end of file
diff --git a/gremlin-python/glv/GraphTraversalSource.template b/gremlin-python/glv/GraphTraversalSource.template
deleted file mode 100644
index 27d9e15..0000000
--- a/gremlin-python/glv/GraphTraversalSource.template
+++ /dev/null
@@ -1,206 +0,0 @@
-#
-# 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.
-#
-
-import sys
-import copy
-from .traversal import Traversal
-from .traversal import TraversalStrategies
-from .strategies import VertexProgramStrategy
-from .traversal import Bytecode
-from ..driver.remote_connection import RemoteStrategy
-from .. import statics
-from ..statics import long
-
-
-class GraphTraversalSource(object):
-    def __init__(self, graph, traversal_strategies, bytecode=None):
-        self.graph = graph
-        self.traversal_strategies = traversal_strategies
-        if bytecode is None:
-          bytecode = Bytecode()
-        self.bytecode = bytecode
-        self.graph_traversal = GraphTraversal
-
-    def __repr__(self):
-        return "graphtraversalsource[" + str(self.graph) + "]"
-
-    def get_graph_traversal_source(self):
-        return self.__class__(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
-
-    def get_graph_traversal(self):
-        return self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-<% sourceStepMethods.each{ method -> %>
-    def <%= method %>(self, *args):
-        source = self.get_graph_traversal_source()
-        source.bytecode.add_source("<%= toJava.call(method) %>", *args)
-        return source
-<% } %>
-    def withRemote(self, remote_connection):
-        source = self.get_graph_traversal_source()
-        source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
-        return source
-
-    def withComputer(self, graph_computer=None, workers=None, result=None, persist=None, vertices=None,
-                     edges=None, configuration=None):
-        return self.withStrategies(VertexProgramStrategy(graph_computer, workers, result, persist, vertices,
-                                   edges, configuration))
-<% sourceSpawnMethods.each { method -> %>
-    def <%= method %>(self, *args):
-        traversal = self.get_graph_traversal()
-        traversal.bytecode.add_step("<%= toJava.call(method) %>", *args)
-        return traversal
-<% } %>
-
-class GraphTraversal(Traversal):
-    def __init__(self, graph, traversal_strategies, bytecode):
-        super(GraphTraversal, self).__init__(graph, traversal_strategies, bytecode)
-
-    def __getitem__(self, index):
-        if isinstance(index, int):
-            return self.range(long(index), long(index + 1))
-        elif isinstance(index, slice):
-            low = long(0) if index.start is None else long(index.start)
-            high = long(sys.maxsize) if index.stop is None else long(index.stop)
-            if low == long(0):
-                return self.limit(high)
-            else:
-                return self.range(low,high)
-        else:
-            raise TypeError("Index must be int or slice")
-
-    def __getattr__(self, key):
-        return self.values(key)
-
-    def clone(self):
-        return GraphTraversal(self.graph, self.traversal_strategies, copy.deepcopy(self.bytecode))
-<% graphStepMethods.each { method -> %>
-    def <%= method %>(self, *args):
-        self.bytecode.add_step("<%= toJava.call(method) %>", *args)
-        return self
-<% } %>
-    # Deprecated - prefer the underscore suffixed versions e.g filter_()
-
-    def filter(self, *args):
-        self.bytecode.add_step("filter", *args)
-        return self
-
-    def id(self, *args):
-        self.bytecode.add_step("id", *args)
-        return self
-
-    def max(self, *args):
-        self.bytecode.add_step("max", *args)
-        return self
-
-    def min(self, *args):
-        self.bytecode.add_step("min", *args)
-        return self
-
-    def range(self, *args):
-        self.bytecode.add_step("range", *args)
-        return self
-
-    def sum(self, *args):
-        self.bytecode.add_step("sum", *args)
-        return self
-
-
-class __(object):
-    graph_traversal = GraphTraversal
-
-    @classmethod
-    def start(cls):
-        return GraphTraversal(None, None, Bytecode())
-
-    @classmethod
-    def __(cls, *args):
-        return __.inject(*args)
-<% anonStepMethods.each{ method -> %>
-    @classmethod
-    def <%= method %>(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).<%= method %>(*args)
-<% } %>
-    # Deprecated - prefer the underscore suffixed versions e.g filter_()
-
-    @classmethod
-    def filter(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).filter_(*args)
-
-    @classmethod
-    def id(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).id_(*args)
-
-    @classmethod
-    def max(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).max_(*args)
-
-    @classmethod
-    def min(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).min_(*args)
-
-    @classmethod
-    def range(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).range_(*args)
-
-    @classmethod
-    def sum(cls, *args):
-        return cls.graph_traversal(None, None, Bytecode()).sum_(*args)
-
-<% anonStepMethods.each{ method -> %>
-def <%= method %>(*args):
-    return __.<%= method %>(*args)
-
-<% } %>
-# Deprecated - prefer the underscore suffixed versions e.g filter_()
-
-def filter(*args):
-    return __.filter_(*args)
-
-
-def id(*args):
-    return __.id_(*args)
-
-
-def max(*args):
-    return __.max_(*args)
-
-
-def min(*args):
-    return __.min_(*args)
-
-
-def range(*args):
-    return __.range_(*args)
-
-
-def sum(*args):
-    return __.sum_(*args)
-
-
-<% anonStepMethods.each{ method -> %>statics.add_static('<%= method %>', <%= method %>)
-
-<% } %>
-# Deprecated - prefer the underscore suffixed versions e.g filter_()
-
-statics.add_static('filter', filter)
-statics.add_static('id', id)
-statics.add_static('max', max)
-statics.add_static('min', min)
-statics.add_static('range', range)
-statics.add_static('sum', sum)
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
deleted file mode 100644
index 3b7ee72..0000000
--- a/gremlin-python/glv/TraversalSource.template
+++ /dev/null
@@ -1,434 +0,0 @@
-#
-# 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.
-#
-
-import copy
-from aenum import Enum
-from .. import statics
-from ..statics import long
-
-class Traversal(object):
-    def __init__(self, graph, traversal_strategies, bytecode):
-        self.graph = graph
-        self.traversal_strategies = traversal_strategies
-        self.bytecode = bytecode
-        self.side_effects = TraversalSideEffects()
-        self.traversers = None
-        self.last_traverser = None
-
-    def __repr__(self):
-        return str(self.bytecode)
-
-    def __eq__(self, other):
-        if isinstance(other, self.__class__):
-            return self.bytecode == other.bytecode
-        else:
-            return False
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        if self.traversers is None:
-            self.traversal_strategies.apply_strategies(self)
-        if self.last_traverser is None:
-            self.last_traverser = next(self.traversers)
-        object = self.last_traverser.object
-        self.last_traverser.bulk = self.last_traverser.bulk - 1
-        if self.last_traverser.bulk <= 0:
-            self.last_traverser = None
-        return object
-
-    def toList(self):
-        return list(iter(self))
-
-    def toSet(self):
-        return set(iter(self))
-
-    def iterate(self):
-        self.bytecode.add_step("none")
-        while True:
-            try: self.nextTraverser()
-            except StopIteration: return self
-
-    def nextTraverser(self):
-        if self.traversers is None:
-            self.traversal_strategies.apply_strategies(self)
-        if self.last_traverser is None:
-            return next(self.traversers)
-        else:
-            temp = self.last_traverser
-            self.last_traverser = None
-            return temp
-
-    def hasNext(self):
-        if self.traversers is None:
-            self.traversal_strategies.apply_strategies(self)
-        if self.last_traverser is None:
-            try: self.last_traverser = next(self.traversers)
-            except StopIteration: return False
-        return not(self.last_traverser is None) and self.last_traverser.bulk > 0
-
-    def next(self, amount=None):
-        if amount is None:
-            return self.__next__()
-        else:
-            count = 0
-            tempList = []
-            while count < amount:
-                count = count + 1
-                try: temp = self.__next__()
-                except StopIteration: return tempList
-                tempList.append(temp)
-            return tempList
-
-    def promise(self, cb=None):
-        self.traversal_strategies.apply_async_strategies(self)
-        future_traversal = self.remote_results
-        future = type(future_traversal)()
-        def process(f):
-            try:
-                traversal = f.result()
-            except Exception as e:
-                future.set_exception(e)
-            else:
-                self.traversers = iter(traversal.traversers)
-                self.side_effects = traversal.side_effects
-                if cb:
-                    try:
-                        result = cb(self)
-                    except Exception as e:
-                        future.set_exception(e)
-                    else:
-                        future.set_result(result)
-                else:
-                    future.set_result(self)
-        future_traversal.add_done_callback(process)
-        return future
-
-<% enums.each { e -> %>
-<%= e.getSimpleName() %> = Enum('<%= e.getSimpleName() %>', ' <%= e.getEnumConstants().sort{a, b -> a.name() <=> b.name()}.collect{v -> toPython.call(v.name())}.join(" ") %>')
-<% e.getEnumConstants().each {v -> %>
-statics.add_static('<%= toPython.call(v.name()) %>', <%= v.getDeclaringClass().getSimpleName() %>.<%= toPython.call(v.name()) %>)<% } %>
-<% } %>
-
-T = Enum('T', ' id id_ key label value')
-
-statics.add_static('id', T.id)
-statics.add_static('label', T.label)
-statics.add_static('id_', T.id_)
-statics.add_static('key', T.key)
-statics.add_static('value', T.value)
-
-
-Operator = Enum('Operator', ' addAll and_ assign div max max_ min min_ minus mult or_ sum sum_ sumLong')
-
-statics.add_static('sum_', Operator.sum_)
-statics.add_static('sum', Operator.sum_)
-statics.add_static('minus', Operator.minus)
-statics.add_static('mult', Operator.mult)
-statics.add_static('div', Operator.div)
-statics.add_static('min', Operator.min_)
-statics.add_static('min_', Operator.min_)
-statics.add_static('max_', Operator.max_)
-statics.add_static('assign', Operator.assign)
-statics.add_static('and_', Operator.and_)
-statics.add_static('or_', Operator.or_)
-statics.add_static('addAll', Operator.addAll)
-statics.add_static('sumLong', Operator.sumLong)
-
-
-class P(object):
-    def __init__(self, operator, value, other=None):
-        self.operator = operator
-        self.value = value
-        self.other = other
-<% pmethods.findAll{!(it in ["within","without"])}.each { method -> %>
-    @staticmethod
-    def <%= method %>(*args):
-        return P("<%= toJava.call(method) %>", *args)
-<% } %>
-    @staticmethod
-    def within(*args):
-        if len(args) == 1 and type(args[0]) == list:
-            return P("within", args[0])
-        else:
-            return P("within", list(args))
-        
-    @staticmethod
-    def without(*args):
-        if len(args) == 1 and type(args[0]) == list:
-            return P("without", args[0])
-        else:
-            return P("without", list(args))
-
-    def and_(self, arg):
-        return P("and", self, arg)
-
-    def or_(self, arg):
-        return P("or", self, arg)
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
-
-    def __repr__(self):
-        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
-
-<% pmethods.findAll{!it.equals("clone")}.each { method -> %>
-def <%= method %>(*args):
-    return P.<%= method %>(*args)
-
-<% } %>
-<% pmethods.findAll{!it.equals("clone")}.each { method -> %>statics.add_static('<%= method %>', <%= method %>)
-
-<% } %>
-class TextP(P):
-    def __init__(self, operator, value, other=None):
-        P.__init__(self, operator, value, other)
-<% tpmethods.each { method -> %>
-    @staticmethod
-    def <%= method %>(*args):
-        return TextP("<%= toJava.call(method) %>", *args)
-<% } %>
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
-
-    def __repr__(self):
-        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
-
-<% tpmethods.findAll{!it.equals("clone")}.each { method -> %>
-def <%= method %>(*args):
-    return TextP.<%= method %>(*args)
-
-<% } %>
-<% tpmethods.findAll{!it.equals("clone")}.each { method -> %>statics.add_static('<%= method %>', <%= method %>)
-
-<% } %>
-<% tokens.each { k,v -> %>
-
-'''
-<%= k %>
-'''
-
-
-class <%= k %>(object):
-<% v.each {a,b -> %>
-    <%= a %> = "<%= b %>"
-<% }} %>
-
-'''
-TRAVERSER
-'''
-
-
-class Traverser(object):
-    def __init__(self, object, bulk=None):
-        if bulk is None:
-            bulk = long(1)
-        self.object = object
-        self.bulk = bulk
-
-    def __repr__(self):
-        return str(self.object)
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.object == other.object
-
-
-'''
-TRAVERSAL SIDE-EFFECTS
-'''
-
-
-class TraversalSideEffects(object):
-    def keys(self):
-        return set()
-
-    def get(self, key):
-        raise KeyError(key)
-
-    def __getitem__(self, key):
-        return self.get(key)
-
-    def __repr__(self):
-        return "sideEffects[size:" + str(len(self.keys())) + "]"
-
-
-'''
-TRAVERSAL STRATEGIES
-'''
-
-
-class TraversalStrategies(object):
-    global_cache = {}
-
-    def __init__(self, traversal_strategies=None):
-        self.traversal_strategies = \
-            traversal_strategies.traversal_strategies if traversal_strategies is not None else []
-
-    def add_strategies(self, traversal_strategies):
-        self.traversal_strategies = self.traversal_strategies + traversal_strategies
-
-    def apply_strategies(self, traversal):
-        for traversal_strategy in self.traversal_strategies:
-            traversal_strategy.apply(traversal)
-
-    def apply_async_strategies(self, traversal):
-        for traversal_strategy in self.traversal_strategies:
-            traversal_strategy.apply_async(traversal)
-
-    def __repr__(self):
-        return str(self.traversal_strategies)
-
-
-class TraversalStrategy(object):
-    def __init__(self, strategy_name=None, configuration=None, fqcn=None):
-        self.fqcn = fqcn
-        self.strategy_name = type(self).__name__ if strategy_name is None else strategy_name
-        self.configuration = {} if configuration is None else configuration
-
-    def apply(self, traversal):
-        return
-
-    def apply_async(self, traversal):
-        return
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__)
-
-    def __hash__(self):
-        return hash(self.strategy_name)
-
-    def __repr__(self):
-        return self.strategy_name
-
-
-'''
-BYTECODE
-'''
-
-
-class Bytecode(object):
-    def __init__(self, bytecode=None):
-        self.source_instructions = []
-        self.step_instructions = []
-        self.bindings = {}
-        if bytecode is not None:
-            self.source_instructions = list(bytecode.source_instructions)
-            self.step_instructions = list(bytecode.step_instructions)
-
-    def add_source(self, source_name, *args):
-        instruction = [source_name]
-        for arg in args:
-            instruction.append(self.__convertArgument(arg))
-        self.source_instructions.append(instruction)
-
-    def add_step(self, step_name, *args):
-        instruction = [step_name]
-        for arg in args:
-            instruction.append(self.__convertArgument(arg))
-        self.step_instructions.append(instruction)
-
-    def __eq__(self, other):
-        if isinstance(other, self.__class__):
-            return self.source_instructions == other.source_instructions and self.step_instructions == other.step_instructions
-        else:
-            return False
-
-    def __copy__(self):
-        bb = Bytecode()
-        bb.source_instructions = self.source_instructions
-        bb.step_instructions = self.step_instructions
-        bb.bindings = self.bindings
-        return bb
-
-    def __deepcopy__(self, memo={}):
-        bb = Bytecode()
-        bb.source_instructions = copy.deepcopy(self.source_instructions, memo)
-        bb.step_instructions = copy.deepcopy(self.step_instructions, memo)
-        bb.bindings = copy.deepcopy(self.bindings, memo)
-        return bb
-
-    def __convertArgument(self,arg):
-        if isinstance(arg, Traversal):
-            self.bindings.update(arg.bytecode.bindings)
-            return arg.bytecode
-        elif isinstance(arg, dict):
-            newDict = {}
-            for key in arg:
-                newDict[self.__convertArgument(key)] = self.__convertArgument(arg[key])
-            return newDict
-        elif isinstance(arg, list):
-            newList = []
-            for item in arg:
-                newList.append(self.__convertArgument(item))
-            return newList
-        elif isinstance(arg, set):
-            newSet = set()
-            for item in arg:
-                newSet.add(self.__convertArgument(item))
-            return newSet
-        elif isinstance(arg, Binding):
-            self.bindings[arg.key] = arg.value
-            return Binding(arg.key, self.__convertArgument(arg.value))
-        else:
-            return arg
-
-    def __repr__(self):
-        return (str(self.source_instructions) if len(self.source_instructions) > 0 else "") + \\
-               (str(self.step_instructions) if len(self.step_instructions) > 0 else "")
-
-
-'''
-BINDINGS
-'''
-
-
-class Bindings(object):
-
-    @staticmethod
-    def of(key, value):
-        if not isinstance(key, str):
-            raise TypeError("Key must be str")
-        return Binding(key, value)
-
-
-class Binding(object):
-    def __init__(self, key, value):
-        self.key = key
-        self.value = value
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value
-
-    def __hash__(self):
-        return hash(self.key) + hash(self.value)
-
-    def __repr__(self):
-        return "binding[" + self.key + "=" + str(self.value) + "]"
-
-
-'''
-WITH OPTIONS
-'''
-
-
-class WithOptions(object):
-<% withOptions.each { %>
-    <%= it.name %> = <%= it.value %>
-<% } %>
diff --git a/gremlin-python/glv/generate.groovy b/gremlin-python/glv/generate.groovy
deleted file mode 100644
index 5011a40..0000000
--- a/gremlin-python/glv/generate.groovy
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.
- */
-
-import org.apache.tinkerpop.gremlin.jsr223.CoreImports
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ConnectedComponent
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressure
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPath
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
-import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.TextP
-import org.apache.tinkerpop.gremlin.process.traversal.IO
-import org.apache.tinkerpop.gremlin.process.traversal.Operator
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
-import org.apache.tinkerpop.gremlin.structure.T
-import java.lang.reflect.Modifier
-
-// this is a bit of a copy of what's in SymbolHelper - no way around it because this code generation task occurs
-// before the SymbolHelper is available to the plugin.
-def toPythonMap = ["and": "and_",
-                   "all": "all_",
-                   "as": "as_",
-                   "filter": "filter_",
-                   "from": "from_",
-                   "global": "global_",
-                   "id": "id_",
-                   "in": "in_",
-                   "is": "is_",
-                   "list": "list_",
-                   "max": "max_",
-                   "min": "min_",
-                   "not": "not_",
-                   "range": "range_",
-                   "or": "or_",
-                   "set": "set_",
-                   "sum": "sum_",
-                   "with": "with_"]
-
-def gatherTokensFrom = { tokenClasses ->
-    def m = [:]
-    tokenClasses.each { tc -> m << [(tc.simpleName) : tc.getFields().sort{ a, b -> a.name <=> b.name }.collectEntries{ f -> [(f.name) : f.get(null)]}]}
-    return m
-}
-
-def toPythonValue = { type, value ->
-  type == String.class && value != null ? ('"' + value + '"') : value
-}
-
-def toJavaMap = toPythonMap.collectEntries{k,v -> [(v):k]}
-def toPython = { symbol -> toPythonMap.getOrDefault(symbol, symbol) }
-def toJava = { symbol -> toJavaMap.getOrDefault(symbol, symbol) }
-
-// for enums we ignore T and handle it manually because of conflict with T.id which is trickier to deal with
-// in the templating language
-def binding = ["enums": CoreImports.getClassImports()
-        .findAll { Enum.class.isAssignableFrom(it) && !(it in [T, Operator]) }
-        .sort { a, b -> a.getSimpleName() <=> b.getSimpleName() },
-               "pmethods": P.class.getMethods().
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { P.class.isAssignableFrom(it.returnType) }.
-                       collect { toPython(it.name) }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "tpmethods": TextP.class.getMethods().
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { TextP.class.isAssignableFrom(it.returnType) }.
-                       collect { toPython(it.name) }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS
-                       findAll { GraphTraversalSource.class.equals(it.returnType) }.
-                       findAll {
-                           !it.name.equals("clone") &&
-                                   !it.name.equals(TraversalSource.Symbols.withRemote) &&
-                                   !it.name.equals(TraversalSource.Symbols.withComputer)
-                       }.
-                       collect { toPython(it.name) }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS
-                       findAll { GraphTraversal.class.equals(it.returnType) }.
-                       collect { toPython(it.name) }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "graphStepMethods": GraphTraversal.getMethods().
-                       findAll { GraphTraversal.class.equals(it.returnType) }.
-                       findAll { !it.name.equals("clone") && !it.name.equals("iterate") }.
-                       collect { toPython(it.name) }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "anonStepMethods": __.class.getMethods().
-                       findAll { GraphTraversal.class.equals(it.returnType) }.
-                       findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { !it.name.equals("__") && !it.name.equals("start") }.
-                       collect { toPython(it.name) }.
-                       unique().
-                       sort { a, b -> a <=> b },
-               "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
-               "toPython": toPython,
-               "toJava": toJava,
-               "withOptions": WithOptions.getDeclaredFields().
-                        collect {["name": it.name, "value": toPythonValue(it.type, it.get(null))]}]
-
-def engine = new groovy.text.GStringTemplateEngine()
-def traversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TraversalSource.template")).make(binding)
-def traversalFile = new File("${projectBaseDir}/src/main/jython/gremlin_python/process/traversal.py")
-traversalFile.newWriter().withWriter{ it << traversalTemplate }
-
-def graphTraversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversalSource.template")).make(binding)
-def graphTraversalFile = new File("${projectBaseDir}/src/main/jython/gremlin_python/process/graph_traversal.py")
-graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate }
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index 2bbc279..7f7954e 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -21,46 +21,10 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-python</artifactId>
     <name>Apache TinkerPop :: Gremlin Python</name>
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.tinkerpop</groupId>
-            <artifactId>gremlin-core</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.python</groupId>
-            <artifactId>jython-standalone</artifactId>
-            <version>2.7.1</version>
-        </dependency>
-        <!-- TESTING -->
-        <dependency>
-            <groupId>org.apache.tinkerpop</groupId>
-            <artifactId>tinkergraph-gremlin</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tinkerpop</groupId>
-            <artifactId>gremlin-test</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tinkerpop</groupId>
-            <artifactId>gremlin-server</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
     <properties>
         <!-- provides a way to convert maven.test.skip value to skipTests for use in skipping python tests -->
         <maven.test.skip>false</maven.test.skip>
@@ -70,177 +34,42 @@
     <build>
         <directory>${basedir}/target</directory>
         <finalName>${project.artifactId}-${project.version}</finalName>
-        <resources>
-            <resource>
-                <directory>src/main/resources
-                </directory>
-            </resource>
-        </resources>
-        <testResources>
-            <testResource>
-                <directory>${basedir}/src/test/resources
-                </directory>
-            </testResource>
-        </testResources>
         <plugins>
+            <!--
+            there is no point to building/deploying the jvm stuff - there is no java source really - just poms
+            -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-clean-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>clean</goal>
-                        </goals>
-                    </execution>
-                </executions>
+                <artifactId>maven-javadoc-plugin</artifactId>
                 <configuration>
-                    <filesets>
-                        <!-- SOURCE DIRECTORIES -->
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/gremlin_python</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/gremlin_python/driver</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/gremlin_python/process</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/gremlin_python/structure</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/gremlin_python/structure/io</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <!-- TEST DIRECTORIES -->
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/tests</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/tests/driver</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/tests/process</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/tests/structure</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                        <fileset>
-                            <directory>${basedir}/src/main/jython/tests/structure/io</directory>
-                            <includes>
-                                <include>**/*.pyc</include>
-                                <include>**/*.class</include>
-                            </includes>
-                            <excludes>
-                                <exclude>**/*.py</exclude>
-                            </excludes>
-                            <followSymlinks>false</followSymlinks>
-                        </fileset>
-                    </filesets>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <configuration>
+                    <skipSource>true</skipSource>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-install-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
                 </configuration>
             </plugin>
         </plugins>
     </build>
 
     <profiles>
-        <!-- This default profile works around the issue where the glv-python profile which is expected to run all tests
-             can't override the exclusions defined below. -->
-        <profile>
-            <id>glv-python-standard</id>
-            <activation>
-                <activeByDefault>true</activeByDefault>
-            </activation>
-            <build>
-                <plugins>
-                    <!-- excludes python related tests that require python itself installed on the system - run with the
-                         python profile if glVPython is present -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <python.home>${project.build.outputDirectory}</python.home>
-                            </systemPropertyVariables>
-                            <excludes>
-                                <exclude>**/jsr223/Python*Test.java</exclude>
-                                <exclude>**/graphson/GraphSON*Test.java</exclude>
-                            </excludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
         <!-- activates the building of python components and requires that python be installed on the system -->
         <profile>
             <id>glv-python</id>
@@ -251,18 +80,7 @@
                 </file>
             </activation>
             <build>
-
-                <!-- don't exclude any tests as python is assumed to be installed on this system -->
                 <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <python.home>${project.build.outputDirectory}</python.home>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
                     <!-- need to create python-reports directory at this point or else pytest can't write the report to it -->
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
@@ -281,7 +99,7 @@
                                     </target>
                                 </configuration>
                             </execution>
-                            <!-- copy files in jython directory to target/py and run virtual env to sandbox python.
+                            <!-- copy files in python directory to target/py and run virtual env to sandbox python.
                                  there is no need to "activate" the virtualenv because all calls to python occur
                                  directly from bin/ -->
                             <execution>
@@ -293,57 +111,35 @@
                                 <configuration>
                                     <tasks>
                                         <!-- seems like we need a few different copies of the same source. all the
-                                             different python/jython stuff doesn't seem to want to share. we use
-                                             /python for basic tests and stuff, /jython for jython compilation with
-                                             the jython plugin, /python-packaged for distribution tasks. some of the
-                                             problem seems to stem from the python lifecycle not binding perfectly well
-                                             to the maven lifecycle (integration tests seems to cause troubles
-                                             specifically). note that the commands to install wheel are largely for
-                                             safety in case someone is using an older version of virtualenv (which
-                                             doesn't install wheel by default) -->
+                                             different python stuff doesn't seem to want to share. we use
+                                             /python3 for basic tests and stuff and /python-packaged for distribution
+                                             tasks. some of the problem seems to stem from the python lifecycle not
+                                             binding perfectly well to the maven lifecycle (integration tests seems to
+                                             cause troubles specifically). note that the commands to install wheel are
+                                             largely for safety in case someone is using an older version of virtualenv
+                                             (which doesn't install wheel by default) -->
                                         <copy todir="${project.build.directory}/python3">
-                                            <fileset dir="src/main/jython"/>
+                                            <fileset dir="src/main/python"/>
                                         </copy>
-                                        <copy todir="${project.build.directory}/python2">
-                                            <fileset dir="src/main/jython"/>
-                                        </copy>
-                                        <copy todir="${project.build.directory}/python-packaged">
-                                            <fileset dir="src/main/jython"/>
-                                        </copy>
-                                        <!-- print versions of python and virtualenv -->
-                                        <exec dir="${project.build.directory}/python2" executable="python2"
+                                        <exec dir="${project.build.directory}/python3" executable="python3"
                                               failonerror="true">
                                             <arg line="--version"/>
                                         </exec>
-                                        <exec dir="${project.build.directory}/python2" executable="python3"
+                                        <exec dir="${project.build.directory}/python3" executable="virtualenv"
                                               failonerror="true">
                                             <arg line="--version"/>
                                         </exec>
-                                        <exec dir="${project.build.directory}/python2" executable="virtualenv"
-                                              failonerror="true">
-                                            <arg line="--version"/>
-                                        </exec>
-                                        <exec dir="${project.build.directory}/python2" executable="virtualenv"
-                                              failonerror="true">
-                                            <arg line="--python=python2 env"/>
-                                        </exec>
-                                        <!-- pip 20 doesn't work with python 2 it seems -->
-                                        <exec dir="${project.build.directory}/python2" executable="env/bin/python"
-                                              failonerror="true">
-                                            <arg line="-m pip install pip&gt;=19.3.1,&lt;20.0.0"/>
-                                        </exec>
-                                        <exec dir="${project.build.directory}/python2" executable="env/bin/pip"
-                                              failonerror="true">
-                                            <arg line="install wheel radish-bdd PyHamcrest aenum isodate"/>
-                                        </exec>
                                         <exec dir="${project.build.directory}/python3" executable="virtualenv"
                                               failonerror="true">
                                             <arg line="--python=python3 env"/>
                                         </exec>
                                         <exec dir="${project.build.directory}/python3" executable="env/bin/pip"
                                               failonerror="true">
-                                            <arg line="install wheel radish-bdd PyHamcrest aenum isodate"/>
+                                            <arg line="install wheel radish-bdd PyHamcrest aenum isodate kerberos six"/>
                                         </exec>
+                                        <copy todir="${project.build.directory}/python-packaged">
+                                            <fileset dir="src/main/python"/>
+                                        </copy>
                                         <exec dir="${project.build.directory}/python-packaged" executable="virtualenv"
                                               failonerror="true">
                                             <arg line="--python=python3 env"/>
@@ -356,23 +152,6 @@
                                 </configuration>
                             </execution>
                             <execution>
-                                <id>native-python2-build</id>
-                                <phase>compile</phase>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <configuration>
-                                    <target>
-                                        <exec executable="env/bin/python" dir="${project.build.directory}/python2"
-                                              failonerror="true">
-                                            <env key="PYTHONPATH" value=""/>
-                                            <!-- oddly the "build-lib" needs to be in place or else docs won't generate -->
-                                            <arg line="setup.py build --build-lib ${project.build.outputDirectory}/Lib"/>
-                                        </exec>
-                                    </target>
-                                </configuration>
-                            </execution>
-                            <execution>
                                 <id>native-python3-build</id>
                                 <phase>compile</phase>
                                 <goals>
@@ -418,48 +197,6 @@
                             test phase doesn't have a pre/post event like integration-test does.
                             -->
                             <execution>
-                                <id>native-python2-test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <configuration>
-                                    <skip>${skipTests}</skip>
-                                    <target>
-                                        <!-- setup.py seems to have troubles with the recently published zipp 1.0.0 -->
-                                        <exec dir="${project.build.directory}/python2" executable="env/bin/python"
-                                              failonerror="true">
-                                            <arg line="-m pip install zipp&gt;=0.5.0,&lt;1.0.0"/>
-                                        </exec>
-                                        <exec executable="env/bin/python" dir="${project.build.directory}/python2"
-                                              failonerror="true">
-                                            <env key="PYTHONPATH" value=""/>
-                                            <arg line="setup.py test"/>
-                                        </exec>
-                                        <!-- radish seems to like all dependencies in place -->
-                                        <exec executable="env/bin/python" dir="${project.build.directory}/python2"
-                                              failonerror="true">
-                                            <env key="PYTHONPATH" value=""/>
-                                            <arg line="setup.py install"/>
-                                        </exec>
-                                        <!-- run for graphson 3.0 -->
-                                        <exec executable="env/bin/radish" dir="${project.build.directory}/python2"
-                                              failonerror="true">
-                                            <env key="PYTHONPATH" value=""/>
-                                            <env key="PYTHONIOENCODING" value="utf-8:surrogateescape"/>
-                                            <arg line="-f dots -e -t -b ${project.build.directory}/python2/radish ${project.basedir}/../gremlin-test/features/ --user-data=&quot;serializer=application/vnd.gremlin-v3.0+json&quot;"/> <!-- -no-line-jump -->
-                                        </exec>
-                                        <!-- run for graphbinary 1.0 -->
-                                        <exec executable="env/bin/radish" dir="${project.build.directory}/python2"
-                                              failonerror="true">
-                                            <env key="PYTHONPATH" value=""/>
-                                            <env key="PYTHONIOENCODING" value="utf-8:surrogateescape"/>
-                                            <arg line="-f dots -e -t -b ${project.build.directory}/python2/radish ${project.basedir}/../gremlin-test/features/ --user-data=&quot;serializer=application/vnd.graphbinary-v1.0&quot;"/> <!-- -no-line-jump -->
-                                        </exec>
-                                    </target>
-                                </configuration>
-                            </execution>
-                            <execution>
                                 <id>native-python3-test</id>
                                 <phase>integration-test</phase>
                                 <goals>
@@ -471,8 +208,30 @@
                                         <exec executable="env/bin/python" dir="${project.build.directory}/python3"
                                               failonerror="true">
                                             <env key="PYTHONPATH" value=""/>
+                                            <env key="KRB5_CONFIG" value="${project.build.directory}/kdc/krb5.conf"/>
+                                            <env key="KRB5CCNAME" value="${project.build.directory}/kdc/test-tkt.cc"/>
                                             <arg line="setup.py test"/>
                                         </exec>
+                                        <!-- radish seems to like all dependencies in place -->
+                                        <exec executable="env/bin/python" dir="${project.build.directory}/python3"
+                                              failonerror="true">
+                                            <env key="PYTHONPATH" value=""/>
+                                            <arg line="setup.py install"/>
+                                        </exec>
+                                        <!-- run for graphson 3.0 -->
+                                        <exec executable="env/bin/radish" dir="${project.build.directory}/python3"
+                                              failonerror="true">
+                                            <env key="PYTHONPATH" value=""/>
+                                            <env key="PYTHONIOENCODING" value="utf-8:surrogateescape"/>
+                                            <arg line="-f dots -e -t -b ${project.build.directory}/python3/radish ${project.basedir}/../gremlin-test/features/ --user-data=&quot;serializer=application/vnd.gremlin-v3.0+json&quot;"/> <!-- -no-line-jump -->
+                                        </exec>
+                                        <!-- run for graphbinary 1.0 -->
+                                        <exec executable="env/bin/radish" dir="${project.build.directory}/python3"
+                                              failonerror="true">
+                                            <env key="PYTHONPATH" value=""/>
+                                            <env key="PYTHONIOENCODING" value="utf-8:surrogateescape"/>
+                                            <arg line="-f dots -e -t -b ${project.build.directory}/python3/radish ${project.basedir}/../gremlin-test/features/ --user-data=&quot;serializer=application/vnd.graphbinary-v1.0&quot;"/> <!-- -no-line-jump -->
+                                        </exec>
                                     </target>
                                 </configuration>
                             </execution>
@@ -483,6 +242,16 @@
                         <artifactId>gmavenplus-plugin</artifactId>
                         <dependencies>
                             <dependency>
+                                <groupId>org.apache.tinkerpop</groupId>
+                                <artifactId>gremlin-server</artifactId>
+                                <version>${project.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.tinkerpop</groupId>
+                                <artifactId>gremlin-test</artifactId>
+                                <version>${project.version}</version>
+                            </dependency>
+                            <dependency>
                                 <groupId>org.codehaus.groovy</groupId>
                                 <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
@@ -498,24 +267,6 @@
                         </dependencies>
                         <executions>
                             <execution>
-                                <id>generate-dsl</id>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>execute</goal>
-                                </goals>
-                                <configuration>
-                                    <properties>
-                                        <property>
-                                            <name>projectBaseDir</name>
-                                            <value>${project.basedir}</value>
-                                        </property>
-                                    </properties>
-                                    <scripts>
-                                        <script>${project.basedir}/glv/generate.groovy</script>
-                                    </scripts>
-                                </configuration>
-                            </execution>
-                            <execution>
                                 <id>gremlin-server-start</id>
                                 <phase>pre-integration-test</phase>
                                 <goals>
@@ -528,10 +279,6 @@
                                             <value>${skipTests}</value>
                                         </property>
                                         <property>
-                                            <name>python</name>
-                                            <value>true</value>
-                                        </property>
-                                        <property>
                                             <name>gremlinServerDir</name>
                                             <value>${gremlin.server.dir}</value>
                                         </property>
@@ -596,19 +343,6 @@
             </activation>
             <build>
                 <plugins>
-                    <!--
-                    pypi doesn't have a staging area like sonatype so the deploy to pypi is done out of the normal
-                    release band. it is performed after successful VOTE in which case, the maven artifacts should
-                    not be deployed again - hence the plugin is disabled. deployment to pypi uses the antrun plugin
-                    below with twine so disabling the plugin has no effect on the pypi deployment.
-                    -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-deploy-plugin</artifactId>
-                        <configuration>
-                            <skip>true</skip>
-                        </configuration>
-                    </plugin>
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-antrun-plugin</artifactId>
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java
deleted file mode 100644
index 86473c4..0000000
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.jsr223.CoreGremlinPlugin;
-import org.apache.tinkerpop.gremlin.jsr223.CoreImports;
-import org.apache.tinkerpop.gremlin.jsr223.Customizer;
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory;
-import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer;
-import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.python.jsr223.PyScriptEngine;
-import org.python.jsr223.PyScriptEngineFactory;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptException;
-import javax.script.SimpleBindings;
-import java.io.Reader;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @deprecated As of release 3.3.10, not replaced - see TINKERPOP-2317
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@Deprecated
-public class GremlinJythonScriptEngine implements GremlinScriptEngine {
-
-    private final PyScriptEngine pyScriptEngine;
-
-    public GremlinJythonScriptEngine(final Customizer... customizers) {
-        this.pyScriptEngine = (PyScriptEngine) new PyScriptEngineFactory().getScriptEngine();
-        final List<Customizer> listOfCustomizers = new ArrayList<>(Arrays.asList(customizers));
-
-        // always need this plugin for a scriptengine to be "Gremlin-enabled"
-        CoreGremlinPlugin.instance().getCustomizers("gremlin-jython").ifPresent(c -> listOfCustomizers.addAll(Arrays.asList(c)));
-
-        final List<ImportCustomizer> importCustomizers = listOfCustomizers.stream()
-                .filter(p -> p instanceof ImportCustomizer)
-                .map(p -> (ImportCustomizer) p)
-                .collect(Collectors.toList());
-
-        try {
-            for (ImportCustomizer ic : importCustomizers) {
-                for (Class<?> c : ic.getClassImports()) {
-                    if (null == c.getDeclaringClass())
-                        this.pyScriptEngine.eval("from " + c.getPackage().getName() + " import " + c.getSimpleName());
-                    else
-                        this.pyScriptEngine.eval("from " + c.getPackage().getName() + "." + c.getDeclaringClass().getSimpleName() + " import " + c.getSimpleName());
-                }
-
-                for (Method m : ic.getMethodImports()) {
-                    this.pyScriptEngine.eval(SymbolHelper.toPython(m.getName()) + " = " + m.getDeclaringClass().getSimpleName() + "." + m.getName());
-                }
-
-                // enums need to import after methods for some reason or else label comes in as a PyReflectedFunction
-                for (Enum e : ic.getEnumImports()) {
-                    this.pyScriptEngine.eval(SymbolHelper.toPython(e.name()) + " = " + e.getDeclaringClass().getSimpleName() + "." + e.name());
-                }
-            }
-
-            loadSugar();
-
-        } catch (Exception ex) {
-            throw new IllegalStateException(ex);
-        }
-    }
-
-    @Override
-    public Traversal.Admin eval(final Bytecode bytecode, final Bindings bindings, final String traversalSource) throws ScriptException {
-        // these validations occur before merging in bytecode bindings which will override existing ones. need to
-        // extract the named traversalsource prior to that happening so that bytecode bindings can share the same
-        // namespace as global bindings (e.g. traversalsources and graphs).
-        if (traversalSource.equals(HIDDEN_G))
-            throw new IllegalArgumentException("The traversalSource cannot have the name " + HIDDEN_G + " - it is reserved");
-
-        if (!bindings.containsKey(traversalSource))
-            throw new IllegalArgumentException("The bindings available to the ScriptEngine do not contain a traversalSource named: " + traversalSource);
-
-        final Object b = bindings.get(traversalSource);
-        if (!(b instanceof TraversalSource))
-            throw new IllegalArgumentException(traversalSource + " is of type " + b.getClass().getSimpleName() + " and is not an instance of TraversalSource");
-
-        final Bindings inner = new SimpleBindings();
-        inner.putAll(bindings);
-        inner.putAll(bytecode.getBindings());
-        inner.put(HIDDEN_G, b);
-
-        return (Traversal.Admin) this.eval(JythonTranslator.of(HIDDEN_G).translate(bytecode), inner);
-    }
-
-    @Override
-    public Object eval(final String script, final ScriptContext context) throws ScriptException {
-        return this.pyScriptEngine.eval(script, context);
-    }
-
-    @Override
-    public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
-        return this.pyScriptEngine.eval(reader, context);
-    }
-
-    @Override
-    public Object eval(final String script) throws ScriptException {
-        return this.pyScriptEngine.eval(script);
-    }
-
-    @Override
-    public Object eval(final Reader reader) throws ScriptException {
-        return this.pyScriptEngine.eval(reader);
-    }
-
-    @Override
-    public Object eval(final String script, final Bindings n) throws ScriptException {
-        this.pyScriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(n); // TODO: groovy and jython act different
-        return this.pyScriptEngine.eval(script);
-    }
-
-    @Override
-    public Object eval(final Reader reader, final Bindings n) throws ScriptException {
-        this.pyScriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(n); // TODO: groovy and jython act different
-        return this.pyScriptEngine.eval(reader);
-    }
-
-    @Override
-    public void put(final String key, final Object value) {
-        this.pyScriptEngine.put(key, value);
-    }
-
-    @Override
-    public Object get(final String key) {
-        return this.pyScriptEngine.get(key);
-    }
-
-    @Override
-    public Bindings getBindings(final int scope) {
-        return this.pyScriptEngine.getBindings(scope);
-    }
-
-    @Override
-    public void setBindings(final Bindings bindings, final int scope) {
-        this.pyScriptEngine.setBindings(bindings, scope);
-    }
-
-    @Override
-    public Bindings createBindings() {
-        return this.pyScriptEngine.createBindings();
-    }
-
-    @Override
-    public ScriptContext getContext() {
-        return this.pyScriptEngine.getContext();
-    }
-
-    @Override
-    public void setContext(final ScriptContext context) {
-        this.pyScriptEngine.setContext(context);
-    }
-
-    @Override
-    public GremlinScriptEngineFactory getFactory() {
-        return new GremlinJythonScriptEngineFactory();
-    }
-
-    private void loadSugar() throws ScriptException {
-        // add sugar methods
-        this.pyScriptEngine.eval("def getitem_bypass(self, index):\n" +
-                "  if isinstance(index,int):\n    return self.range(index,index+1)\n" +
-                "  elif isinstance(index,slice):\n    return self.range(index.start,index.stop)\n" +
-                "  else:\n    return TypeError('Index must be int or slice')");
-        this.pyScriptEngine.eval(GraphTraversal.class.getSimpleName() + ".__getitem__ = getitem_bypass");
-        this.pyScriptEngine.eval(GraphTraversal.class.getSimpleName() + ".__getattr__ = lambda self, key: self.values(key)\n");
-        this.pyScriptEngine.eval("\n" +
-                "from java.lang import Long\n" +
-                "import org.apache.tinkerpop.gremlin.util.function.Lambda\n" + // todo: remove or remove imported subclass names? (choose)
-                "from org.apache.tinkerpop.gremlin.util.function.Lambda import AbstractLambda\n" +
-                "from org.apache.tinkerpop.gremlin.util.function.Lambda import UnknownArgLambda\n" +
-                "from org.apache.tinkerpop.gremlin.util.function.Lambda import ZeroArgLambda\n" +
-                "from org.apache.tinkerpop.gremlin.util.function.Lambda import OneArgLambda\n" +
-                "from org.apache.tinkerpop.gremlin.util.function.Lambda import TwoArgLambda\n\n" +
-
-                "class JythonUnknownArgLambda(UnknownArgLambda):\n" +
-                "  def __init__(self,func,script='none',lang='gremlin-jython'):\n" +
-                "    UnknownArgLambda.__init__(self, script, lang, -1)\n" +
-                "    self.func = func\n" +
-                "  def __repr__(self):\n" +
-                "    return self.getLambdaScript()\n\n" +
-
-                "class JythonZeroArgLambda(ZeroArgLambda):\n" +
-                "  def __init__(self,func,script='none',lang='gremlin-jython'):\n" +
-                "    ZeroArgLambda.__init__(self, script, lang)\n" +
-                "    self.func = func\n" +
-                "  def __repr__(self):\n" +
-                "    return self.getLambdaScript()\n" +
-                "  def get(self):\n" +
-                "    return self.func()\n\n" +
-
-                "class JythonOneArgLambda(OneArgLambda):\n" +
-                "  def __init__(self,func,script='none',lang='gremlin-jython'):\n" +
-                "    OneArgLambda.__init__(self, script, lang)\n" +
-                "    self.func = func\n" +
-                "  def __repr__(self):\n" +
-                "    return self.getLambdaScript()\n" +
-                "  def test(self,a):\n" +
-                "    return self.func(a)\n" +
-                "  def apply(self,a):\n" +
-                "    return self.func(a)\n" +
-                "  def accept(self,a):\n" +
-                "    self.func(a)\n" +
-                "  def compare(self,a,b):\n" +
-                "    return self.func(a,b)\n\n" +
-
-                "class JythonTwoArgLambda(TwoArgLambda):\n" +
-                "  def __init__(self,func,script='none',lang='gremlin-jython'):\n" +
-                "    TwoArgLambda.__init__(self, script, lang)\n" +
-                "    self.func = func\n" +
-                "  def __repr__(self):\n" +
-                "    return self.getLambdaScript()\n" +
-                "  def apply(self,a,b):\n" +
-                "    return self.func(a,b)\n" +
-                "  def compare(self,a,b):\n" +
-                "    return self.func(a,b)\n"
-        );
-    }
-}
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineFactory.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineFactory.java
deleted file mode 100644
index f3cafc1..0000000
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineFactory.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.jsr223.Customizer;
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory;
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineManager;
-import org.apache.tinkerpop.gremlin.util.Gremlin;
-import org.python.jsr223.PyScriptEngineFactory;
-
-import javax.script.ScriptEngine;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @deprecated As of release 3.3.10, not replaced - see TINKERPOP-2317
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Deprecated
-public class GremlinJythonScriptEngineFactory extends PyScriptEngineFactory implements GremlinScriptEngineFactory {
-
-    private static final String GREMLIN_JYTHON = "gremlin-jython";
-    private static final String GREMLIN_PYTHON = "gremlin-python";
-    private static final String PLAIN = "plain";
-    private static final List<String> EXTENSIONS = Collections.singletonList("py");
-
-    private GremlinScriptEngineManager manager;
-
-    @Override
-    public void setCustomizerManager(final GremlinScriptEngineManager manager) {
-        this.manager = manager;
-    }
-
-    @Override
-    public String getEngineName() {
-        return GREMLIN_JYTHON;
-    }
-
-    @Override
-    public String getEngineVersion() {
-        return Gremlin.version();
-    }
-
-    @Override
-    public List<String> getExtensions() {
-        return EXTENSIONS;
-    }
-
-    @Override
-    public String getLanguageName() {
-        return GREMLIN_JYTHON;
-    }
-
-    @Override
-    public String getLanguageVersion() {
-        return Gremlin.version();
-    }
-
-    @Override
-    public List<String> getMimeTypes() {
-        return Collections.singletonList(PLAIN);
-    }
-
-    @Override
-    public List<String> getNames() {
-        return Arrays.asList(GREMLIN_JYTHON, GREMLIN_PYTHON);
-    }
-
-    @Override
-    public Object getParameter(final String key) {
-        if (key.equals(ScriptEngine.ENGINE)) {
-            return this.getEngineName();
-        } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
-            return this.getEngineVersion();
-        } else if (key.equals(ScriptEngine.NAME)) {
-            return GREMLIN_JYTHON;
-        } else if (key.equals(ScriptEngine.LANGUAGE)) {
-            return this.getLanguageName();
-        } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
-            return this.getLanguageVersion();
-        } else
-            return super.getParameter(key);
-    }
-
-    @Override
-    public GremlinScriptEngine getScriptEngine() {
-        final Set<Customizer> customizers = new HashSet<>(manager.getCustomizers(GREMLIN_JYTHON));
-        customizers.addAll(manager.getCustomizers(GREMLIN_PYTHON));
-
-        return (customizers.isEmpty()) ? new GremlinJythonScriptEngine() :
-                new GremlinJythonScriptEngine(customizers.toArray(new Customizer[customizers.size()]));
-    }
-}
\ No newline at end of file
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java
deleted file mode 100644
index 0a77526..0000000
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.commons.configuration.ConfigurationConverter;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
-import org.apache.tinkerpop.gremlin.util.function.Lambda;
-
-/**
- * @deprecated As of release 3.3.10, not replaced - see TINKERPOP-2317
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@Deprecated
-public final class JythonTranslator extends PythonTranslator {
-
-    private JythonTranslator(final String traversalSource, final boolean importStatics) {
-        super(traversalSource, importStatics);
-    }
-
-    public static JythonTranslator of(final String traversalSource) {
-        return new JythonTranslator(traversalSource, false);
-    }
-
-    @Override
-    public String getTargetLanguage() {
-        return "gremlin-jython";
-    }
-
-    @Override
-    protected String convertLambdaToString(final Lambda lambda) {
-        String lambdaString = lambda.getLambdaScript().trim();
-        lambdaString = lambdaString.startsWith("lambda") ?
-                lambdaString :
-                "lambda " + lambdaString;
-        if (0 == lambda.getLambdaArguments())
-            return "JythonZeroArgLambda(" + lambdaString + ")";
-        else if (1 == lambda.getLambdaArguments())
-            return "JythonOneArgLambda(" + lambdaString + ")";
-        else if (2 == lambda.getLambdaArguments())
-            return "JythonTwoArgLambda(" + lambdaString + ")";
-        else
-            return "JythonUnknownArgLambda(" + lambdaString + ")";
-    }
-
-    @Override
-    protected String resolveSymbol(final String methodName) {
-        // since this is Jython we should expect the Gremlin to conform to the java classes to which the engine is
-        // bound - therefore, unlike the python engine which converts java names to python friendly ones, this
-        // jython one can just pass them through.
-        return methodName;
-    }
-
-    @Override
-    protected String resolveTraversalStrategyProxy(final TraversalStrategyProxy proxy) {
-        // since this is jython we don't need a traversal proxy here - we need the actual JVM version of the strategy
-        // since this script will be executed in Jython. 
-        if (proxy.getConfiguration().isEmpty())
-            return proxy.getStrategyClass().getCanonicalName() + ".instance()";
-        else
-            return proxy.getStrategyClass().getCanonicalName() + ".create(org.apache.commons.configuration.MapConfiguration(" + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + "))";
-    }
-}
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
deleted file mode 100644
index a24e0e5..0000000
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.commons.configuration.ConfigurationConverter;
-import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.Operator;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
-import org.apache.tinkerpop.gremlin.process.traversal.TextP;
-import org.apache.tinkerpop.gremlin.process.traversal.Translator;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
-import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
-import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * @deprecated As of release 3.3.10, not replaced - see TINKERPOP-2317
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@Deprecated
-public class PythonTranslator implements Translator.ScriptTranslator {
-
-    private static final Set<String> STEP_NAMES = Stream.of(GraphTraversal.class.getMethods()).filter(method -> Traversal.class.isAssignableFrom(method.getReturnType())).map(Method::getName).collect(Collectors.toSet());
-    private static final Set<String> NO_STATIC = Stream.of(T.values(), Operator.values())
-            .flatMap(arg -> IteratorUtils.stream(new ArrayIterator<>(arg)))
-            .map(arg -> ((Enum) arg).name())
-            .collect(Collectors.toCollection(() -> new HashSet<>(Collections.singleton("not"))));
-
-    private final String traversalSource;
-    private final boolean importStatics;
-
-    PythonTranslator(final String traversalSource, final boolean importStatics) {
-        this.traversalSource = traversalSource;
-        this.importStatics = importStatics;
-    }
-
-    public static PythonTranslator of(final String traversalSource, final boolean importStatics) {
-        return new PythonTranslator(traversalSource, importStatics);
-    }
-
-    public static PythonTranslator of(final String traversalSource) {
-        return new PythonTranslator(traversalSource, false);
-    }
-
-    @Override
-    public String getTraversalSource() {
-        return this.traversalSource;
-    }
-
-    @Override
-    public String translate(final Bytecode bytecode) {
-        return this.internalTranslate(this.traversalSource, bytecode);
-    }
-
-    @Override
-    public String getTargetLanguage() {
-        return "gremlin-python";
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.translatorString(this);
-    }
-
-    ///////
-
-    private String internalTranslate(final String start, final Bytecode bytecode) {
-        final StringBuilder traversalScript = new StringBuilder(start);
-        for (final Bytecode.Instruction instruction : bytecode.getInstructions()) {
-            final String methodName = instruction.getOperator();
-            final Object[] arguments = instruction.getArguments();
-            if (0 == arguments.length)
-                traversalScript.append(".").append(resolveSymbol(methodName)).append("()");
-            else if (methodName.equals("range") && 2 == arguments.length)
-                if (((Number) arguments[0]).longValue() + 1 == ((Number) arguments[1]).longValue())
-                    traversalScript.append("[").append(arguments[0]).append("]");
-                else
-                    traversalScript.append("[").append(arguments[0]).append(":").append(arguments[1]).append("]");
-            else if (methodName.equals("limit") && 1 == arguments.length)
-                traversalScript.append("[0:").append(arguments[0]).append("]");
-            else if (methodName.equals("values") && 1 == arguments.length && traversalScript.length() > 3 && !STEP_NAMES.contains(arguments[0].toString()))
-                traversalScript.append(".").append(arguments[0]);
-            else {
-                traversalScript.append(".");
-                String temp = resolveSymbol(methodName) + "(";
-
-                // jython has trouble with java varargs...wrapping in collection seems to solve the problem
-                final boolean varargsBeware = instruction.getOperator().equals(TraversalSource.Symbols.withStrategies)
-                            || instruction.getOperator().equals(TraversalSource.Symbols.withoutStrategies);
-                if (varargsBeware) temp = temp + "[";
-
-                for (final Object object : arguments) {
-                    temp = temp + convertToString(object) + ",";
-                }
-                temp = temp.substring(0, temp.length() - 1);
-
-                if (varargsBeware) temp = temp + "]";
-
-                traversalScript.append(temp).append(")");
-            }
-            // clip off __.
-            if (this.importStatics && traversalScript.substring(0, 3).startsWith("__.")
-                    && !NO_STATIC.stream().filter(name -> traversalScript.substring(3).startsWith(resolveSymbol(name))).findAny().isPresent()) {
-                traversalScript.delete(0, 3);
-            }
-        }
-        return traversalScript.toString();
-    }
-
-    protected String convertToString(final Object object) {
-        if (object instanceof Bytecode.Binding)
-            return ((Bytecode.Binding) object).variable();
-        else if (object instanceof Bytecode)
-            return this.internalTranslate("__", (Bytecode) object);
-        else if (object instanceof Traversal)
-            return convertToString(((Traversal) object).asAdmin().getBytecode());
-        else if (object instanceof String)
-            return ((String) object).contains("\"") ? "\"\"\"" + object + "\"\"\"" : "\"" + object + "\"";
-        else if (object instanceof Set) {
-            final Set<String> set = new LinkedHashSet<>(((Set) object).size());
-            for (final Object item : (Set) object) {
-                set.add(convertToString(item));
-            }
-            return "set(" + set.toString() + ")";
-        } else if (object instanceof List) {
-            final List<String> list = new ArrayList<>(((List) object).size());
-            for (final Object item : (List) object) {
-                list.add(convertToString(item));
-            }
-            return list.toString();
-        } else if (object instanceof Map) {
-            final StringBuilder map = new StringBuilder("{");
-            for (final Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
-                map.append(convertToString(entry.getKey())).
-                        append(":").
-                        append(convertToString(entry.getValue())).
-                        append(",");
-            }
-            return map.length() > 1 ? map.substring(0, map.length() - 1) + "}" : map.append("}").toString();
-        } else if (object instanceof Long)
-            return object + "L";
-        else if (object instanceof TraversalStrategyProxy) {
-            return resolveTraversalStrategyProxy((TraversalStrategyProxy) object);
-        } else if (object instanceof TraversalStrategy) {
-            return convertToString(new TraversalStrategyProxy((TraversalStrategy) object));
-        } else if (object instanceof Boolean)
-            return object.equals(Boolean.TRUE) ? "True" : "False";
-        else if (object instanceof Class)
-            return ((Class) object).getCanonicalName();
-        else if (object instanceof VertexProperty.Cardinality)
-            return "Cardinality." + resolveSymbol(object.toString());
-        else if (object instanceof SackFunctions.Barrier)
-            return "Barrier." + resolveSymbol(object.toString());
-        else if (object instanceof TraversalOptionParent.Pick)
-            return "Pick." + resolveSymbol(object.toString());
-        else if (object instanceof Enum)
-            return convertStatic(((Enum) object).getDeclaringClass().getSimpleName() + ".") + resolveSymbol(object.toString());
-        else if (object instanceof P)
-            return convertPToString((P) object, new StringBuilder()).toString();
-        else if (object instanceof Element) {
-            if (object instanceof Vertex) {
-                final Vertex vertex = (Vertex) object;
-                return "Vertex(" + convertToString(vertex.id()) + "," + convertToString(vertex.label()) + ")";
-            } else if (object instanceof Edge) {
-                final Edge edge = (Edge) object;
-                return "Edge(" + convertToString(edge.id()) + "," +
-                        convertToString(edge.outVertex()) + "," +
-                        convertToString(edge.label()) + "," +
-                        convertToString(edge.inVertex()) + ")";
-            } else {
-                final VertexProperty vertexProperty = (VertexProperty) object;
-                return "VertexProperty(" + convertToString(vertexProperty.id()) + "," +
-                        convertToString(vertexProperty.label()) + "," +
-                        convertToString(vertexProperty.value()) + ")";
-            }
-        } else if (object instanceof Lambda)
-            return convertLambdaToString((Lambda) object);
-        else
-            return null == object ? "None" : object.toString();
-    }
-
-    private String convertStatic(final String name) {
-        return this.importStatics ? "" : name;
-    }
-
-    private StringBuilder convertPToString(final P p, final StringBuilder current) {
-        if (p instanceof TextP) return convertTextPToString((TextP) p, current);
-        if (p instanceof ConnectiveP) {
-            final List<P<?>> list = ((ConnectiveP) p).getPredicates();
-            for (int i = 0; i < list.size(); i++) {
-                convertPToString(list.get(i), current);
-                if (i < list.size() - 1)
-                    current.append(p instanceof OrP ? ".or_(" : ".and_(");
-            }
-            current.append(")");
-        } else
-            current.append(convertStatic("P.")).append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
-        return current;
-    }
-
-    private StringBuilder convertTextPToString(final TextP p, final StringBuilder current) {
-        current.append(convertStatic("TextP.")).append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
-        return current;
-    }
-
-    protected String convertLambdaToString(final Lambda lambda) {
-        final String lambdaString = lambda.getLambdaScript().trim();
-        return lambdaString.startsWith("lambda") ? lambdaString : "lambda " + lambdaString;
-    }
-
-    protected String resolveSymbol(final String methodName) {
-        return SymbolHelper.toPython(methodName);
-    }
-
-    protected String resolveTraversalStrategyProxy(final TraversalStrategyProxy proxy) {
-        if (proxy.getConfiguration().isEmpty())
-            return "TraversalStrategy(\"" + proxy.getStrategyClass().getSimpleName() + "\")";
-        else
-            return "TraversalStrategy(\"" + proxy.getStrategyClass().getSimpleName() + "\"," + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + ")";
-    }
-}
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java
deleted file mode 100644
index 54cd5b3..0000000
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @deprecated As of release 3.3.10, not replaced - see TINKERPOP-2317
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Deprecated
-public final class SymbolHelper {
-
-    private final static Map<String, String> TO_PYTHON_MAP = new HashMap<>();
-    private final static Map<String, String> FROM_PYTHON_MAP = new HashMap<>();
-
-    static {
-        TO_PYTHON_MAP.put("global", "global_");
-        TO_PYTHON_MAP.put("as", "as_");
-        TO_PYTHON_MAP.put("in", "in_");
-        TO_PYTHON_MAP.put("and", "and_");
-        TO_PYTHON_MAP.put("or", "or_");
-        TO_PYTHON_MAP.put("is", "is_");
-        TO_PYTHON_MAP.put("not", "not_");
-        TO_PYTHON_MAP.put("from", "from_");
-        TO_PYTHON_MAP.put("list", "list_");
-        TO_PYTHON_MAP.put("set", "set_");
-        TO_PYTHON_MAP.put("all", "all_");
-        TO_PYTHON_MAP.put("with", "with_");
-        //
-        TO_PYTHON_MAP.forEach((k, v) -> FROM_PYTHON_MAP.put(v, k));
-    }
-
-    private SymbolHelper() {
-        // static methods only, do not instantiate
-    }
-
-    public static String toPython(final String symbol) {
-        return TO_PYTHON_MAP.getOrDefault(symbol, symbol);
-    }
-
-    public static String toJava(final String symbol) {
-        return FROM_PYTHON_MAP.getOrDefault(symbol, symbol);
-    }
-
-}
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/client.py b/gremlin-python/src/main/jython/gremlin_python/driver/client.py
deleted file mode 100644
index f43a054..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/driver/client.py
+++ /dev/null
@@ -1,146 +0,0 @@
-#
-# 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.
-#
-from concurrent.futures import ThreadPoolExecutor
-
-from six.moves import queue
-
-from gremlin_python.driver import connection, protocol, request, serializer
-from gremlin_python.process import traversal
-
-# This is until concurrent.futures backport 3.1.0 release
-try:
-    from multiprocessing import cpu_count
-except ImportError:
-    # some platforms don't have multiprocessing
-    def cpu_count():
-        return None
-
-__author__ = 'David M. Brown (davebshow@gmail.com)'
-
-
-class Client:
-
-    def __init__(self, url, traversal_source, protocol_factory=None,
-                 transport_factory=None, pool_size=None, max_workers=None,
-                 message_serializer=None, username="", password="",
-                 headers=None, session=""):
-        self._url = url
-        self._headers = headers
-        self._traversal_source = traversal_source
-        if message_serializer is None:
-            message_serializer = serializer.GraphSONSerializersV3d0()
-        self._message_serializer = message_serializer
-        self._username = username
-        self._password = password
-        self._session = session
-        self._sessionEnabled = (session != "")
-        if transport_factory is None:
-            try:
-                from gremlin_python.driver.tornado.transport import (
-                    TornadoTransport)
-            except ImportError:
-                raise Exception("Please install Tornado or pass"
-                                "custom transport factory")
-            else:
-                transport_factory = lambda: TornadoTransport()
-        self._transport_factory = transport_factory
-        if protocol_factory is None:
-            protocol_factory = lambda: protocol.GremlinServerWSProtocol(
-                self._message_serializer,
-                username=self._username,
-                password=self._password)
-        self._protocol_factory = protocol_factory
-        if self._sessionEnabled:
-            if pool_size is None:
-                pool_size = 1
-            elif pool_size != 1:
-                raise Exception("PoolSize must be 1 on session mode!")
-        if pool_size is None:
-            pool_size = 4
-        self._pool_size = pool_size
-        # This is until concurrent.futures backport 3.1.0 release
-        if max_workers is None:
-            # If your application is overlapping Gremlin I/O on multiple threads
-            # consider passing kwarg max_workers = (cpu_count() or 1) * 5
-            max_workers = pool_size
-        self._executor = ThreadPoolExecutor(max_workers=max_workers)
-        # Threadsafe queue
-        self._pool = queue.Queue()
-        self._fill_pool()
-
-    @property
-    def available_pool_size(self):
-        return self._pool.qsize()
-
-    @property
-    def executor(self):
-        return self._executor
-
-    @property
-    def traversal_source(self):
-        return self._traversal_source
-
-    def _fill_pool(self):
-        for i in range(self._pool_size):
-            conn = self._get_connection()
-            self._pool.put_nowait(conn)
-
-    def close(self):
-        if self._sessionEnabled:
-            self._close_session()
-        while not self._pool.empty():
-            conn = self._pool.get(True)
-            conn.close()
-        self._executor.shutdown()
-
-    def _close_session(self):
-        message = request.RequestMessage(
-            processor='session', op='close',
-            args={'session': self._session})
-        conn = self._pool.get(True)
-        return conn.write(message).result()
-
-    def _get_connection(self):
-        protocol = self._protocol_factory()
-        return connection.Connection(
-            self._url, self._traversal_source, protocol,
-            self._transport_factory, self._executor, self._pool,
-            headers=self._headers)
-
-    def submit(self, message, bindings=None):
-        return self.submitAsync(message, bindings=bindings).result()
-
-    def submitAsync(self, message, bindings=None):
-        if isinstance(message, traversal.Bytecode):
-            message = request.RequestMessage(
-                processor='traversal', op='bytecode',
-                args={'gremlin': message,
-                      'aliases': {'g': self._traversal_source}})
-        elif isinstance(message, str):
-            message = request.RequestMessage(
-                processor='', op='eval',
-                args={'gremlin': message,
-                      'aliases': {'g': self._traversal_source}})
-            if bindings:
-                message.args.update({'bindings': bindings})
-            if self._sessionEnabled:
-                message = message._replace(processor='session')
-                message.args.update({'session': self._session})
-        conn = self._pool.get(True)
-        return conn.write(message)
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
deleted file mode 100644
index 3b6a760..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# 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.
-#
-from concurrent.futures import Future
-
-from gremlin_python.driver import client, serializer
-from gremlin_python.driver.remote_connection import (
-    RemoteConnection, RemoteTraversal, RemoteTraversalSideEffects)
-
-__author__ = 'David M. Brown (davebshow@gmail.com)'
-
-
-class DriverRemoteConnection(RemoteConnection):
-
-    def __init__(self, url, traversal_source, protocol_factory=None,
-                 transport_factory=None, pool_size=None, max_workers=None,
-                 username="", password="", message_serializer=None,
-                 graphson_reader=None, graphson_writer=None,
-                 headers=None):
-        if message_serializer is None:
-            message_serializer = serializer.GraphSONMessageSerializer(
-                reader=graphson_reader,
-                writer=graphson_writer)
-        self._client = client.Client(url, traversal_source,
-                                     protocol_factory=protocol_factory,
-                                     transport_factory=transport_factory,
-                                     pool_size=pool_size,
-                                     max_workers=max_workers,
-                                     message_serializer=message_serializer,
-                                     username=username,
-                                     password=password,
-                                     headers=headers)
-        self._url = self._client._url
-        self._traversal_source = self._client._traversal_source
-
-    def close(self):
-        self._client.close()
-
-    def submit(self, bytecode):
-        result_set = self._client.submit(bytecode)
-        results = result_set.all().result()
-        side_effects = RemoteTraversalSideEffects(result_set.request_id, self._client,
-                                                  result_set.status_attributes)
-        return RemoteTraversal(iter(results), side_effects)
-
-    def submitAsync(self, bytecode):
-        future = Future()
-        future_result_set = self._client.submitAsync(bytecode)
-
-        def cb(f):
-            try:
-                result_set = f.result()
-                results = result_set.all().result()
-                side_effects = RemoteTraversalSideEffects(result_set.request_id, self._client,
-                                                          result_set.status_attributes)
-                future.set_result(RemoteTraversal(iter(results), side_effects))
-            except Exception as e:
-                future.set_exception(e)
-
-        future_result_set.add_done_callback(cb)
-        return future
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py b/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
deleted file mode 100644
index ad0d467..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#
-# 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.
-#
-import abc
-import base64
-
-import six
-
-try:
-    import ujson as json
-except ImportError:
-    import json
-
-from gremlin_python.driver import serializer, request
-from gremlin_python.driver.resultset import ResultSet
-
-__author__ = 'David M. Brown (davebshow@gmail.com)'
-
-
-class GremlinServerError(Exception):
-    def __init__(self, status):
-        super(GremlinServerError, self).__init__("{0}: {1}".format(status["code"], status["message"]))
-        self._status_attributes = status["attributes"]
-        self.status_code = status["code"]
-
-    @property
-    def status_attributes(self):
-        return self._status_attributes
-
-
-@six.add_metaclass(abc.ABCMeta)
-class AbstractBaseProtocol:
-
-    @abc.abstractmethod
-    def connection_made(self, transport):
-        self._transport = transport
-
-    @abc.abstractmethod
-    def data_received(self, message):
-        pass
-
-    @abc.abstractmethod
-    def write(self, request_id, request_message):
-        pass
-
-
-class GremlinServerWSProtocol(AbstractBaseProtocol):
-
-    def __init__(self, message_serializer, username='', password=''):
-        self._message_serializer = message_serializer
-        self._username = username
-        self._password = password
-
-    def connection_made(self, transport):
-        super(GremlinServerWSProtocol, self).connection_made(transport)
-
-    def write(self, request_id, request_message):
-        message = self._message_serializer.serialize_message(
-            request_id, request_message)
-        self._transport.write(message)
-
-    def data_received(self, message, results_dict):
-        # if Gremlin Server cuts off then we get a None for the message
-        if message is None:
-            raise GremlinServerError({'code': 500, 
-                                      'message': 'Server disconnected - please try to reconnect', 'attributes': {}})
-
-        message = self._message_serializer.deserialize_message(message)
-        request_id = message['requestId']
-        result_set = results_dict[request_id] if request_id in results_dict else ResultSet(None, None)
-        status_code = message['status']['code']
-        aggregate_to = message['result']['meta'].get('aggregateTo', 'list')
-        data = message['result']['data']
-        result_set.aggregate_to = aggregate_to
-        if status_code == 407:
-            auth = b''.join([b'\x00', self._username.encode('utf-8'),
-                             b'\x00', self._password.encode('utf-8')])
-            request_message = request.RequestMessage(
-                'traversal', 'authentication',
-                {'sasl': base64.b64encode(auth).decode()})
-            self.write(request_id, request_message)
-            data = self._transport.read()
-            # Allow recursive call for auth
-            return self.data_received(data, results_dict)
-        elif status_code == 204:
-            result_set.stream.put_nowait([])
-            del results_dict[request_id]
-            return status_code
-        elif status_code in [200, 206]:
-            result_set.stream.put_nowait(data)
-            if status_code == 200:
-                result_set.status_attributes = message['status']['attributes']
-                del results_dict[request_id]
-            return status_code
-        else:
-            del results_dict[request_id]
-            raise GremlinServerError(message["status"])
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
deleted file mode 100644
index 6b6de14..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#
-# 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.
-#
-import abc
-import six
-
-from gremlin_python.driver import request
-from gremlin_python.process import traversal
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-
-@six.add_metaclass(abc.ABCMeta)
-class RemoteConnection(object):
-    def __init__(self, url, traversal_source):
-        self._url = url
-        self._traversal_source = traversal_source
-
-    @property
-    def url(self):
-        return self._url
-
-    @property
-    def traversal_source(self):
-        return self._traversal_source
-
-    @abc.abstractmethod
-    def submit(self, bytecode):
-        pass
-
-    def __repr__(self):
-        return "remoteconnection[" + self._url + "," + self._traversal_source + "]"
-
-
-class RemoteTraversal(traversal.Traversal):
-    def __init__(self, traversers, side_effects):
-        super(RemoteTraversal, self).__init__(None, None, None)
-        self.traversers = traversers
-        self._side_effects = side_effects
-
-    @property
-    def side_effects(self):
-        return self._side_effects
-
-    @side_effects.setter
-    def side_effects(self, val):
-        self._side_effects = val
-
-
-class RemoteTraversalSideEffects(traversal.TraversalSideEffects):
-    def __init__(self, side_effect, client, status_attributes):
-        self._side_effect = side_effect
-        self._client = client
-        self._keys = set()
-        self._side_effects = {}
-        self._closed = False
-        self._status_attributes = status_attributes
-
-    @property
-    def status_attributes(self):
-        return self._status_attributes
-
-    def keys(self):
-        if not self._closed:
-            message = request.RequestMessage(
-                'traversal', 'keys',
-                {'sideEffect': self._side_effect,
-                'aliases': {'g': self._client.traversal_source}})
-            self._keys = set(self._client.submit(message).all().result())
-        return self._keys
-
-    def get(self, key):
-
-        if not self._side_effects.get(key):
-            if not self._closed:
-                message = request.RequestMessage(
-                    'traversal', 'gather',
-                    {'sideEffect': self._side_effect, 'sideEffectKey': key,
-                     'aliases': {'g': self._client.traversal_source}})
-                results = self._aggregate_results(self._client.submit(message))
-                self._side_effects[key] = results
-                self._keys.add(key)
-            else:
-                return None
-        return self._side_effects[key]
-
-    def close(self):
-        if not self._closed:
-            message = request.RequestMessage(
-                'traversal', 'close',
-                {'sideEffect': self._side_effect,
-                 'aliases': {'g': self._client._traversal_source}})
-            results = self._client.submit(message).all().result()
-        self._closed = True
-        return results
-
-    def _aggregate_results(self, result_set):
-        aggregates = {'list': [], 'set': set(), 'map': {}, 'bulkset': {},
-                      'none': None}
-        results = None
-        for msg in result_set:
-            if results is None:
-                aggregate_to = result_set.aggregate_to
-                results = aggregates.get(aggregate_to, [])
-            # on first message, get the right result data structure
-            # if there is no update to a structure, then the item is the result
-            if results is None:
-                results = msg[0]
-            # updating a map is different than a list or a set
-            elif isinstance(results, dict):
-                if aggregate_to == "map":
-                    for item in msg:
-                        results.update(item)
-                else:
-                    for item in msg:
-                        results[item.object] = item.bulk
-            elif isinstance(results, set):
-                results.update(msg)
-            # flat add list to result list
-            else:
-                results += msg
-        if results is None:
-            results = []
-        return results
-
-
-class RemoteStrategy(traversal.TraversalStrategy):
-    def __init__(self, remote_connection):
-        traversal.TraversalStrategy.__init__(self)
-        self.remote_connection = remote_connection
-
-    def apply(self, traversal):
-        if traversal.traversers is None:
-            remote_traversal = self.remote_connection.submit(traversal.bytecode)
-            traversal.remote_results = remote_traversal
-            traversal.side_effects = remote_traversal.side_effects
-            traversal.traversers = remote_traversal.traversers
-
-    def apply_async(self, traversal):
-        if traversal.traversers is None:
-            traversal.remote_results = self.remote_connection.submitAsync(
-                traversal.bytecode)
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py b/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
deleted file mode 100644
index c7b6b4d..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
+++ /dev/null
@@ -1,293 +0,0 @@
-#
-# 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.
-#
-try:
-    import ujson as json
-except ImportError:
-    import json
-import struct
-import uuid
-import io
-
-from gremlin_python.structure.io import graphbinaryV1
-from gremlin_python.structure.io import graphsonV2d0
-from gremlin_python.structure.io import graphsonV3d0
-
-__author__ = 'David M. Brown (davebshow@gmail.com)'
-
-
-class Processor:
-    """Base class for OpProcessor serialization system."""
-
-    def __init__(self, writer):
-        self._writer = writer
-
-    def get_op_args(self, op, args):
-        op_method = getattr(self, op, None)
-        if not op_method:
-            raise Exception("Processor does not support op: {}".format(op))
-        return op_method(args)
-
-
-class Standard(Processor):
-
-    def authentication(self, args):
-        return args
-
-    def eval(self, args):
-        return args
-
-
-class Session(Processor):
-
-    def authentication(self, args):
-        return args
-
-    def eval(self, args):
-        return args
-
-    def close(self, args):
-        return args
-
-class Traversal(Processor):
-
-    def authentication(self, args):
-        return args
-
-    def bytecode(self, args):
-        gremlin = args['gremlin']
-        args['gremlin'] = self._writer.toDict(gremlin)
-        aliases = args.get('aliases', '')
-        if not aliases:
-            aliases = {'g': 'g'}
-        args['aliases'] = aliases
-        return args
-
-    def close(self, args):
-        return self.keys(args)
-
-    def gather(self, args):
-        side_effect = uuid.UUID(args['sideEffect'])
-        args['sideEffect'] = self._writer.toDict(side_effect)
-        aliases = args.get('aliases', '')
-        if not aliases:
-            aliases = {'g': 'g'}
-        args['aliases'] = aliases
-        return args
-
-    def keys(self, args):
-        side_effect = uuid.UUID(args['sideEffect'])
-        args['sideEffect'] = self._writer.toDict(side_effect)
-        return args
-
-
-class GraphSONMessageSerializer(object):
-    """
-    Message serializer for GraphSON. Allow users to pass custom reader,
-    writer, and version kwargs for custom serialization. Otherwise,
-    use current GraphSON version as default.
-    """
-
-    # KEEP TRACK OF CURRENT DEFAULTS
-    DEFAULT_READER_CLASS = graphsonV3d0.GraphSONReader
-    DEFAULT_WRITER_CLASS = graphsonV3d0.GraphSONWriter
-    DEFAULT_VERSION = b"application/vnd.gremlin-v3.0+json"
-
-    def __init__(self, reader=None, writer=None, version=None):
-        if not version:
-            version = self.DEFAULT_VERSION
-        self._version = version
-        if not reader:
-            reader = self.DEFAULT_READER_CLASS()
-        self._graphson_reader = reader
-        if not writer:
-            writer = self.DEFAULT_WRITER_CLASS()
-        self.standard = Standard(writer)
-        self.traversal = Traversal(writer)
-        self.session = Session(writer)
-
-    @property
-    def version(self):
-        """Read only property"""
-        return self._version
-
-    def get_processor(self, processor):
-        processor = getattr(self, processor, None)
-        if not processor:
-            raise Exception("Unknown processor")
-        return processor
-
-    def serialize_message(self, request_id, request_message):
-        processor = request_message.processor
-        op = request_message.op
-        args = request_message.args
-        if not processor:
-            processor_obj = self.get_processor('standard')
-        else:
-            processor_obj = self.get_processor(processor)
-        args = processor_obj.get_op_args(op, args)
-        message = self.build_message(request_id, processor, op, args)
-        return message
-
-    def build_message(self, request_id, processor, op, args):
-        message = {
-            'requestId': {'@type': 'g:UUID', '@value': request_id},
-            'processor': processor,
-            'op': op,
-            'args': args
-        }
-        return self.finalize_message(message, b"\x21", self.version)
-
-    def finalize_message(self, message, mime_len, mime_type):
-        message = json.dumps(message)
-        message = b''.join([mime_len, mime_type, message.encode('utf-8')])
-        return message
-
-    def deserialize_message(self, message):
-        msg = json.loads(message.decode('utf-8'))
-        return self._graphson_reader.toObject(msg)
-
-
-class GraphSONSerializersV2d0(GraphSONMessageSerializer):
-    """Message serializer for GraphSON 2.0"""
-    def __init__(self):
-        reader = graphsonV2d0.GraphSONReader()
-        writer = graphsonV2d0.GraphSONWriter()
-        version = b"application/vnd.gremlin-v2.0+json"
-        super(GraphSONSerializersV2d0, self).__init__(reader, writer, version)
-
-
-class GraphSONSerializersV3d0(GraphSONMessageSerializer):
-    """Message serializer for GraphSON 3.0"""
-    def __init__(self):
-        reader = graphsonV3d0.GraphSONReader()
-        writer = graphsonV3d0.GraphSONWriter()
-        version = b"application/vnd.gremlin-v3.0+json"
-        super(GraphSONSerializersV3d0, self).__init__(reader, writer, version)
-
-
-class GraphBinarySerializersV1(object):
-    DEFAULT_READER_CLASS = graphbinaryV1.GraphBinaryReader
-    DEFAULT_WRITER_CLASS = graphbinaryV1.GraphBinaryWriter
-    DEFAULT_VERSION = b"application/vnd.graphbinary-v1.0"
-
-    max_int64 = 0xFFFFFFFFFFFFFFFF
-    header_struct = struct.Struct('>b32sBQQ')
-    header_pack = header_struct.pack
-    int_pack = graphbinaryV1.int32_pack
-    int32_unpack = struct.Struct(">i").unpack
-
-    def __init__(self, reader=None, writer=None, version=None):
-        if not version:
-            version = self.DEFAULT_VERSION
-        self._version = version
-        if not reader:
-            reader = self.DEFAULT_READER_CLASS()
-        self._graphbinary_reader = reader
-        if not writer:
-            writer = self.DEFAULT_WRITER_CLASS()
-        self._graphbinary_writer = writer
-        self.standard = Standard(writer)
-        self.traversal = Traversal(writer)
-
-    @property
-    def version(self):
-        """Read only property"""
-        return self._version
-
-    def get_processor(self, processor):
-        processor = getattr(self, processor, None)
-        if not processor:
-            raise Exception("Unknown processor")
-        return processor
-
-    def serialize_message(self, request_id, request_message):
-        processor = request_message.processor
-        op = request_message.op
-        args = request_message.args
-        if not processor:
-            processor_obj = self.get_processor('standard')
-        else:
-            processor_obj = self.get_processor(processor)
-        args = processor_obj.get_op_args(op, args)
-        message = self.build_message(request_id, processor, op, args)
-        return message
-
-    def build_message(self, request_id, processor, op, args):
-        message = {
-            'requestId': request_id,
-            'processor': processor,
-            'op': op,
-            'args': args
-        }
-        return self.finalize_message(message, 0x20, self.version)
-
-    def finalize_message(self, message, mime_len, mime_type):
-        ba = bytearray()
-
-        request_id = uuid.UUID(message['requestId'])
-        ba.extend(self.header_pack(mime_len, mime_type, 0x81,
-                                   (request_id.int >> 64) & self.max_int64, request_id.int & self.max_int64))
-
-        op_bytes = message['op'].encode("utf-8")
-        ba.extend(self.int_pack(len(op_bytes)))
-        ba.extend(op_bytes)
-
-        processor_bytes = message['processor'].encode("utf-8")
-        ba.extend(self.int_pack(len(processor_bytes)))
-        ba.extend(processor_bytes)
-
-        args = message["args"]
-        ba.extend(self.int_pack(len(args)))
-        for k, v in args.items():
-            self._graphbinary_writer.toDict(k, ba)
-
-            # processor_obj.get_op_args in serialize_message() seems to already handle bytecode. in python 3
-            # because bytearray isn't bound to a type in graphbinary it falls through the writeObject() and
-            # just works but python 2 bytearray is bound to ByteBufferType so it writes DataType.bytebuffer
-            # rather than DataType.bytecode and the server gets confused. special casing this for now until
-            # it can be refactored
-            if k == "gremlin" or k == "sideEffect":
-                ba.extend(v)
-            else:
-                self._graphbinary_writer.toDict(v, ba)
-
-        return bytes(ba)
-
-    def deserialize_message(self, message):
-        b = io.BytesIO(message)
-
-        b.read(1)  # version
-
-        request_id = str(self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.uuid))
-        status_code = self.int32_unpack(b.read(4))[0]
-        status_msg = self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.string)
-        status_attrs = self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.map, nullable=False)
-        meta_attrs = self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.map, nullable=False)
-        result = self._graphbinary_reader.toObject(b)
-
-        b.close()
-
-        msg = {'requestId': request_id,
-               'status': {'code': status_code,
-                          'message': status_msg,
-                          'attributes': status_attrs},
-               'result': {'meta': meta_attrs,
-                          'data': result}}
-
-        return msg
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
deleted file mode 100644
index 8988b79..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
+++ /dev/null
@@ -1,210 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-from gremlin_python.process.traversal import TraversalStrategy
-
-
-#########################
-# DECORATION STRATEGIES #
-#########################
-
-class ConnectiveStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy")
-
-
-class ElementIdStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy")
-
-
-# EventStrategy doesn't make sense outside JVM traversal machine
-
-class HaltedTraverserStrategy(TraversalStrategy):
-    def __init__(self, halted_traverser_factory=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy")
-        if halted_traverser_factory is not None:
-            self.configuration["haltedTraverserFactory"] = halted_traverser_factory
-
-
-class OptionsStrategy(TraversalStrategy):
-    def __init__(self, options=None):
-        TraversalStrategy.__init__(self, configuration=options, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy")
-
-
-class PartitionStrategy(TraversalStrategy):
-    def __init__(self, partition_key=None, write_partition=None, read_partitions=None, include_meta_properties=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy")
-        if partition_key is not None:
-            self.configuration["partitionKey"] = partition_key
-        if write_partition is not None:
-            self.configuration["writePartition"] = write_partition
-        if write_partition is not None:
-            self.configuration["readPartitions"] = read_partitions
-        if include_meta_properties is not None:
-            self.configuration["includeMetaProperties"] = include_meta_properties
-
-
-class SubgraphStrategy(TraversalStrategy):
-
-    def __init__(self, vertices=None, edges=None, vertex_properties=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy")
-        if vertices is not None:
-            self.configuration["vertices"] = vertices
-        if edges is not None:
-            self.configuration["edges"] = edges
-        if vertex_properties is not None:
-            self.configuration["vertexProperties"] = vertex_properties
-
-
-class VertexProgramStrategy(TraversalStrategy):
-    def __init__(self, graph_computer=None, workers=None, persist=None, result=None, vertices=None, edges=None,
-                 configuration=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy")
-        if graph_computer is not None:
-            self.configuration["graphComputer"] = graph_computer
-        if workers is not None:
-            self.configuration["workers"] = workers
-        if persist is not None:
-            self.configuration["persist"] = persist
-        if result is not None:
-            self.configuration["result"] = result
-        if vertices is not None:
-            self.configuration["vertices"] = vertices
-        if edges is not None:
-            self.configuration["edges"] = edges
-        if configuration is not None:
-            self.configuration.update(configuration)
-
-
-###########################
-# FINALIZATION STRATEGIES #
-###########################
-
-class MatchAlgorithmStrategy(TraversalStrategy):
-    def __init__(self, match_algorithm=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy")
-        if match_algorithm is not None:
-            self.configuration["matchAlgorithm"] = match_algorithm
-
-
-###########################
-# OPTIMIZATION STRATEGIES #
-###########################
-
-class AdjacentToIncidentStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy")
-
-
-class FilterRankingStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy")
-
-
-class IdentityRemovalStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy")
-
-
-class IncidentToAdjacentStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy")
-
-
-class InlineFilterStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.InlineFilterStrategy")
-
-
-class LazyBarrierStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.LazyBarrierStrategy")
-
-
-class MatchPredicateStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy")
-
-
-class OrderLimitStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy")
-
-
-class PathProcessorStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy")
-
-
-class PathRetractionStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy")
-
-
-class CountStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy")
-
-
-class RepeatUnrollStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy")
-
-
-class GraphFilterStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy")
-
-
-
-class EarlyLimitStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy")
-
-###########################
-# VERIFICATION STRATEGIES #
-###########################
-
-
-class LambdaRestrictionStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy")
-
-
-class ReadOnlyStrategy(TraversalStrategy):
-    def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy")
-
-
-class EdgeLabelVerificationStrategy(TraversalStrategy):
-    def __init__(self, log_warning=False, throw_exception=False):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy")
-        self.configuration["logWarning"] = log_warning
-        self.configuration["throwException"] = throw_exception
-
-
-class ReservedKeysVerificationStrategy(TraversalStrategy):
-    def __init__(self, log_warning=False, throw_exception=False, keys=["id", "label"]):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy")
-        self.configuration["logWarning"] = log_warning
-        self.configuration["throwException"] = throw_exception
-        self.configuration["keys"] = keys
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
deleted file mode 100644
index ff0d121..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ /dev/null
@@ -1,736 +0,0 @@
-#
-# 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.
-#
-
-import copy
-from aenum import Enum
-from .. import statics
-from ..statics import long
-
-class Traversal(object):
-    def __init__(self, graph, traversal_strategies, bytecode):
-        self.graph = graph
-        self.traversal_strategies = traversal_strategies
-        self.bytecode = bytecode
-        self.side_effects = TraversalSideEffects()
-        self.traversers = None
-        self.last_traverser = None
-
-    def __repr__(self):
-        return str(self.bytecode)
-
-    def __eq__(self, other):
-        if isinstance(other, self.__class__):
-            return self.bytecode == other.bytecode
-        else:
-            return False
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        if self.traversers is None:
-            self.traversal_strategies.apply_strategies(self)
-        if self.last_traverser is None:
-            self.last_traverser = next(self.traversers)
-        object = self.last_traverser.object
-        self.last_traverser.bulk = self.last_traverser.bulk - 1
-        if self.last_traverser.bulk <= 0:
-            self.last_traverser = None
-        return object
-
-    def toList(self):
-        return list(iter(self))
-
-    def toSet(self):
-        return set(iter(self))
-
-    def iterate(self):
-        self.bytecode.add_step("none")
-        while True:
-            try: self.nextTraverser()
-            except StopIteration: return self
-
-    def nextTraverser(self):
-        if self.traversers is None:
-            self.traversal_strategies.apply_strategies(self)
-        if self.last_traverser is None:
-            return next(self.traversers)
-        else:
-            temp = self.last_traverser
-            self.last_traverser = None
-            return temp
-
-    def hasNext(self):
-        if self.traversers is None:
-            self.traversal_strategies.apply_strategies(self)
-        if self.last_traverser is None:
-            try: self.last_traverser = next(self.traversers)
-            except StopIteration: return False
-        return not(self.last_traverser is None) and self.last_traverser.bulk > 0
-
-    def next(self, amount=None):
-        if amount is None:
-            return self.__next__()
-        else:
-            count = 0
-            tempList = []
-            while count < amount:
-                count = count + 1
-                try: temp = self.__next__()
-                except StopIteration: return tempList
-                tempList.append(temp)
-            return tempList
-
-    def promise(self, cb=None):
-        self.traversal_strategies.apply_async_strategies(self)
-        future_traversal = self.remote_results
-        future = type(future_traversal)()
-        def process(f):
-            try:
-                traversal = f.result()
-            except Exception as e:
-                future.set_exception(e)
-            else:
-                self.traversers = iter(traversal.traversers)
-                self.side_effects = traversal.side_effects
-                if cb:
-                    try:
-                        result = cb(self)
-                    except Exception as e:
-                        future.set_exception(e)
-                    else:
-                        future.set_result(result)
-                else:
-                    future.set_result(self)
-        future_traversal.add_done_callback(process)
-        return future
-
-
-Barrier = Enum('Barrier', ' normSack')
-
-statics.add_static('normSack', Barrier.normSack)
-
-Cardinality = Enum('Cardinality', ' list_ set_ single')
-
-statics.add_static('single', Cardinality.single)
-statics.add_static('list_', Cardinality.list_)
-statics.add_static('set_', Cardinality.set_)
-
-Column = Enum('Column', ' keys values')
-
-statics.add_static('keys', Column.keys)
-statics.add_static('values', Column.values)
-
-Direction = Enum('Direction', ' BOTH IN OUT')
-
-statics.add_static('OUT', Direction.OUT)
-statics.add_static('IN', Direction.IN)
-statics.add_static('BOTH', Direction.BOTH)
-
-GraphSONVersion = Enum('GraphSONVersion', ' V1_0 V2_0 V3_0')
-
-statics.add_static('V1_0', GraphSONVersion.V1_0)
-statics.add_static('V2_0', GraphSONVersion.V2_0)
-statics.add_static('V3_0', GraphSONVersion.V3_0)
-
-GryoVersion = Enum('GryoVersion', ' V1_0 V3_0')
-
-statics.add_static('V1_0', GryoVersion.V1_0)
-statics.add_static('V3_0', GryoVersion.V3_0)
-
-Order = Enum('Order', ' asc decr desc incr shuffle')
-
-statics.add_static('incr', Order.incr)
-statics.add_static('decr', Order.decr)
-statics.add_static('shuffle', Order.shuffle)
-statics.add_static('asc', Order.asc)
-statics.add_static('desc', Order.desc)
-
-Pick = Enum('Pick', ' any none')
-
-statics.add_static('any', Pick.any)
-statics.add_static('none', Pick.none)
-
-Pop = Enum('Pop', ' all_ first last mixed')
-
-statics.add_static('first', Pop.first)
-statics.add_static('last', Pop.last)
-statics.add_static('all_', Pop.all_)
-statics.add_static('mixed', Pop.mixed)
-
-Scope = Enum('Scope', ' global_ local')
-
-statics.add_static('global_', Scope.global_)
-statics.add_static('local', Scope.local)
-
-
-T = Enum('T', ' id id_ key label value')
-
-statics.add_static('id', T.id)
-statics.add_static('label', T.label)
-statics.add_static('id_', T.id_)
-statics.add_static('key', T.key)
-statics.add_static('value', T.value)
-
-
-Operator = Enum('Operator', ' addAll and_ assign div max max_ min min_ minus mult or_ sum sum_ sumLong')
-
-statics.add_static('sum_', Operator.sum_)
-statics.add_static('sum', Operator.sum_)
-statics.add_static('minus', Operator.minus)
-statics.add_static('mult', Operator.mult)
-statics.add_static('div', Operator.div)
-statics.add_static('min', Operator.min_)
-statics.add_static('min_', Operator.min_)
-statics.add_static('max_', Operator.max_)
-statics.add_static('assign', Operator.assign)
-statics.add_static('and_', Operator.and_)
-statics.add_static('or_', Operator.or_)
-statics.add_static('addAll', Operator.addAll)
-statics.add_static('sumLong', Operator.sumLong)
-
-
-class P(object):
-    def __init__(self, operator, value, other=None):
-        self.operator = operator
-        self.value = value
-        self.other = other
-
-    @staticmethod
-    def between(*args):
-        return P("between", *args)
-
-    @staticmethod
-    def eq(*args):
-        return P("eq", *args)
-
-    @staticmethod
-    def gt(*args):
-        return P("gt", *args)
-
-    @staticmethod
-    def gte(*args):
-        return P("gte", *args)
-
-    @staticmethod
-    def inside(*args):
-        return P("inside", *args)
-
-    @staticmethod
-    def lt(*args):
-        return P("lt", *args)
-
-    @staticmethod
-    def lte(*args):
-        return P("lte", *args)
-
-    @staticmethod
-    def neq(*args):
-        return P("neq", *args)
-
-    @staticmethod
-    def not_(*args):
-        return P("not", *args)
-
-    @staticmethod
-    def outside(*args):
-        return P("outside", *args)
-
-    @staticmethod
-    def test(*args):
-        return P("test", *args)
-
-    @staticmethod
-    def within(*args):
-        if len(args) == 1 and type(args[0]) == list:
-            return P("within", args[0])
-        else:
-            return P("within", list(args))
-        
-    @staticmethod
-    def without(*args):
-        if len(args) == 1 and type(args[0]) == list:
-            return P("without", args[0])
-        else:
-            return P("without", list(args))
-
-    def and_(self, arg):
-        return P("and", self, arg)
-
-    def or_(self, arg):
-        return P("or", self, arg)
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
-
-    def __repr__(self):
-        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
-
-
-def between(*args):
-    return P.between(*args)
-
-
-def eq(*args):
-    return P.eq(*args)
-
-
-def gt(*args):
-    return P.gt(*args)
-
-
-def gte(*args):
-    return P.gte(*args)
-
-
-def inside(*args):
-    return P.inside(*args)
-
-
-def lt(*args):
-    return P.lt(*args)
-
-
-def lte(*args):
-    return P.lte(*args)
-
-
-def neq(*args):
-    return P.neq(*args)
-
-
-def not_(*args):
-    return P.not_(*args)
-
-
-def outside(*args):
-    return P.outside(*args)
-
-
-def test(*args):
-    return P.test(*args)
-
-
-def within(*args):
-    return P.within(*args)
-
-
-def without(*args):
-    return P.without(*args)
-
-
-statics.add_static('between', between)
-
-statics.add_static('eq', eq)
-
-statics.add_static('gt', gt)
-
-statics.add_static('gte', gte)
-
-statics.add_static('inside', inside)
-
-statics.add_static('lt', lt)
-
-statics.add_static('lte', lte)
-
-statics.add_static('neq', neq)
-
-statics.add_static('not_', not_)
-
-statics.add_static('outside', outside)
-
-statics.add_static('test', test)
-
-statics.add_static('within', within)
-
-statics.add_static('without', without)
-
-
-class TextP(P):
-    def __init__(self, operator, value, other=None):
-        P.__init__(self, operator, value, other)
-
-    @staticmethod
-    def containing(*args):
-        return TextP("containing", *args)
-
-    @staticmethod
-    def endingWith(*args):
-        return TextP("endingWith", *args)
-
-    @staticmethod
-    def notContaining(*args):
-        return TextP("notContaining", *args)
-
-    @staticmethod
-    def notEndingWith(*args):
-        return TextP("notEndingWith", *args)
-
-    @staticmethod
-    def notStartingWith(*args):
-        return TextP("notStartingWith", *args)
-
-    @staticmethod
-    def startingWith(*args):
-        return TextP("startingWith", *args)
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
-
-    def __repr__(self):
-        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
-
-
-def containing(*args):
-    return TextP.containing(*args)
-
-
-def endingWith(*args):
-    return TextP.endingWith(*args)
-
-
-def notContaining(*args):
-    return TextP.notContaining(*args)
-
-
-def notEndingWith(*args):
-    return TextP.notEndingWith(*args)
-
-
-def notStartingWith(*args):
-    return TextP.notStartingWith(*args)
-
-
-def startingWith(*args):
-    return TextP.startingWith(*args)
-
-
-statics.add_static('containing', containing)
-
-statics.add_static('endingWith', endingWith)
-
-statics.add_static('notContaining', notContaining)
-
-statics.add_static('notEndingWith', notEndingWith)
-
-statics.add_static('notStartingWith', notStartingWith)
-
-statics.add_static('startingWith', startingWith)
-
-
-
-
-'''
-IO
-'''
-
-
-class IO(object):
-
-    graphml = "graphml"
-
-    graphson = "graphson"
-
-    gryo = "gryo"
-
-    reader = "~tinkerpop.io.reader"
-
-    registry = "~tinkerpop.io.registry"
-
-    writer = "~tinkerpop.io.writer"
-
-
-'''
-ConnectedComponent
-'''
-
-
-class ConnectedComponent(object):
-
-    component = "gremlin.connectedComponentVertexProgram.component"
-
-    edges = "~tinkerpop.connectedComponent.edges"
-
-    propertyName = "~tinkerpop.connectedComponent.propertyName"
-
-
-'''
-ShortestPath
-'''
-
-
-class ShortestPath(object):
-
-    distance = "~tinkerpop.shortestPath.distance"
-
-    edges = "~tinkerpop.shortestPath.edges"
-
-    includeEdges = "~tinkerpop.shortestPath.includeEdges"
-
-    maxDistance = "~tinkerpop.shortestPath.maxDistance"
-
-    target = "~tinkerpop.shortestPath.target"
-
-
-'''
-PageRank
-'''
-
-
-class PageRank(object):
-
-    edges = "~tinkerpop.pageRank.edges"
-
-    propertyName = "~tinkerpop.pageRank.propertyName"
-
-    times = "~tinkerpop.pageRank.times"
-
-
-'''
-PeerPressure
-'''
-
-
-class PeerPressure(object):
-
-    edges = "~tinkerpop.peerPressure.edges"
-
-    propertyName = "~tinkerpop.peerPressure.propertyName"
-
-    times = "~tinkerpop.peerPressure.times"
-
-
-'''
-TRAVERSER
-'''
-
-
-class Traverser(object):
-    def __init__(self, object, bulk=None):
-        if bulk is None:
-            bulk = long(1)
-        self.object = object
-        self.bulk = bulk
-
-    def __repr__(self):
-        return str(self.object)
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.object == other.object
-
-
-'''
-TRAVERSAL SIDE-EFFECTS
-'''
-
-
-class TraversalSideEffects(object):
-    def keys(self):
-        return set()
-
-    def get(self, key):
-        raise KeyError(key)
-
-    def __getitem__(self, key):
-        return self.get(key)
-
-    def __repr__(self):
-        return "sideEffects[size:" + str(len(self.keys())) + "]"
-
-
-'''
-TRAVERSAL STRATEGIES
-'''
-
-
-class TraversalStrategies(object):
-    global_cache = {}
-
-    def __init__(self, traversal_strategies=None):
-        self.traversal_strategies =             traversal_strategies.traversal_strategies if traversal_strategies is not None else []
-
-    def add_strategies(self, traversal_strategies):
-        self.traversal_strategies = self.traversal_strategies + traversal_strategies
-
-    def apply_strategies(self, traversal):
-        for traversal_strategy in self.traversal_strategies:
-            traversal_strategy.apply(traversal)
-
-    def apply_async_strategies(self, traversal):
-        for traversal_strategy in self.traversal_strategies:
-            traversal_strategy.apply_async(traversal)
-
-    def __repr__(self):
-        return str(self.traversal_strategies)
-
-
-class TraversalStrategy(object):
-    def __init__(self, strategy_name=None, configuration=None, fqcn=None):
-        self.fqcn = fqcn
-        self.strategy_name = type(self).__name__ if strategy_name is None else strategy_name
-        self.configuration = {} if configuration is None else configuration
-
-    def apply(self, traversal):
-        return
-
-    def apply_async(self, traversal):
-        return
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__)
-
-    def __hash__(self):
-        return hash(self.strategy_name)
-
-    def __repr__(self):
-        return self.strategy_name
-
-
-'''
-BYTECODE
-'''
-
-
-class Bytecode(object):
-    def __init__(self, bytecode=None):
-        self.source_instructions = []
-        self.step_instructions = []
-        self.bindings = {}
-        if bytecode is not None:
-            self.source_instructions = list(bytecode.source_instructions)
-            self.step_instructions = list(bytecode.step_instructions)
-
-    def add_source(self, source_name, *args):
-        instruction = [source_name]
-        for arg in args:
-            instruction.append(self.__convertArgument(arg))
-        self.source_instructions.append(instruction)
-
-    def add_step(self, step_name, *args):
-        instruction = [step_name]
-        for arg in args:
-            instruction.append(self.__convertArgument(arg))
-        self.step_instructions.append(instruction)
-
-    def __eq__(self, other):
-        if isinstance(other, self.__class__):
-            return self.source_instructions == other.source_instructions and self.step_instructions == other.step_instructions
-        else:
-            return False
-
-    def __copy__(self):
-        bb = Bytecode()
-        bb.source_instructions = self.source_instructions
-        bb.step_instructions = self.step_instructions
-        bb.bindings = self.bindings
-        return bb
-
-    def __deepcopy__(self, memo={}):
-        bb = Bytecode()
-        bb.source_instructions = copy.deepcopy(self.source_instructions, memo)
-        bb.step_instructions = copy.deepcopy(self.step_instructions, memo)
-        bb.bindings = copy.deepcopy(self.bindings, memo)
-        return bb
-
-    def __convertArgument(self,arg):
-        if isinstance(arg, Traversal):
-            self.bindings.update(arg.bytecode.bindings)
-            return arg.bytecode
-        elif isinstance(arg, dict):
-            newDict = {}
-            for key in arg:
-                newDict[self.__convertArgument(key)] = self.__convertArgument(arg[key])
-            return newDict
-        elif isinstance(arg, list):
-            newList = []
-            for item in arg:
-                newList.append(self.__convertArgument(item))
-            return newList
-        elif isinstance(arg, set):
-            newSet = set()
-            for item in arg:
-                newSet.add(self.__convertArgument(item))
-            return newSet
-        elif isinstance(arg, Binding):
-            self.bindings[arg.key] = arg.value
-            return Binding(arg.key, self.__convertArgument(arg.value))
-        else:
-            return arg
-
-    def __repr__(self):
-        return (str(self.source_instructions) if len(self.source_instructions) > 0 else "") + \
-               (str(self.step_instructions) if len(self.step_instructions) > 0 else "")
-
-
-'''
-BINDINGS
-'''
-
-
-class Bindings(object):
-
-    @staticmethod
-    def of(key, value):
-        if not isinstance(key, str):
-            raise TypeError("Key must be str")
-        return Binding(key, value)
-
-
-class Binding(object):
-    def __init__(self, key, value):
-        self.key = key
-        self.value = value
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value
-
-    def __hash__(self):
-        return hash(self.key) + hash(self.value)
-
-    def __repr__(self):
-        return "binding[" + self.key + "=" + str(self.value) + "]"
-
-
-'''
-WITH OPTIONS
-'''
-
-
-class WithOptions(object):
-
-    tokens = "~tinkerpop.valueMap.tokens"
-
-    none = 0
-
-    ids = 1
-
-    labels = 2
-
-    keys = 4
-
-    values = 8
-
-    all = 15
-
-    indexer = "~tinkerpop.index.indexer"
-
-    list = 0
-
-    map = 1
-
diff --git a/gremlin-python/src/main/jython/gremlin_python/statics.py b/gremlin-python/src/main/jython/gremlin_python/statics.py
deleted file mode 100644
index 221e166..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/statics.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#
-# 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.
-#
-
-from types import FunctionType
-
-import six
-from aenum import Enum
-
-
-if six.PY3:
-    class long(int): pass
-    FloatType = float
-    IntType = int
-    LongType = long
-    TypeType = type
-    ListType = list
-    DictType = dict
-    SetType = set
-    ByteBufferType = bytes
-else:
-    long = long
-    SetType = set
-    ByteBufferType = bytearray
-    from types import FloatType
-    from types import IntType
-    from types import LongType
-    from types import TypeType
-    from types import ListType
-    from types import DictType
-    from types import TypeType
-
-
-class timestamp(float):
-    """
-    In Python a timestamp is simply a float. This dummy class (similar to long), allows users to wrap a float
-    in a GLV script to make sure the value is serialized as a Gremlin timestamp.
-    """
-    pass
-
-
-class SingleByte(int):
-    """
-    Provides a way to pass a single byte via Gremlin.
-    """
-    def __new__(cls, b):
-        if -128 <= b < 128:
-            int.__new__(cls, b)
-        else:
-            raise ValueError("value must be between -128 and 127 inclusive")
-
-
-class SingleChar(str):
-    """
-    Provides a way to pass a single character via Gremlin.
-    """
-    def __new__(cls, c):
-        if len(b) == 1:
-            str.__new__(cls, c)
-        else:
-            raise ValueError("string must contain a single character")
-
-
-class GremlinType(object):
-    """
-    Provides a way to represent a "Java class" for Gremlin.
-    """
-    def __init__(self, gremlin_type):
-        self.gremlin_type = gremlin_type
-        
-
-staticMethods = {}
-staticEnums = {}
-default_lambda_language = "gremlin-python"
-
-
-def add_static(key, value):
-    if isinstance(value, Enum):
-        staticEnums[key] = value
-    else:
-        staticMethods[key] = value
-
-
-def load_statics(global_dict):
-    for key in staticMethods:
-        global_dict[key] = staticMethods[key]
-    for key in staticEnums:
-        global_dict[key] = staticEnums[key]
-
-
-def unload_statics(global_dict):
-    for key in staticMethods:
-        if key in global_dict:
-            del global_dict[key]
-    for key in staticEnums:
-        if key in global_dict:
-            del global_dict[key]
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py
deleted file mode 100644
index c06ee12..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py
+++ /dev/null
@@ -1,1083 +0,0 @@
-"""
-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.
-"""
-
-import six
-import datetime
-import calendar
-import uuid
-import math
-import io
-import struct
-from collections import OrderedDict
-import logging
-
-from struct import pack, unpack
-from aenum import Enum
-from datetime import timedelta
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, \
-                                   SingleByte, ByteBufferType, GremlinType, SingleChar
-from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Cardinality, Column, Direction, Operator, \
-                                             Order, Pick, Pop, P, Scope, TextP, Traversal, Traverser, \
-                                             TraversalStrategy, T
-from gremlin_python.process.graph_traversal import GraphTraversal
-from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path
-
-log = logging.getLogger(__name__)
-
-# When we fall back to a superclass's serializer, we iterate over this map.
-# We want that iteration order to be consistent, so we use an OrderedDict,
-# not a dict.
-_serializers = OrderedDict()
-_deserializers = {}
-
-
-class DataType(Enum):
-    null = 0xfe
-    int = 0x01
-    long = 0x02
-    string = 0x03
-    date = 0x04
-    timestamp = 0x05
-    clazz = 0x06
-    double = 0x07
-    float = 0x08
-    list = 0x09
-    map = 0x0a
-    set = 0x0b
-    uuid = 0x0c
-    edge = 0x0d
-    path = 0x0e
-    property = 0x0f
-    graph = 0x10                  # not supported - no graph object in python yet
-    vertex = 0x11
-    vertexproperty = 0x12
-    barrier = 0x13
-    binding = 0x14
-    bytecode = 0x15
-    cardinality = 0x16
-    column = 0x17
-    direction = 0x18
-    operator = 0x19
-    order = 0x1a
-    pick = 0x1b
-    pop = 0x1c
-    lambda_ = 0x1d
-    p = 0x1e
-    scope = 0x1f
-    t = 0x20
-    traverser = 0x21
-    bigdecimal = 0x22             # todo
-    biginteger = 0x23             # todo
-    byte = 0x24
-    bytebuffer = 0x25
-    short = 0x26                  # todo
-    boolean = 0x27
-    textp = 0x28
-    traversalstrategy = 0x29
-    bulkset = 0x2a
-    tree = 0x2b                   # not supported - no tree object in Python yet
-    metrics = 0x2c
-    traversalmetrics = 0x2d
-    char = 0x80
-    duration = 0x81
-    inetaddress = 0x82            # todo
-    instant = 0x83                # todo
-    localdate = 0x84              # todo
-    localdatetime = 0x85          # todo
-    localtime = 0x86              # todo
-    monthday = 0x87               # todo
-    offsetdatetime = 0x88         # todo
-    offsettime = 0x89             # todo
-    period = 0x8a                 # todo
-    year = 0x8b                   # todo
-    yearmonth = 0x8c              # todo
-    zonedatetime = 0x8d           # todo
-    zoneoffset = 0x8e             # todo
-    custom = 0x00                 # todo
-
-
-NULL_BYTES = [DataType.null.value, 0x01]
-
-
-def _make_packer(format_string):
-    packer = struct.Struct(format_string)
-    pack = packer.pack
-    unpack = lambda s: packer.unpack(s)[0]
-    return pack, unpack
-
-
-int64_pack, int64_unpack = _make_packer('>q')
-int32_pack, int32_unpack = _make_packer('>i')
-int8_pack, int8_unpack = _make_packer('>b')
-uint64_pack, uint64_unpack = _make_packer('>Q')
-uint8_pack, uint8_unpack = _make_packer('>B')
-float_pack, float_unpack = _make_packer('>f')
-double_pack, double_unpack = _make_packer('>d')
-
-
-class GraphBinaryTypeType(type):
-    def __new__(mcs, name, bases, dct):
-        cls = super(GraphBinaryTypeType, mcs).__new__(mcs, name, bases, dct)
-        if not name.startswith('_'):
-            if cls.python_type:
-                _serializers[cls.python_type] = cls
-            if cls.graphbinary_type:
-                _deserializers[cls.graphbinary_type] = cls
-        return cls
-
-
-class GraphBinaryWriter(object):
-    def __init__(self, serializer_map=None):
-        self.serializers = _serializers.copy()
-        if serializer_map:
-            self.serializers.update(serializer_map)
-
-    def writeObject(self, objectData):
-        return self.toDict(objectData)
-
-    def toDict(self, obj, to_extend=None):
-        if to_extend is None:
-            to_extend = bytearray()
-
-        try:
-            t = type(obj)
-            
-            # coerce unicode to str so the serializer will be found properly in the cache...better way?
-            if not six.PY3:
-                t = str if isinstance(obj, unicode) else t
-            return self.serializers[t].dictify(obj, self, to_extend)
-        except KeyError:
-            for key, serializer in self.serializers.items():
-                if isinstance(obj, key):
-                    return serializer.dictify(obj, self, to_extend)
-
-        if isinstance(obj, dict):
-            return dict((self.toDict(k, to_extend), self.toDict(v, to_extend)) for k, v in obj.items())
-        elif isinstance(obj, set):
-            return set([self.toDict(o, to_extend) for o in obj])
-        elif isinstance(obj, list):
-            return [self.toDict(o, to_extend) for o in obj]
-        else:
-            return obj
-
-
-class GraphBinaryReader(object):
-    def __init__(self, deserializer_map=None):
-        self.deserializers = _deserializers.copy()
-        if deserializer_map:
-            self.deserializers.update(deserializer_map)
-
-    def readObject(self, b):
-        if isinstance(b, bytearray):
-            return self.toObject(io.BytesIO(b))
-        elif isinstance(b, io.BufferedIOBase):
-            return self.toObject(b)
-
-    def toObject(self, buff, data_type=None, nullable=True):
-        if data_type is None:
-            bt = uint8_unpack(buff.read(1))
-            if bt == DataType.null.value:
-                if nullable:
-                    buff.read(1)
-                return None
-            return self.deserializers[DataType(bt)].objectify(buff, self, nullable)
-        else:
-            return self.deserializers[data_type].objectify(buff, self, nullable)
-
-
-@six.add_metaclass(GraphBinaryTypeType)
-class _GraphBinaryTypeIO(object):
-    python_type = None
-    graphbinary_type = None
-
-    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
-                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
-                 "set_": "set", "list_": "list", "all_": "all", "with_": "with",
-                 "filter_": "filter", "id_": "id", "max_": "max", "min_": "min", "sum_": "sum"}
-
-    @classmethod
-    def prefix_bytes(cls, graphbin_type, as_value=False, nullable=True, to_extend=None):
-        if to_extend is None:
-            to_extend = bytearray()
-
-        if not as_value:
-            to_extend += uint8_pack(graphbin_type.value)
-
-        if nullable:
-            to_extend += int8_pack(0)
-
-        return to_extend
-
-    @classmethod
-    def read_int(cls, buff):
-        return int32_unpack(buff.read(4))
-
-    @classmethod
-    def unmangle_keyword(cls, symbol):
-        return cls.symbolMap.get(symbol, symbol)
-
-    @classmethod
-    def is_null(cls, buff, reader, else_opt, nullable=True):
-        return None if nullable and buff.read(1)[0] == 0x01 else else_opt(buff, reader)
-
-    def dictify(self, obj, writer, to_extend, as_value=False, nullable=True):
-        raise NotImplementedError()
-
-    def objectify(self, d, reader, nullable=True):
-        raise NotImplementedError()
-        
-
-class LongIO(_GraphBinaryTypeIO):
-
-    python_type = LongType
-    graphbinary_type = DataType.long
-    byte_format_pack = int64_pack
-    byte_format_unpack = int64_unpack
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        if obj < -9223372036854775808 or obj > 9223372036854775807:
-            raise Exception("TODO: don't forget bigint")
-        else:
-            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-            to_extend.extend(cls.byte_format_pack(obj))
-            return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-            return cls.is_null(buff, reader, lambda b, r: int64_unpack(buff.read(8)), nullable)
-
-
-class IntIO(LongIO):
-
-    python_type = IntType
-    graphbinary_type = DataType.int
-    byte_format_pack = int32_pack
-    byte_format_unpack = int32_unpack
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: cls.read_int(b), nullable)
-
-
-class DateIO(_GraphBinaryTypeIO):
-
-    python_type = datetime.datetime
-    graphbinary_type = DataType.date
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        try:
-            timestamp_seconds = calendar.timegm(obj.utctimetuple())
-            pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
-        except AttributeError:
-            pts = calendar.timegm(obj.timetuple()) * 1e3
-
-        ts = int(round(pts))
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int64_pack(ts))
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader,
-                           lambda b, r: datetime.datetime.utcfromtimestamp(int64_unpack(b.read(8)) / 1000.0),
-                           nullable)
-
-
-# Based on current implementation, this class must always be declared before FloatIO.
-# Seems pretty fragile for future maintainers. Maybe look into this.
-class TimestampIO(_GraphBinaryTypeIO):
-    python_type = statics.timestamp
-    graphbinary_type = DataType.timestamp
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        # Java timestamp expects milliseconds integer - Have to use int because of legacy Python
-        ts = int(round(obj * 1000))
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int64_pack(ts))
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        # Python timestamp expects seconds
-        return cls.is_null(buff, reader, lambda b, r: statics.timestamp(int64_unpack(b.read(8)) / 1000.0),
-                           nullable)
-    
-
-def _long_bits_to_double(bits):
-    return unpack('d', pack('Q', bits))[0]
-
-
-NAN = _long_bits_to_double(0x7ff8000000000000)
-POSITIVE_INFINITY = _long_bits_to_double(0x7ff0000000000000)
-NEGATIVE_INFINITY = _long_bits_to_double(0xFff0000000000000)
-
-
-class FloatIO(LongIO):
-
-    python_type = FloatType
-    graphbinary_type = DataType.float
-    graphbinary_base_type = DataType.float
-    byte_format_pack = float_pack
-    byte_format_unpack = float_unpack
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        if math.isnan(obj):
-            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-            to_extend.extend(cls.byte_format_pack(NAN))
-        elif math.isinf(obj) and obj > 0:
-            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-            to_extend.extend(cls.byte_format_pack(POSITIVE_INFINITY))
-        elif math.isinf(obj) and obj < 0:
-            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-            to_extend.extend(cls.byte_format_pack(NEGATIVE_INFINITY))
-        else:
-            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-            to_extend.extend(cls.byte_format_pack(obj))
-
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: float_unpack(b.read(4)), nullable)
-
-
-class DoubleIO(FloatIO):
-    """
-    Floats basically just fall through to double serialization.
-    """
-
-    graphbinary_type = DataType.double
-    graphbinary_base_type = DataType.double
-    byte_format_pack = double_pack
-    byte_format_unpack = double_unpack
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: double_unpack(b.read(8)), nullable)
-
-
-class CharIO(_GraphBinaryTypeIO):
-    python_type = SingleChar
-    graphbinary_type = DataType.char
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(obj.encode("utf-8"))
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_char, nullable)
-
-    @classmethod
-    def _read_char(cls, b, r):
-        max_bytes = 4
-        x = b.read(1)
-        while max_bytes > 0:
-            max_bytes = max_bytes - 1
-            try:
-                return x.decode("utf-8")
-            except UnicodeDecodeError:
-                x += b.read(1)
-
-
-class StringIO(_GraphBinaryTypeIO):
-
-    python_type = str
-    graphbinary_type = DataType.string
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        str_bytes = obj.encode("utf-8")
-        to_extend += int32_pack(len(str_bytes))
-        to_extend += str_bytes
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: b.read(cls.read_int(b)).decode("utf-8"), nullable)
-
-
-class ListIO(_GraphBinaryTypeIO):
-
-    python_type = list
-    graphbinary_type = DataType.list
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int32_pack(len(obj)))
-        for item in obj:
-            writer.toDict(item, to_extend)
-
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_list, nullable)
-
-    @classmethod
-    def _read_list(cls, b, r):
-        size = cls.read_int(b)
-        the_list = []
-        while size > 0:
-            the_list.append(r.readObject(b))
-            size = size - 1
-
-        return the_list
-
-
-class SetDeserializer(ListIO):
-
-    python_type = SetType
-    graphbinary_type = DataType.set
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return set(ListIO.objectify(buff, reader, nullable))
-
-
-class MapIO(_GraphBinaryTypeIO):
-
-    python_type = DictType
-    graphbinary_type = DataType.map
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
-        to_extend.extend(int32_pack(len(obj)))
-        for k, v in obj.items():
-            writer.toDict(k, to_extend)
-            writer.toDict(v, to_extend)
-
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_map, nullable)
-
-    @classmethod
-    def _read_map(cls, b, r):
-        size = cls.read_int(b)
-        the_dict = {}
-        while size > 0:
-            k = r.readObject(b)
-            v = r.readObject(b)
-            the_dict[k] = v
-            size = size - 1
-
-        return the_dict
-
-
-class UuidIO(_GraphBinaryTypeIO):
-
-    python_type = uuid.UUID
-    graphbinary_type = DataType.uuid
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(obj.bytes)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: uuid.UUID(bytes=b.read(16)), nullable)
-
-
-class EdgeIO(_GraphBinaryTypeIO):
-
-    python_type = Edge
-    graphbinary_type = DataType.edge
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
-        writer.toDict(obj.id, to_extend)
-        StringIO.dictify(obj.label, writer, to_extend, True, False)
-        writer.toDict(obj.inV.id, to_extend)
-        StringIO.dictify(obj.inV.label, writer, to_extend, True, False)
-        writer.toDict(obj.outV.id, to_extend)
-        StringIO.dictify(obj.outV.label, writer, to_extend, True, False)
-        to_extend.extend(NULL_BYTES)
-        to_extend.extend(NULL_BYTES)
-
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_edge, nullable)
-
-    @classmethod
-    def _read_edge(cls, b, r):
-        edgeid = r.readObject(b)
-        edgelbl = r.toObject(b, DataType.string, False)
-        inv = Vertex(r.readObject(b), r.toObject(b, DataType.string, False))
-        outv = Vertex(r.readObject(b), r.toObject(b, DataType.string, False))
-        edge = Edge(edgeid, outv, edgelbl, inv)
-        b.read(4)
-        return edge
-
-
-class PathIO(_GraphBinaryTypeIO):
-
-    python_type = Path
-    graphbinary_type = DataType.path
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        writer.toDict(obj.labels, to_extend)
-        writer.toDict(obj.objects, to_extend)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: Path(r.readObject(b), r.readObject(b)), nullable)
-
-
-class PropertyIO(_GraphBinaryTypeIO):
-
-    python_type = Property
-    graphbinary_type = DataType.property
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        StringIO.dictify(obj.key, writer, to_extend, True, False)
-        writer.toDict(obj.value, to_extend)
-        to_extend.extend(NULL_BYTES)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_property, nullable)
-
-    @classmethod
-    def _read_property(cls, b, r):
-        p = Property(r.toObject(b, DataType.string, False), r.readObject(b), None)
-        b.read(2)
-        return p
-
-
-class TinkerGraphIO(_GraphBinaryTypeIO):
-
-    python_type = Graph
-    graphbinary_type = DataType.graph
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        raise AttributeError("TinkerGraph serialization is not currently supported by gremlin-python")
-
-    @classmethod
-    def objectify(cls, b, reader, as_value=False):
-        raise AttributeError("TinkerGraph deserialization is not currently supported by gremlin-python")
-
-
-class VertexIO(_GraphBinaryTypeIO):
-
-    python_type = Vertex
-    graphbinary_type = DataType.vertex
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        writer.toDict(obj.id, to_extend)
-        StringIO.dictify(obj.label, writer, to_extend, True, False)
-        to_extend.extend(NULL_BYTES)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_vertex, nullable)
-
-    @classmethod
-    def _read_vertex(cls, b, r):
-        vertex = Vertex(r.readObject(b), r.toObject(b, DataType.string, False))
-        b.read(2)
-        return vertex
-
-
-class VertexPropertyIO(_GraphBinaryTypeIO):
-
-    python_type = VertexProperty
-    graphbinary_type = DataType.vertexproperty
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        writer.toDict(obj.id, to_extend)
-        StringIO.dictify(obj.label, writer, to_extend, True, False)
-        writer.toDict(obj.value, to_extend)
-        to_extend.extend(NULL_BYTES)
-        to_extend.extend(NULL_BYTES)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_vertexproperty, nullable)
-
-    @classmethod
-    def _read_vertexproperty(cls, b, r):
-        vp = VertexProperty(r.readObject(b), r.toObject(b, DataType.string, False), r.readObject(b), None)
-        b.read(4)
-        return vp
-
-
-class _EnumIO(_GraphBinaryTypeIO):
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        StringIO.dictify(cls.unmangle_keyword(str(obj.name)), writer, to_extend)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_enumval, nullable)
-
-    @classmethod
-    def _read_enumval(cls, b, r):
-        enum_name = r.toObject(b)
-        return cls.python_type[enum_name]
-
-
-class BarrierIO(_EnumIO):
-    graphbinary_type = DataType.barrier
-    python_type = Barrier
-
-
-class CardinalityIO(_EnumIO):
-    graphbinary_type = DataType.cardinality
-    python_type = Cardinality
-
-
-class ColumnIO(_EnumIO):
-    graphbinary_type = DataType.column
-    python_type = Column
-
-
-class DirectionIO(_EnumIO):
-    graphbinary_type = DataType.direction
-    python_type = Direction
-
-
-class OperatorIO(_EnumIO):
-    graphbinary_type = DataType.operator
-    python_type = Operator
-
-
-class OrderIO(_EnumIO):
-    graphbinary_type = DataType.order
-    python_type = Order
-
-
-class PickIO(_EnumIO):
-    graphbinary_type = DataType.pick
-    python_type = Pick
-
-
-class PopIO(_EnumIO):
-    graphbinary_type = DataType.pop
-    python_type = Pop
-
-
-class BindingIO(_GraphBinaryTypeIO):
-
-    python_type = Binding
-    graphbinary_type = DataType.binding
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        StringIO.dictify(obj.key, writer, to_extend, True, False)
-        writer.toDict(obj.value, to_extend)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, lambda b, r: Binding(r.toObject(b, DataType.string, False),
-                                                              reader.readObject(b)), nullable)
-
-
-class BytecodeIO(_GraphBinaryTypeIO):
-    python_type = Bytecode
-    graphbinary_type = DataType.bytecode
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        bc = obj.bytecode if isinstance(obj, Traversal) else obj
-        to_extend.extend(int32_pack(len(bc.step_instructions)))
-        for inst in bc.step_instructions:
-            inst_name, inst_args = inst[0], inst[1:] if len(inst) > 1 else []
-            StringIO.dictify(inst_name, writer, to_extend, True, False)
-            to_extend.extend(int32_pack(len(inst_args)))
-            for arg in inst_args:
-                writer.toDict(arg, to_extend)
-
-        to_extend.extend(int32_pack(len(bc.source_instructions)))
-        for inst in bc.source_instructions:
-            inst_name, inst_args = inst[0], inst[1:] if len(inst) > 1 else []
-            StringIO.dictify(inst_name, writer, to_extend, True, False)
-            to_extend.extend(int32_pack(len(inst_args)))
-            for arg in inst_args:
-                if isinstance(arg, TypeType):
-                    writer.toDict(GremlinType(arg().fqcn), to_extend)
-                else:
-                    writer.toDict(arg, to_extend)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_bytecode, nullable)
-
-    @classmethod
-    def _read_bytecode(cls, b, r):
-        bytecode = Bytecode()
-
-        step_count = cls.read_int(b)
-        ix = 0
-        while ix < step_count:
-            inst = [r.toObject(b, DataType.string, False)]
-            inst_ct = cls.read_int(b)
-            iy = 0
-            while iy < inst_ct:
-                inst.append(r.readObject(b))
-                iy += 1
-            bytecode.step_instructions.append(inst)
-            ix += 1
-
-        source_count = cls.read_int(b)
-        ix = 0
-        while ix < source_count:
-            inst = [r.toObject(b, DataType.string, False)]
-            inst_ct = cls.read_int(b)
-            iy = 0
-            while iy < inst_ct:
-                inst.append(r.readObject(b))
-                iy += 1
-            bytecode.source_instructions.append(inst)
-            ix += 1
-
-        return bytecode
-
-
-class TraversalIO(BytecodeIO):
-    python_type = GraphTraversal
-
-
-class LambdaSerializer(_GraphBinaryTypeIO):
-
-    python_type = FunctionType
-    graphbinary_type = DataType.lambda_
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
-        lambda_result = obj()
-        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
-        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
-
-        StringIO.dictify(language, writer, to_extend, True, False)
-
-        script_cleaned = script
-        script_args = -1
-
-        if language == "gremlin-jython" or language == "gremlin-python":
-            if not script.strip().startswith("lambda"):
-                script_cleaned = "lambda " + script
-            script_args = six.get_function_code(eval(script_cleaned)).co_argcount
-        elif language == "gremlin-groovy" and "->" in script:
-            # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
-            # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
-            args = script[0:script.find("->")]
-            script_args = 2 if "," in args else 1
-
-        StringIO.dictify(script_cleaned, writer, to_extend, True, False)
-        to_extend.extend(int32_pack(script_args))
-
-        return to_extend
-
-
-class PSerializer(_GraphBinaryTypeIO):
-    graphbinary_type = DataType.p
-    python_type = P
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
-        StringIO.dictify(obj.operator, writer, to_extend, True, False)
-
-        args = []
-        if obj.other is None:
-            if isinstance(obj.value, ListType):
-                args = obj.value
-            else:
-                args.append(obj.value)
-        else:
-            args.append(obj.value)
-            args.append(obj.other)
-
-        to_extend.extend(int32_pack(len(args)))
-        for a in args:
-            writer.toDict(a, to_extend)
-
-        return to_extend
-
-
-class ScopeIO(_EnumIO):
-    graphbinary_type = DataType.scope
-    python_type = Scope
-
-
-class TIO(_EnumIO):
-    graphbinary_type = DataType.t
-    python_type = T
-
-
-class TraverserIO(_GraphBinaryTypeIO):
-    graphbinary_type = DataType.traverser
-    python_type = Traverser
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int64_pack(obj.bulk))
-        writer.toDict(obj.object, to_extend)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_traverser, nullable)
-
-    @classmethod
-    def _read_traverser(cls, b, r):
-        bulk = int64_unpack(b.read(8))
-        obj = r.readObject(b)
-        return Traverser(obj, bulk=bulk)
-
-
-class ByteIO(_GraphBinaryTypeIO):
-    python_type = SingleByte
-    graphbinary_type = DataType.byte
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int8_pack(obj))
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader,
-                           lambda b, r: int.__new__(SingleByte, int8_unpack(b.read(1))),
-                           nullable)
-
-
-class ByteBufferIO(_GraphBinaryTypeIO):
-    python_type = ByteBufferType
-    graphbinary_type = DataType.bytebuffer
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int32_pack(len(obj)))
-        to_extend.extend(obj)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_bytebuffer, nullable)
-
-    @classmethod
-    def _read_bytebuffer(cls, b, r):
-        size = cls.read_int(b)
-        return ByteBufferType(b.read(size))
-
-
-class BooleanIO(_GraphBinaryTypeIO):
-    python_type = bool
-    graphbinary_type = DataType.boolean
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        to_extend.extend(int8_pack(0x01 if obj else 0x00))
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader,
-                           lambda b, r: True if int8_unpack(b.read(1)) == 0x01 else False,
-                           nullable)
-
-
-class TextPSerializer(_GraphBinaryTypeIO):
-    graphbinary_type = DataType.textp
-    python_type = TextP
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
-        StringIO.dictify(obj.operator, writer, to_extend, True, False)
-
-        args = []
-        if obj.other is None:
-            if isinstance(obj.value, ListType):
-                args = obj.value
-            else:
-                args.append(obj.value)
-        else:
-            args.append(obj.value)
-            args.append(obj.other)
-
-        to_extend.extend(int32_pack(len(args)))
-        for a in args:
-            writer.toDict(a, to_extend)
-
-        return to_extend
-
-
-class BulkSetDeserializer(_GraphBinaryTypeIO):
-
-    graphbinary_type = DataType.bulkset
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_bulkset, nullable)
-
-    @classmethod
-    def _read_bulkset(cls, b, r):
-        size = cls.read_int(b)
-        the_list = []
-        while size > 0:
-            itm = r.readObject(b)
-            bulk = int64_unpack(b.read(8))
-            for y in range(bulk):
-                the_list.append(itm)            
-            size = size - 1
-
-        return the_list
-
-
-class MetricsDeserializer(_GraphBinaryTypeIO):
-
-    graphbinary_type = DataType.metrics
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_metrics, nullable)
-
-    @classmethod
-    def _read_metrics(cls, b, r):
-        metricid = r.toObject(b, DataType.string, False)
-        name = r.toObject(b, DataType.string, False)
-        duration = r.toObject(b, DataType.long, nullable=False)
-        counts = r.toObject(b, DataType.map, nullable=False)
-        annotations = r.toObject(b, DataType.map, nullable=False)
-        metrics = r.toObject(b, DataType.list, nullable=False)
-
-        return {"id": metricid,
-                "name": name,
-                "dur": duration,
-                "counts": counts,
-                "annotations": annotations,
-                "metrics": metrics}
-
-
-class TraversalMetricsDeserializer(_GraphBinaryTypeIO):
-
-    graphbinary_type = DataType.traversalmetrics
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_traversalmetrics, nullable)
-
-    @classmethod
-    def _read_traversalmetrics(cls, b, r):
-        duration = r.toObject(b, DataType.long, nullable=False)
-        metrics = r.toObject(b, DataType.list, nullable=False)
-
-        return {"dur": duration,
-                "metrics": metrics}
-
-
-class ClassSerializer(_GraphBinaryTypeIO):
-    graphbinary_type = DataType.clazz
-    python_type = GremlinType
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        StringIO.dictify(obj.gremlin_type, writer, to_extend, True, False)
-        return to_extend
-
-
-class TraversalStrategySerializer(_GraphBinaryTypeIO):
-    graphbinary_type = DataType.traversalstrategy
-    python_type = TraversalStrategy
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
-        ClassSerializer.dictify(GremlinType(obj.fqcn), writer, to_extend, True, False)
-        conf = {k: cls._convert(v) for k, v in obj.configuration.items()}
-        MapIO.dictify(conf, writer, to_extend, True, False)
-
-        return to_extend
-
-    @classmethod
-    def _convert(cls, v):
-        return v.bytecode if isinstance(v, Traversal) else v
-
-
-class DurationIO(_GraphBinaryTypeIO):
-    python_type = timedelta
-    graphbinary_type = DataType.duration
-
-    @classmethod
-    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
-        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-        LongIO.dictify(obj.seconds, writer, to_extend, True, False)
-        IntIO.dictify(obj.microseconds * 1000, writer, to_extend, True, False)
-        return to_extend
-
-    @classmethod
-    def objectify(cls, buff, reader, nullable=True):
-        return cls.is_null(buff, reader, cls._read_duration, nullable)
-    
-    @classmethod
-    def _read_duration(cls, b, r):
-        seconds = r.toObject(b, DataType.long, False)
-        nanos = r.toObject(b, DataType.int, False)
-        return timedelta(seconds=seconds, microseconds=nanos / 1000)
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
deleted file mode 100644
index 2906dba..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
+++ /dev/null
@@ -1,637 +0,0 @@
-#
-# 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.
-#
-
-import calendar
-import datetime
-import json
-import uuid
-import math
-from collections import OrderedDict
-from decimal import *
-from datetime import timedelta
-
-import six
-from aenum import Enum
-from isodate import parse_duration, duration_isoformat
-
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, SingleByte, ByteBufferType, SingleChar
-from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy
-from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
-
-# When we fall back to a superclass's serializer, we iterate over this map.
-# We want that iteration order to be consistent, so we use an OrderedDict,
-# not a dict.
-_serializers = OrderedDict()
-_deserializers = {}
-
-
-class GraphSONTypeType(type):
-    def __new__(mcs, name, bases, dct):
-        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
-        if not name.startswith('_'):
-            if cls.python_type:
-                _serializers[cls.python_type] = cls
-            if cls.graphson_type:
-                _deserializers[cls.graphson_type] = cls
-        return cls
-
-
-class GraphSONUtil(object):
-    TYPE_KEY = "@type"
-    VALUE_KEY = "@value"
-
-    @classmethod
-    def typedValue(cls, type_name, value, prefix="g"):
-        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
-        if value is not None:
-            out[cls.VALUE_KEY] = value
-        return out
-
-    @classmethod
-    def formatType(cls, prefix, type_name):
-        return "%s:%s" % (prefix, type_name)
-
-
-# Read/Write classes split to follow precedence of the Java API
-class GraphSONWriter(object):
-    def __init__(self, serializer_map=None):
-        """
-        :param serializer_map: map from Python type to serializer instance implementing `dictify`
-        """
-        self.serializers = _serializers.copy()
-        if serializer_map:
-            self.serializers.update(serializer_map)
-
-    def writeObject(self, objectData):
-        # to JSON
-        return json.dumps(self.toDict(objectData), separators=(',', ':'))
-
-    def toDict(self, obj):
-        """
-        Encodes python objects in GraphSON type-tagged dict values
-        """
-        try:
-            return self.serializers[type(obj)].dictify(obj, self)
-        except KeyError:
-            for key, serializer in self.serializers.items():
-                if isinstance(obj, key):
-                    return serializer.dictify(obj, self)
-
-        # list and map are treated as normal json objs (could be isolated serializers)
-        if isinstance(obj, (list, set)):
-            return [self.toDict(o) for o in obj]
-        elif isinstance(obj, dict):
-            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
-        else:
-            return obj
-
-
-class GraphSONReader(object):
-    def __init__(self, deserializer_map=None):
-        """
-        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
-        """
-        self.deserializers = _deserializers.copy()
-        if deserializer_map:
-            self.deserializers.update(deserializer_map)
-
-    def readObject(self, jsonData):
-        # from JSON
-        return self.toObject(json.loads(jsonData))
-
-    def toObject(self, obj):
-        """
-        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
-        """
-        if isinstance(obj, dict):
-            try:
-                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
-            except KeyError:
-                pass
-            # list and map are treated as normal json objs (could be isolated deserializers)
-            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
-        elif isinstance(obj, list):
-            return [self.toObject(o) for o in obj]
-        else:
-            return obj
-
-
-@six.add_metaclass(GraphSONTypeType)
-class _GraphSONTypeIO(object):
-    python_type = None
-    graphson_type = None
-
-    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
-                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
-                 "set_": "set", "list_": "list", "all_": "all", "with_": "with",
-                 "filter_": "filter", "id_": "id", "max_": "max", "min_": "min", "sum_": "sum"}
-
-    @classmethod
-    def unmangleKeyword(cls, symbol):
-        return cls.symbolMap.get(symbol, symbol)
-
-    def dictify(self, obj, writer):
-        raise NotImplementedError()
-
-    def objectify(self, d, reader):
-        raise NotImplementedError()
-
-
-class _BytecodeSerializer(_GraphSONTypeIO):
-    @classmethod
-    def _dictify_instructions(cls, instructions, writer):
-        out = []
-        for instruction in instructions:
-            inst = [instruction[0]]
-            inst.extend(writer.toDict(arg) for arg in instruction[1:])
-            out.append(inst)
-        return out
-
-    @classmethod
-    def dictify(cls, bytecode, writer):
-        if isinstance(bytecode, Traversal):
-            bytecode = bytecode.bytecode
-        out = {}
-        if bytecode.source_instructions:
-            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
-        if bytecode.step_instructions:
-            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
-        return GraphSONUtil.typedValue("Bytecode", out)
-
-class TraversalSerializer(_BytecodeSerializer):
-    python_type = Traversal
-
-
-class BytecodeSerializer(_BytecodeSerializer):
-    python_type = Bytecode
-
-
-class VertexSerializer(_GraphSONTypeIO):
-    python_type = Vertex
-    graphson_type = "g:Vertex"
-
-    @classmethod
-    def dictify(cls, vertex, writer):
-        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
-                                                  "label": writer.toDict(vertex.label)})
-
-
-class EdgeSerializer(_GraphSONTypeIO):
-    python_type = Edge
-    graphson_type = "g:Edge"
-
-    @classmethod
-    def dictify(cls, edge, writer):
-        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
-                                                "outV": writer.toDict(edge.outV.id),
-                                                "outVLabel": writer.toDict(edge.outV.label),
-                                                "label": writer.toDict(edge.label),
-                                                "inV": writer.toDict(edge.inV.id),
-                                                "inVLabel": writer.toDict(edge.inV.label)})
-
-
-class VertexPropertySerializer(_GraphSONTypeIO):
-    python_type = VertexProperty
-    graphson_type = "g:VertexProperty"
-
-    @classmethod
-    def dictify(cls, vertex_property, writer):
-        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
-                                                          "label": writer.toDict(vertex_property.label),
-                                                          "value": writer.toDict(vertex_property.value),
-                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
-
-
-class PropertySerializer(_GraphSONTypeIO):
-    python_type = Property
-    graphson_type = "g:Property"
-
-    @classmethod
-    def dictify(cls, property, writer):
-        elementDict = writer.toDict(property.element)
-        if elementDict is not None:
-            valueDict = elementDict["@value"]
-            if "outVLabel" in valueDict:
-                del valueDict["outVLabel"]
-            if "inVLabel" in valueDict:
-                del valueDict["inVLabel"]
-            if "properties" in valueDict:
-                del valueDict["properties"]
-            if "value" in valueDict:
-                del valueDict["value"]
-        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
-                                                    "value": writer.toDict(property.value),
-                                                    "element": elementDict})
-
-
-class TraversalStrategySerializer(_GraphSONTypeIO):
-    python_type = TraversalStrategy
-
-    @classmethod
-    def dictify(cls, strategy, writer):
-        return GraphSONUtil.typedValue(strategy.strategy_name, writer.toDict(strategy.configuration))
-
-
-class TraverserIO(_GraphSONTypeIO):
-    python_type = Traverser
-    graphson_type = "g:Traverser"
-
-    @classmethod
-    def dictify(cls, traverser, writer):
-        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
-                                                     "bulk": writer.toDict(traverser.bulk)})
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Traverser(reader.toObject(d["value"]),
-                         reader.toObject(d["bulk"]))
-
-
-class EnumSerializer(_GraphSONTypeIO):
-    python_type = Enum
-
-    @classmethod
-    def dictify(cls, enum, _):
-        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
-                                       cls.unmangleKeyword(str(enum.name)))
-
-
-class PSerializer(_GraphSONTypeIO):
-    python_type = P
-
-    @classmethod
-    def dictify(cls, p, writer):
-        out = {"predicate": p.operator,
-               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
-               writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("P", out)
-
-
-class TextPSerializer(_GraphSONTypeIO):
-    python_type = TextP
-
-    @classmethod
-    def dictify(cls, p, writer):
-        out = {"predicate": p.operator,
-               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
-               writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("TextP", out)
-
-
-class BindingSerializer(_GraphSONTypeIO):
-    python_type = Binding
-
-    @classmethod
-    def dictify(cls, binding, writer):
-        out = {"key": binding.key,
-               "value": writer.toDict(binding.value)}
-        return GraphSONUtil.typedValue("Binding", out)
-
-
-class LambdaSerializer(_GraphSONTypeIO):
-    python_type = FunctionType
-
-    @classmethod
-    def dictify(cls, lambda_object, writer):
-        lambda_result = lambda_object()
-        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
-        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
-        out = {"script": script,
-               "language": language}
-        if language == "gremlin-jython" or language == "gremlin-python":
-            if not script.strip().startswith("lambda"):
-                script = "lambda " + script
-                out["script"] = script
-            out["arguments"] = six.get_function_code(eval(out["script"])).co_argcount
-        elif language == "gremlin-groovy" and "->" in script:
-            # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
-            # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
-            args = script[0:script.find("->")]
-            out["arguments"] = 2 if "," in args else 1
-        else:
-            out["arguments"] = -1
-
-        return GraphSONUtil.typedValue("Lambda", out)
-
-
-class TypeSerializer(_GraphSONTypeIO):
-    python_type = TypeType
-
-    @classmethod
-    def dictify(cls, typ, writer):
-        return writer.toDict(typ())
-
-
-class UUIDIO(_GraphSONTypeIO):
-    python_type = uuid.UUID
-    graphson_type = "g:UUID"
-    graphson_base_type = "UUID"
-
-    @classmethod
-    def dictify(cls, obj, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, str(obj))
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return cls.python_type(d)
-
-
-class DateIO(_GraphSONTypeIO):
-    python_type = datetime.datetime
-    graphson_type = "g:Date"
-    graphson_base_type = "Date"
-
-    @classmethod
-    def dictify(cls, obj, writer):
-        try:
-            timestamp_seconds = calendar.timegm(obj.utctimetuple())
-            pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
-        except AttributeError:
-            pts = calendar.timegm(obj.timetuple()) * 1e3
-
-        ts = int(round(pts))
-        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
-
-    @classmethod
-    def objectify(cls, ts, reader):
-        # Python timestamp expects seconds
-        return datetime.datetime.utcfromtimestamp(ts / 1000.0)
-
-
-# Based on current implementation, this class must always be declared before FloatIO.
-# Seems pretty fragile for future maintainers. Maybe look into this.
-class TimestampIO(_GraphSONTypeIO):
-    """A timestamp in Python is type float"""
-    python_type = statics.timestamp
-    graphson_type = "g:Timestamp"
-    graphson_base_type = "Timestamp"
-
-    @classmethod
-    def dictify(cls, obj, writer):
-        # Java timestamp expects milliseconds integer
-        # Have to use int because of legacy Python
-        ts = int(round(obj * 1000))
-        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
-
-    @classmethod
-    def objectify(cls, ts, reader):
-        # Python timestamp expects seconds
-        return cls.python_type(ts / 1000.0)
-
-
-class _NumberIO(_GraphSONTypeIO):
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-    @classmethod
-    def objectify(cls, v, _):
-        return cls.python_type(v)
-
-
-class FloatIO(_NumberIO):
-    python_type = FloatType
-    graphson_type = "g:Float"
-    graphson_base_type = "Float"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        elif math.isnan(n):
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN")
-        elif math.isinf(n) and n > 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity")
-        elif math.isinf(n) and n < 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity")
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-    @classmethod
-    def objectify(cls, v, _):
-        if isinstance(v, str):
-            if v == 'NaN':
-                return float('nan')
-            elif v == "Infinity":
-                return float('inf')
-            elif v == "-Infinity":
-                return float('-inf')
-
-        return cls.python_type(v)
-
-
-class BigDecimalIO(_NumberIO):
-    python_type = Decimal
-    graphson_type = "gx:BigDecimal"
-    graphson_base_type = "BigDecimal"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        elif math.isnan(n):
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN", "gx")
-        elif math.isinf(n) and n > 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity", "gx")
-        elif math.isinf(n) and n < 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity", "gx")
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, str(n), "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        if isinstance(v, str):
-            if v == 'NaN':
-                return Decimal('nan')
-            elif v == "Infinity":
-                return Decimal('inf')
-            elif v == "-Infinity":
-                return Decimal('-inf')
-
-        return Decimal(v)
-
-
-class DoubleIO(FloatIO):
-    graphson_type = "g:Double"
-    graphson_base_type = "Double"
-
-
-class Int64IO(_NumberIO):
-    python_type = LongType
-    graphson_type = "g:Int64"
-    graphson_base_type = "Int64"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        # if we exceed Java long range then we need a BigInteger
-        if isinstance(n, bool):
-            return n
-        elif n < -9223372036854775808 or n > 9223372036854775807:
-            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-
-class BigIntegerIO(Int64IO):
-    graphson_type = "gx:BigInteger"
-
-
-class Int32IO(Int64IO):
-    python_type = IntType
-    graphson_type = "g:Int32"
-    graphson_base_type = "Int32"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        # if we exceed Java int range then we need a long
-        if isinstance(n, bool):
-            return n
-        elif n < -9223372036854775808 or n > 9223372036854775807:
-            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
-        elif n < -2147483648 or n > 2147483647:
-            return GraphSONUtil.typedValue("Int64", n)
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-
-class ByteIO(_NumberIO):
-    python_type = SingleByte
-    graphson_type = "gx:Byte"
-    graphson_base_type = "Byte"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return int.__new__(SingleByte, v)
-
-
-class ByteBufferIO(_GraphSONTypeIO):
-    python_type = ByteBufferType
-    graphson_type = "gx:ByteBuffer"
-    graphson_base_type = "ByteBuffer"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, "".join(chr(x) for x in n), "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return cls.python_type(v, "utf8")
-
-
-class CharIO(_GraphSONTypeIO):
-    python_type = SingleChar
-    graphson_type = "gx:Char"
-    graphson_base_type = "Char"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return str.__new__(SingleChar, v)
-
-
-class DurationIO(_GraphSONTypeIO):
-    python_type = timedelta
-    graphson_type = "gx:Duration"
-    graphson_base_type = "Duration"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, duration_isoformat(n), "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return parse_duration(v)
-
-
-class VertexDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Vertex"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
-
-
-class EdgeDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Edge"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Edge(reader.toObject(d["id"]),
-                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
-                    d.get("label", "edge"),
-                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
-
-
-class VertexPropertyDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:VertexProperty"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
-        return VertexProperty(reader.toObject(d["id"]),
-                              d["label"],
-                              reader.toObject(d["value"]),
-                              vertex)
-
-
-class PropertyDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Property"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        element = reader.toObject(d["element"]) if "element" in d else None
-        return Property(d["key"], reader.toObject(d["value"]), element)
-
-
-class PathDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Path"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        labels = [set(label) for label in d["labels"]]
-        objects = [reader.toObject(o) for o in d["objects"]]
-        return Path(labels, objects)
-
-
-class TraversalMetricsDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:TraversalMetrics"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return reader.toObject(d)
-
-
-class MetricsDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Metrics"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return reader.toObject(d)
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
deleted file mode 100644
index b15aca6..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
+++ /dev/null
@@ -1,755 +0,0 @@
-# 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.
-import calendar
-import datetime
-import json
-import uuid
-import math
-from collections import OrderedDict
-from decimal import *
-import logging
-from datetime import timedelta
-
-import six
-from aenum import Enum
-from isodate import parse_duration, duration_isoformat
-
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
-from gremlin_python.process.traversal import Binding, Bytecode, Direction, P, TextP, Traversal, Traverser, TraversalStrategy, T
-from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
-
-log = logging.getLogger(__name__)
-
-# When we fall back to a superclass's serializer, we iterate over this map.
-# We want that iteration order to be consistent, so we use an OrderedDict,
-# not a dict.
-_serializers = OrderedDict()
-_deserializers = {}
-
-
-class GraphSONTypeType(type):
-    def __new__(mcs, name, bases, dct):
-        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
-        if not name.startswith('_'):
-            if cls.python_type:
-                _serializers[cls.python_type] = cls
-            if cls.graphson_type:
-                _deserializers[cls.graphson_type] = cls
-        return cls
-
-
-class GraphSONUtil(object):
-    TYPE_KEY = "@type"
-    VALUE_KEY = "@value"
-
-    @classmethod
-    def typedValue(cls, type_name, value, prefix="g"):
-        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
-        if value is not None:
-            out[cls.VALUE_KEY] = value
-        return out
-
-    @classmethod
-    def formatType(cls, prefix, type_name):
-        return "%s:%s" % (prefix, type_name)
-
-
-# Read/Write classes split to follow precedence of the Java API
-class GraphSONWriter(object):
-    def __init__(self, serializer_map=None):
-        """
-        :param serializer_map: map from Python type to serializer instance implementing `dictify`
-        """
-        self.serializers = _serializers.copy()
-        if serializer_map:
-            self.serializers.update(serializer_map)
-
-    def writeObject(self, objectData):
-        # to JSON
-        return json.dumps(self.toDict(objectData), separators=(',', ':'))
-
-    def toDict(self, obj):
-        """
-        Encodes python objects in GraphSON type-tagged dict values
-        """
-        try:
-            return self.serializers[type(obj)].dictify(obj, self)
-        except KeyError:
-            for key, serializer in self.serializers.items():
-                if isinstance(obj, key):
-                    return serializer.dictify(obj, self)
-
-        if isinstance(obj, dict):
-            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
-        elif isinstance(obj, set):
-            return set([self.toDict(o) for o in obj])
-        elif isinstance(obj, list):
-            return [self.toDict(o) for o in obj]
-        else:
-            return obj
-
-
-class GraphSONReader(object):
-    def __init__(self, deserializer_map=None):
-        """
-        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
-        """
-        self.deserializers = _deserializers.copy()
-        if deserializer_map:
-            self.deserializers.update(deserializer_map)
-
-    def readObject(self, jsonData):
-        # from JSON
-        return self.toObject(json.loads(jsonData))
-
-    def toObject(self, obj):
-        """
-        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
-        """
-        if isinstance(obj, dict):
-            try:
-                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
-            except KeyError:
-                pass
-            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
-        elif isinstance(obj, set):
-            return set([self.toObject(o) for o in obj])
-        elif isinstance(obj, list):
-            return [self.toObject(o) for o in obj]
-        else:
-            return obj
-
-
-@six.add_metaclass(GraphSONTypeType)
-class _GraphSONTypeIO(object):
-    python_type = None
-    graphson_type = None
-
-    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
-                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
-                 "set_": "set", "list_": "list", "all_": "all", "with_": "with",
-                 "filter_": "filter", "id_": "id", "max_": "max", "min_": "min", "sum_": "sum"}
-
-    @classmethod
-    def unmangleKeyword(cls, symbol):
-        return cls.symbolMap.get(symbol, symbol)
-
-    def dictify(self, obj, writer):
-        raise NotImplementedError()
-
-    def objectify(self, d, reader):
-        raise NotImplementedError()
-
-
-class _BytecodeSerializer(_GraphSONTypeIO):
-    @classmethod
-    def _dictify_instructions(cls, instructions, writer):
-        out = []
-        for instruction in instructions:
-            inst = [instruction[0]]
-            inst.extend(writer.toDict(arg) for arg in instruction[1:])
-            out.append(inst)
-        return out
-
-    @classmethod
-    def dictify(cls, bytecode, writer):
-        if isinstance(bytecode, Traversal):
-            bytecode = bytecode.bytecode
-        out = {}
-        if bytecode.source_instructions:
-            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
-        if bytecode.step_instructions:
-            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
-        return GraphSONUtil.typedValue("Bytecode", out)
-
-
-class TraversalSerializer(_BytecodeSerializer):
-    python_type = Traversal
-
-
-class BytecodeSerializer(_BytecodeSerializer):
-    python_type = Bytecode
-
-
-class VertexSerializer(_GraphSONTypeIO):
-    python_type = Vertex
-    graphson_type = "g:Vertex"
-
-    @classmethod
-    def dictify(cls, vertex, writer):
-        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
-                                                  "label": writer.toDict(vertex.label)})
-
-
-class EdgeSerializer(_GraphSONTypeIO):
-    python_type = Edge
-    graphson_type = "g:Edge"
-
-    @classmethod
-    def dictify(cls, edge, writer):
-        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
-                                                "outV": writer.toDict(edge.outV.id),
-                                                "outVLabel": writer.toDict(edge.outV.label),
-                                                "label": writer.toDict(edge.label),
-                                                "inV": writer.toDict(edge.inV.id),
-                                                "inVLabel": writer.toDict(edge.inV.label)})
-
-
-class VertexPropertySerializer(_GraphSONTypeIO):
-    python_type = VertexProperty
-    graphson_type = "g:VertexProperty"
-
-    @classmethod
-    def dictify(cls, vertex_property, writer):
-        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
-                                                          "label": writer.toDict(vertex_property.label),
-                                                          "value": writer.toDict(vertex_property.value),
-                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
-
-
-class PropertySerializer(_GraphSONTypeIO):
-    python_type = Property
-    graphson_type = "g:Property"
-
-    @classmethod
-    def dictify(cls, property, writer):
-        elementDict = writer.toDict(property.element)
-        if elementDict is not None:
-            valueDict = elementDict["@value"]
-            if "outVLabel" in valueDict:
-                del valueDict["outVLabel"]
-            if "inVLabel" in valueDict:
-                del valueDict["inVLabel"]
-            if "properties" in valueDict:
-                del valueDict["properties"]
-            if "value" in valueDict:
-                del valueDict["value"]
-        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
-                                                    "value": writer.toDict(property.value),
-                                                    "element": elementDict})
-
-
-class TraversalStrategySerializer(_GraphSONTypeIO):
-    python_type = TraversalStrategy
-
-    @classmethod
-    def dictify(cls, strategy, writer):
-        configuration = {}
-        for key in strategy.configuration:
-            configuration[key] = writer.toDict(strategy.configuration[key])
-        return GraphSONUtil.typedValue(strategy.strategy_name, configuration)
-
-
-class TraverserIO(_GraphSONTypeIO):
-    python_type = Traverser
-    graphson_type = "g:Traverser"
-
-    @classmethod
-    def dictify(cls, traverser, writer):
-        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
-                                                     "bulk": writer.toDict(traverser.bulk)})
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Traverser(reader.toObject(d["value"]),
-                         reader.toObject(d["bulk"]))
-
-
-class EnumSerializer(_GraphSONTypeIO):
-    python_type = Enum
-
-    @classmethod
-    def dictify(cls, enum, _):
-        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
-                                       cls.unmangleKeyword(str(enum.name)))
-
-
-class PSerializer(_GraphSONTypeIO):
-    python_type = P
-
-    @classmethod
-    def dictify(cls, p, writer):
-        out = {"predicate": p.operator,
-               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
-               writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("P", out)
-
-
-class TextPSerializer(_GraphSONTypeIO):
-    python_type = TextP
-
-    @classmethod
-    def dictify(cls, p, writer):
-        out = {"predicate": p.operator,
-               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
-               writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("TextP", out)
-
-
-class BindingSerializer(_GraphSONTypeIO):
-    python_type = Binding
-
-    @classmethod
-    def dictify(cls, binding, writer):
-        out = {"key": binding.key,
-               "value": writer.toDict(binding.value)}
-        return GraphSONUtil.typedValue("Binding", out)
-
-
-class LambdaSerializer(_GraphSONTypeIO):
-    python_type = FunctionType
-
-    @classmethod
-    def dictify(cls, lambda_object, writer):
-        lambda_result = lambda_object()
-        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
-        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
-        out = {"script": script,
-               "language": language}
-        if language == "gremlin-jython" or language == "gremlin-python":
-            if not script.strip().startswith("lambda"):
-                script = "lambda " + script
-                out["script"] = script
-            out["arguments"] = six.get_function_code(eval(out["script"])).co_argcount
-        elif language == "gremlin-groovy" and "->" in script:
-            # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
-            # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
-            args = script[0:script.find("->")]
-            out["arguments"] = 2 if "," in args else 1
-        else:
-            out["arguments"] = -1
-
-        return GraphSONUtil.typedValue("Lambda", out)
-
-
-class TypeSerializer(_GraphSONTypeIO):
-    python_type = TypeType
-
-    @classmethod
-    def dictify(cls, typ, writer):
-        return writer.toDict(typ())
-
-
-class UUIDIO(_GraphSONTypeIO):
-    python_type = uuid.UUID
-    graphson_type = "g:UUID"
-    graphson_base_type = "UUID"
-
-    @classmethod
-    def dictify(cls, obj, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, str(obj))
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return cls.python_type(d)
-
-
-class DateIO(_GraphSONTypeIO):
-    python_type = datetime.datetime
-    graphson_type = "g:Date"
-    graphson_base_type = "Date"
-
-    @classmethod
-    def dictify(cls, obj, writer):
-        try:
-            timestamp_seconds = calendar.timegm(obj.utctimetuple())
-            pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
-        except AttributeError:
-            pts = calendar.timegm(obj.timetuple()) * 1e3
-
-        ts = int(round(pts))
-        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
-
-    @classmethod
-    def objectify(cls, ts, reader):
-        # Python timestamp expects seconds
-        return datetime.datetime.utcfromtimestamp(ts / 1000.0)
-
-
-# Based on current implementation, this class must always be declared before FloatIO.
-# Seems pretty fragile for future maintainers. Maybe look into this.
-class TimestampIO(_GraphSONTypeIO):
-    """A timestamp in Python is type float"""
-    python_type = statics.timestamp
-    graphson_type = "g:Timestamp"
-    graphson_base_type = "Timestamp"
-
-    @classmethod
-    def dictify(cls, obj, writer):
-        # Java timestamp expects milliseconds integer
-        # Have to use int because of legacy Python
-        ts = int(round(obj * 1000))
-        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
-
-    @classmethod
-    def objectify(cls, ts, reader):
-        # Python timestamp expects seconds
-        return cls.python_type(ts / 1000.0)
-
-
-class _NumberIO(_GraphSONTypeIO):
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-    @classmethod
-    def objectify(cls, v, _):
-        return cls.python_type(v)
-
-
-class ListIO(_GraphSONTypeIO):
-    python_type = ListType
-    graphson_type = "g:List"
-
-    @classmethod
-    def dictify(cls, l, writer):
-        new_list = []
-        for obj in l:
-            new_list.append(writer.toDict(obj))
-        return GraphSONUtil.typedValue("List", new_list)
-
-    @classmethod
-    def objectify(cls, l, reader):
-        new_list = []
-        for obj in l:
-            new_list.append(reader.toObject(obj))
-        return new_list
-
-
-class SetIO(_GraphSONTypeIO):
-    python_type = SetType
-    graphson_type = "g:Set"
-
-    @classmethod
-    def dictify(cls, s, writer):
-        new_list = []
-        for obj in s:
-            new_list.append(writer.toDict(obj))
-        return GraphSONUtil.typedValue("Set", new_list)
-
-    @classmethod
-    def objectify(cls, s, reader):
-        """
-        By default, returns a python set
-
-        In case Java returns numeric values of different types which
-        python don't recognize, coerce and return a list.
-        See comments of TINKERPOP-1844 for more details
-        """
-        new_list = [reader.toObject(obj) for obj in s]
-        new_set = set(new_list)
-        if len(new_list) != len(new_set):
-            log.warning("Coercing g:Set to list due to java numeric values. "
-                        "See TINKERPOP-1844 for more details.")
-            return new_list
-
-        return new_set
-
-
-class MapType(_GraphSONTypeIO):
-    python_type = DictType
-    graphson_type = "g:Map"
-
-    @classmethod
-    def dictify(cls, d, writer):
-        l = []
-        for key in d:
-            l.append(writer.toDict(key))
-            l.append(writer.toDict(d[key]))
-        return GraphSONUtil.typedValue("Map", l)
-
-    @classmethod
-    def objectify(cls, l, reader):
-        new_dict = {}
-        if len(l) > 0:
-            x = 0
-            while x < len(l):
-                new_dict[reader.toObject(l[x])] = reader.toObject(l[x + 1])
-                x = x + 2
-        return new_dict
-
-
-class BulkSetIO(_GraphSONTypeIO):
-    graphson_type = "g:BulkSet"
-
-    @classmethod
-    def objectify(cls, l, reader):
-        new_list = []
-
-        # this approach basically mimics what currently existed in 3.3.4 and prior versions where BulkSet is
-        # basically just coerced to list. the limitation here is that if the value of a bulk exceeds the size of
-        # a list (into the long space) then stuff won't work nice.
-        if len(l) > 0:
-            x = 0
-            while x < len(l):
-                obj = reader.toObject(l[x])
-                bulk = reader.toObject(l[x + 1])
-                for y in range(bulk):
-                    new_list.append(obj)
-                x = x + 2
-        return new_list
-
-
-class FloatIO(_NumberIO):
-    python_type = FloatType
-    graphson_type = "g:Float"
-    graphson_base_type = "Float"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        elif math.isnan(n):
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN")
-        elif math.isinf(n) and n > 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity")
-        elif math.isinf(n) and n < 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity")
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-    @classmethod
-    def objectify(cls, v, _):
-        if isinstance(v, str):
-            if v == 'NaN':
-                return float('nan')
-            elif v == "Infinity":
-                return float('inf')
-            elif v == "-Infinity":
-                return float('-inf')
-
-        return cls.python_type(v)
-
-
-class BigDecimalIO(_NumberIO):
-    python_type = Decimal
-    graphson_type = "gx:BigDecimal"
-    graphson_base_type = "BigDecimal"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        elif math.isnan(n):
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN", "gx")
-        elif math.isinf(n) and n > 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity", "gx")
-        elif math.isinf(n) and n < 0:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity", "gx")
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, str(n), "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        if isinstance(v, str):
-            if v == 'NaN':
-                return Decimal('nan')
-            elif v == "Infinity":
-                return Decimal('inf')
-            elif v == "-Infinity":
-                return Decimal('-inf')
-
-        return Decimal(v)
-
-
-class DoubleIO(FloatIO):
-    graphson_type = "g:Double"
-    graphson_base_type = "Double"
-
-
-class Int64IO(_NumberIO):
-    python_type = LongType
-    graphson_type = "g:Int64"
-    graphson_base_type = "Int64"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        # if we exceed Java long range then we need a BigInteger
-        if isinstance(n, bool):
-            return n
-        elif n < -9223372036854775808 or n > 9223372036854775807:
-            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-
-class BigIntegerIO(Int64IO):
-    graphson_type = "gx:BigInteger"
-
-
-class Int32IO(Int64IO):
-    python_type = IntType
-    graphson_type = "g:Int32"
-    graphson_base_type = "Int32"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        # if we exceed Java int range then we need a long
-        if isinstance(n, bool):
-            return n
-        elif n < -9223372036854775808 or n > 9223372036854775807:
-            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
-        elif n < -2147483648 or n > 2147483647:
-            return GraphSONUtil.typedValue("Int64", n)
-        else:
-            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-class ByteIO(_NumberIO):
-    python_type = SingleByte
-    graphson_type = "gx:Byte"
-    graphson_base_type = "Byte"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return int.__new__(SingleByte, v)
-
-
-class ByteBufferIO(_GraphSONTypeIO):
-    python_type = ByteBufferType
-    graphson_type = "gx:ByteBuffer"
-    graphson_base_type = "ByteBuffer"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, "".join(chr(x) for x in n), "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return cls.python_type(v, "utf8")
-
-
-class CharIO(_GraphSONTypeIO):
-    python_type = SingleChar
-    graphson_type = "gx:Char"
-    graphson_base_type = "Char"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return str.__new__(SingleChar, v)
-
-
-class DurationIO(_GraphSONTypeIO):
-    python_type = timedelta
-    graphson_type = "gx:Duration"
-    graphson_base_type = "Duration"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, duration_isoformat(n), "gx")
-
-    @classmethod
-    def objectify(cls, v, _):
-        return parse_duration(v)
-
-
-class VertexDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Vertex"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
-
-
-class EdgeDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Edge"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Edge(reader.toObject(d["id"]),
-                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
-                    d.get("label", "edge"),
-                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
-
-
-class VertexPropertyDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:VertexProperty"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
-        return VertexProperty(reader.toObject(d["id"]),
-                              d["label"],
-                              reader.toObject(d["value"]),
-                              vertex)
-
-
-class PropertyDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Property"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        element = reader.toObject(d["element"]) if "element" in d else None
-        return Property(d["key"], reader.toObject(d["value"]), element)
-
-
-class PathDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Path"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Path(reader.toObject(d["labels"]), reader.toObject(d["objects"]))
-
-
-class TDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:T"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return T[d]
-
-
-class DirectionIO(_GraphSONTypeIO):
-    graphson_type = "g:Direction"
-    graphson_base_type = "Direction"
-    python_type = Direction
-
-    @classmethod
-    def dictify(cls, d, writer):
-        return GraphSONUtil.typedValue(cls.graphson_base_type, d.name, "g")
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Direction[d]
-
-
-class TraversalMetricsDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:TraversalMetrics"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return reader.toObject(d)
-
-
-class MetricsDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Metrics"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return reader.toObject(d)
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py
deleted file mode 100644
index 40d2518..0000000
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ /dev/null
@@ -1,292 +0,0 @@
-#
-# 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.
-#
-
-import json
-import re
-from gremlin_python.structure.graph import Path
-from gremlin_python.process.anonymous_traversal import traversal
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO, WithOptions
-from radish import given, when, then
-from hamcrest import *
-
-regex_all = re.compile(r"Pop\.all")
-regex_and = re.compile(r"([(.,\s])and\(")
-regex_as = re.compile(r"([(.,\s])as\(")
-regex_from = re.compile(r"([(.,\s])from\(")
-regex_global = re.compile(r"([(.,\s])global")
-regex_cardlist = re.compile(r"Cardinality\.list")
-regex_in = re.compile(r"([(.,\s])in\(")
-regex_is = re.compile(r"([(.,\s])is\(")
-regex_not = re.compile(r"([(.,\s])not\(")
-regex_or = re.compile(r"([(.,\s])or\(")
-regex_with = re.compile(r"([(.,\s])with\(")
-regex_true = re.compile(r"(true)")
-regex_false = re.compile(r"(false)")
-
-outV = __.outV
-label = __.label
-inV = __.inV
-project = __.project
-tail = __.tail
-
-ignores = []
-
-
-@given("the {graph_name:w} graph")
-def choose_graph(step, graph_name):
-    step.context.graph_name = graph_name
-    step.context.g = traversal().withRemote(step.context.remote_conn[graph_name])
-
-
-@given("the graph initializer of")
-def initialize_graph(step):
-    t = _make_traversal(step.context.g, step.text, {})
-
-    # just be sure that the traversal returns something to prove that it worked to some degree. probably
-    # is overkill to try to assert the complete success of this init operation. presumably the test
-    # suite would fail elsewhere if this didn't work which would help identify a problem.
-    result = t.toList()
-    assert len(result) > 0
-
-    # add the first result - if a map - to the bindings. this is useful for cases when parameters for
-    # the test traversal need to come from the original graph initializer (i.e. a new graph is created
-    # and you need the id of a vertex from that graph)
-
-
-@given("an unsupported test")
-def unsupported_scenario(step):
-    # this is a do nothing step as the test can't be supported for whatever reason
-    return
-
-
-@given("using the parameter {param_name:w} defined as {param:QuotedString}")
-def add_parameter(step, param_name, param):
-    if not hasattr(step.context, "traversal_params"):
-        step.context.traversal_params = {}
-
-    step.context.traversal_params[param_name] = _convert(param.replace('\\"', '"'), step.context)
-
-
-@given("the traversal of")
-def translate_traversal(step):
-    step.context.ignore = ignores.__contains__(step.text)
-    step.context.traversal = _make_traversal(
-        step.context.g, step.text,
-        step.context.traversal_params if hasattr(step.context, "traversal_params") else {})
-
-
-@when("iterated to list")
-def iterate_the_traversal(step):
-    if step.context.ignore:
-        return
-    
-    step.context.result = map(lambda x: _convert_results(x), step.context.traversal.toList())
-
-
-@when("iterated next")
-def next_the_traversal(step):
-    if step.context.ignore:
-        return
-
-    step.context.result = map(lambda x: _convert_results(x), step.context.traversal.next())
-
-
-@then("the result should be {characterized_as:w}")
-def assert_result(step, characterized_as):
-    if step.context.ignore:
-        return
-
-    if characterized_as == "empty":        # no results
-        assert_that(len(step.context.result), equal_to(0))
-    elif characterized_as == "ordered":    # results asserted in the order of the data table
-        _table_assertion(step.table, step.context.result, step.context, True)
-    elif characterized_as == "unordered":  # results asserted in any order
-        _table_assertion(step.table, step.context.result, step.context, False)
-    elif characterized_as == "of":         # results may be of any of the specified items in the data table
-        _any_assertion(step.table, step.context.result, step.context)
-    else:
-        raise ValueError("unknown data characterization of " + characterized_as)
-
-
-@then("the graph should return {count:d} for count of {traversal_string:QuotedString}")
-def assert_side_effects(step, count, traversal_string):
-    if step.context.ignore:
-        return
-
-    t = _make_traversal(step.context.g, traversal_string.replace('\\"', '"'),
-                        step.context.traversal_params if hasattr(step.context, "traversal_params") else {})
-    assert_that(t.count().next(), equal_to(count))
-
-
-@then("the result should have a count of {count:d}")
-def assert_count(step, count):
-    assert_that(len(step.context.result), equal_to(count))
-
-
-@then("nothing should happen because")
-def nothing_happening(step):
-    return
-
-
-def _convert(val, ctx):
-    graph_name = ctx.graph_name
-    if isinstance(val, dict):                                           # convert dictionary keys/values
-        n = {}
-        for key, value in val.items():
-            n[_convert(key, ctx)] = _convert(value, ctx)
-        return n
-    elif isinstance(val, unicode):                                      # convert annoying python 2.x unicode nonsense
-        return _convert(val.encode('utf-8'), ctx)
-    elif isinstance(val, str) and re.match("^l\[.*\]$", val):           # parse list
-        return [] if val == "l[]" else list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
-    elif isinstance(val, str) and re.match("^s\[.*\]$", val):           # parse set
-        return set() if val == "s[]" else set(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
-    elif isinstance(val, str) and re.match("^d\[.*\]\.[ilfdm]$", val):  # parse numeric
-        return float(val[2:-3]) if val[2:-3].__contains__(".") else long(val[2:-3])
-    elif isinstance(val, str) and re.match("^v\[.*\]\.id$", val):       # parse vertex id
-        return __find_cached_element(ctx, graph_name, val[2:-4], "v").id
-    elif isinstance(val, str) and re.match("^v\[.*\]\.sid$", val):      # parse vertex id as string
-        return str(__find_cached_element(ctx, graph_name, val[2:-5], "v").id)
-    elif isinstance(val, str) and re.match("^v\[.*\]$", val):           # parse vertex
-        return __find_cached_element(ctx, graph_name, val[2:-1], "v")
-    elif isinstance(val, str) and re.match("^e\[.*\]\.id$", val):       # parse edge id
-        return __find_cached_element(ctx, graph_name, val[2:-4], "e").id
-    elif isinstance(val, str) and re.match("^e\[.*\]\.sid$", val):      # parse edge id as string
-        return str(__find_cached_element(ctx, graph_name, val[2:-5], "e").id)
-    elif isinstance(val, str) and re.match("^e\[.*\]$", val):           # parse edge
-        return __find_cached_element(ctx, graph_name, val[2:-1], "e")
-    elif isinstance(val, str) and re.match("^m\[.*\]$", val):           # parse json as a map
-        return _convert(json.loads(val[2:-1]), ctx)
-    elif isinstance(val, str) and re.match("^p\[.*\]$", val):           # parse path
-        path_objects = list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
-        return Path([set([])], path_objects)
-    elif isinstance(val, str) and re.match("^c\[.*\]$", val):           # parse lambda/closure
-        return lambda: (val[2:-1], "gremlin-groovy")
-    elif isinstance(val, str) and re.match("^t\[.*\]$", val):           # parse instance of T enum
-        return T[val[2:-1]]
-    elif isinstance(val, str) and re.match("^D\[.*\]$", val):           # parse instance of Direction enum
-        return Direction[val[2:-1]]
-    else:
-        return val
-
-
-def __find_cached_element(ctx, graph_name, identifier, element_type):
-    if graph_name == "empty":
-        cache = __create_lookup_v(ctx.remote_conn["empty"]) if element_type == "v" else __create_lookup_e(ctx.remote_conn["empty"])
-    else:
-        cache = ctx.lookup_v[graph_name] if element_type == "v" else ctx.lookup_e[graph_name]
-
-    return cache[identifier]
-
-
-def _convert_results(val):
-    if isinstance(val, Path):
-        # kill out labels as they aren't in the assertion logic
-        return Path([set([])], map(lambda p: p.encode("utf-8") if isinstance(p, unicode) else p, val.objects))
-    else:
-        return val
-
-
-def _any_assertion(data, result, ctx):
-    converted = [_convert(line['result'], ctx) for line in data]
-    for r in result:
-        assert_that(r, is_in(converted))
-
-
-def _table_assertion(data, result, ctx, ordered):
-    # results from traversal should have the same number of entries as the feature data table
-    assert_that(len(result), equal_to(len(data)), "result:" + str(result))
-
-    results_to_test = list(result)
-
-    # finds a match in the results for each line of data to assert and then removes that item
-    # from the list - in the end there should be no items left over and each will have been asserted
-    for ix, line in enumerate(data):
-        val = _convert(line['result'], ctx)
-
-        # clear the labels since we don't define them in .feature files
-        if isinstance(val, Path):
-            val.labels = [set([])]
-
-        if ordered:
-            assert_that(results_to_test[ix], equal_to(val))
-        else:
-            assert_that(val, is_in(results_to_test))
-            results_to_test.remove(val)
-
-    if not ordered:
-        assert_that(len(results_to_test), is_(0))
-
-
-def _translate(traversal_):
-    replaced = traversal_.replace("\n", "")
-    replaced = regex_all.sub(r"Pop.all_", replaced)
-    replaced = regex_cardlist.sub(r"Cardinality.list_", replaced)
-    replaced = regex_and.sub(r"\1and_(", replaced)
-    replaced = regex_from.sub(r"\1from_(", replaced)
-    replaced = regex_global.sub(r"\1global_", replaced)
-    replaced = regex_as.sub(r"\1as_(", replaced)
-    replaced = regex_is.sub(r"\1is_(", replaced)
-    replaced = regex_not.sub(r"\1not_(", replaced)
-    replaced = regex_or.sub(r"\1or_(", replaced)
-    replaced = regex_in.sub(r"\1in_(", replaced)
-    replaced = regex_with.sub(r"\1with_(", replaced)
-    replaced = regex_true.sub(r"True", replaced)
-    return regex_false.sub(r"False", replaced)
-
-
-def _make_traversal(g, traversal_string, params):
-    b = {"g": g,
-         "__": __,
-         "Barrier": Barrier,
-         "Cardinality": Cardinality,
-         "Column": Column,
-         "Direction": Direction,
-         "Order": Order,
-         "P": P,
-         "TextP": TextP,
-         "IO": IO,
-         "Pick": Pick,
-         "Pop": Pop,
-         "Scope": Scope,
-         "Operator": Operator,
-         "T": T,
-         "WithOptions": WithOptions}
-
-    b.update(params)
-
-    return eval(_translate(traversal_string), b)
-
-
-def __create_lookup_v(remote):
-    g = traversal().withRemote(remote)
-
-    # hold a map of name/vertex for use in asserting results
-    return g.V().group().by('name').by(tail()).next()
-
-
-def __create_lookup_e(remote):
-    g = traversal().withRemote(remote)
-
-    # hold a map of the "name"/edge for use in asserting results - "name" in this context is in the form of
-    # outgoingV-label->incomingV
-    return g.E().group(). \
-        by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + it.inVertex().value('name')", "gremlin-groovy")). \
-        by(tail()).next()
diff --git a/gremlin-python/src/main/jython/radish/terrain.py b/gremlin-python/src/main/jython/radish/terrain.py
deleted file mode 100644
index 8fa01d02..0000000
--- a/gremlin-python/src/main/jython/radish/terrain.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#
-# 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.
-#
-
-from gremlin_python.process.anonymous_traversal import traversal
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.driver import serializer
-from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
-from radish import before, after, world
-
-outV = __.outV
-label = __.label
-inV = __.inV
-project = __.project
-tail = __.tail
-
-
-@before.all
-def prepare_static_traversal_source(features, marker):
-    # as the various traversal sources for testing do not change their data, there is no need to re-create remotes
-    # and client side lookup data over and over. it can be created once for all tests and be reused.
-    cache = {}
-    for graph_name in (("modern", "gmodern"), ("classic", "gclassic"), ("crew", "gcrew"), ("grateful", "ggrateful"), ("sink", "gsink")):
-        cache[graph_name[0]] = {}
-        remote = __create_remote(graph_name[1])
-        cache[graph_name[0]]["remote_conn"] = __create_remote(graph_name[1])
-        cache[graph_name[0]]["lookup_v"] = __create_lookup_v(remote)
-        cache[graph_name[0]]["lookup_e"] = __create_lookup_e(remote)
-
-    # store the cache on the global context so that remotes can be shutdown cleanly at the end of the tests
-    world.cache = cache
-
-    # iterate each feature and apply the cached remotes/lookups to each scenario context so that they are
-    # accessible to the feature steps for test logic
-    for feature in features:
-        for scenario in feature.all_scenarios:
-            scenario.context.remote_conn = {}
-            scenario.context.lookup_v = {}
-            scenario.context.lookup_e = {}
-
-            for graph_name in ("modern", "classic", "crew", "grateful", "sink"):
-                scenario.context.remote_conn[graph_name] = cache[graph_name]["remote_conn"]
-                scenario.context.lookup_v[graph_name] = cache[graph_name]["lookup_v"]
-                scenario.context.lookup_e[graph_name] = cache[graph_name]["lookup_e"]
-
-            # setup the "empty" lookups as needed
-            scenario.context.lookup_v["empty"] = {}
-            scenario.context.lookup_e["empty"] = {}
-
-
-@before.each_scenario
-def prepare_traversal_source(scenario):
-    # some tests create data - create a fresh remote to the empty graph and clear that graph prior to each test
-    remote = __create_remote("ggraph")
-    scenario.context.remote_conn["empty"] = remote
-    g = traversal().withRemote(remote)
-    g.V().drop().iterate()
-
-
-@after.each_scenario
-def close_traversal_source(scenario):
-    scenario.context.remote_conn["empty"].close()
-
-
-@after.all
-def close_static_traversal_source(features, marker):
-    for key, value in world.cache.iteritems():
-        value["remote_conn"].close()
-
-
-def __create_remote(server_graph_name):
-    if not("serializer" in world.config.user_data):
-        raise ValueError('test configuration requires setting of --user-data="serializer={mime-type}"')
-
-    if world.config.user_data["serializer"] == "application/vnd.gremlin-v3.0+json":
-        s = serializer.GraphSONSerializersV3d0()
-    elif world.config.user_data["serializer"] == "application/vnd.graphbinary-v1.0":
-        s = serializer.GraphBinarySerializersV1()
-    else:
-        raise ValueError('serializer not found - ' + world.config.user_data["serializer"])
-
-    return DriverRemoteConnection('ws://localhost:45940/gremlin', server_graph_name, message_serializer=s)
-
-
-def __create_lookup_v(remote):
-    g = traversal().withRemote(remote)
-
-    # hold a map of name/vertex for use in asserting results
-    return g.V().group().by('name').by(tail()).next()
-
-
-def __create_lookup_e(remote):
-    g = traversal().withRemote(remote)
-
-    # hold a map of the "name"/edge for use in asserting results - "name" in this context is in the form of
-    # outgoingV-label->incomingV
-    return g.E().group(). \
-        by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + it.inVertex().value('name')", "gremlin-groovy")). \
-        by(tail()).next()
diff --git a/gremlin-python/src/main/jython/setup.py b/gremlin-python/src/main/jython/setup.py
deleted file mode 100644
index 3e630ec..0000000
--- a/gremlin-python/src/main/jython/setup.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-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.
-"""
-import codecs
-import os
-import sys
-import time
-from setuptools import setup
-
-# Folder containing the setup.py
-root = os.path.dirname(os.path.abspath(__file__))
-
-# Path to __version__ module
-version_file = os.path.join(root, 'gremlin_python', '__version__.py')
-
-# Check if this is a source distribution.
-# If not create the __version__ module containing the version
-if not os.path.exists(os.path.join(root, 'PKG-INFO')):
-    timestamp = int(os.getenv('TIMESTAMP', time.time() * 1000)) / 1000
-    fd = codecs.open(version_file, 'w', 'utf-8')
-    fd.write("'''")
-    fd.write(__doc__)
-    fd.write("'''\n")
-    fd.write('version   = %r\n' % os.getenv('VERSION', '?').replace('-SNAPSHOT', '.dev-%d' % timestamp))
-    fd.write('timestamp = %d\n' % timestamp)
-    fd.close()
-# Load version
-from gremlin_python import __version__
-
-version = __version__.version
-
-install_requires = [
-    'aenum>=1.4.5,<3.0.0',
-    'tornado>=4.4.1,<6.0',
-    'six>=1.10.0,<2.0.0',
-    'isodate>=0.6.0,<1.0.0',
-    'pyparsing>=2.4.7,<3.0.0'
-]
-
-if sys.version_info < (3, 2):
-    install_requires += ['futures>=3.0.5,<4.0.0']
-
-if sys.version_info < (3, 5):
-    install_requires += ['pyparsing>=2.4.6,<3.0.0']
-
-setup(
-    name='gremlinpython',
-    version=version,
-    packages=['gremlin_python', 'gremlin_python.driver',
-              'gremlin_python.driver.tornado', 'gremlin_python.process',
-              'gremlin_python.structure', 'gremlin_python.structure.io'],
-    license='Apache 2',
-    url='http://tinkerpop.apache.org',
-    description='Gremlin-Python for Apache TinkerPop',
-    long_description=codecs.open("README.rst", "r", "UTF-8").read(),
-    long_description_content_type='text/x-rst',
-    test_suite="tests",
-    data_files=[("", ["LICENSE", "NOTICE"])],
-    setup_requires=[
-        'pytest-runner',
-    ],
-    tests_require=[
-        'pytest>=4.6.4,<5.0.0',
-        'mock>=3.0.5,<4.0.0',
-        'radish-bdd==0.8.6',
-        'PyHamcrest>=1.9.0,<2.0.0'
-    ],
-    install_requires=install_requires,
-    classifiers=[
-        "Intended Audience :: Developers",
-        "License :: OSI Approved :: Apache Software License",
-        "Natural Language :: English",
-        "Programming Language :: Python :: 2.7",
-        "Programming Language :: Python :: 3.4",
-        "Programming Language :: Python :: 3.5",
-    ]
-)
diff --git a/gremlin-python/src/main/jython/tests/conftest.py b/gremlin-python/src/main/jython/tests/conftest.py
deleted file mode 100644
index cc3855e..0000000
--- a/gremlin-python/src/main/jython/tests/conftest.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#
-# 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.
-#
-import concurrent.futures
-import pytest
-
-from six.moves import queue
-
-from gremlin_python.driver.client import Client
-from gremlin_python.driver.connection import Connection
-from gremlin_python.driver import serializer
-from gremlin_python.driver.driver_remote_connection import (
-    DriverRemoteConnection)
-from gremlin_python.driver.protocol import GremlinServerWSProtocol
-from gremlin_python.driver.serializer import (
-    GraphSONMessageSerializer, GraphSONSerializersV2d0, GraphSONSerializersV3d0,
-    GraphBinarySerializersV1)
-from gremlin_python.driver.tornado.transport import TornadoTransport
-
-# docker Gremlin Server = 172.17.0.2
-gremlin_server_host = "localhost"
-gremlin_server_url = 'ws://' + gremlin_server_host + ':45940/gremlin'
-
-
-@pytest.fixture
-def connection(request):
-    protocol = GremlinServerWSProtocol(
-        GraphSONMessageSerializer(),
-        username='stephen', password='password')
-    executor = concurrent.futures.ThreadPoolExecutor(5)
-    pool = queue.Queue()
-    try:
-        conn = Connection(gremlin_server_url, 'gmodern', protocol,
-                          lambda: TornadoTransport(), executor, pool)
-    except OSError:
-        executor.shutdown()
-        pytest.skip('Gremlin Server is not running')
-    else:
-        def fin():
-            executor.shutdown()
-            conn.close()
-        request.addfinalizer(fin)
-        return conn
-
-
-@pytest.fixture
-def client(request):
-    try:
-        client = Client(gremlin_server_url, 'gmodern')
-    except OSError:
-        pytest.skip('Gremlin Server is not running')
-    else:
-        def fin():
-            client.close()
-        request.addfinalizer(fin)
-        return client
-
-
-@pytest.fixture
-def secure_client(request):
-    try:
-        client = Client('ws://' + gremlin_server_host + ':45941/gremlin', 'gmodern',
-                        username='stephen', password='password')
-    except OSError:
-        pytest.skip('Gremlin Server is not running')
-    else:
-        def fin():
-            client.close()
-        request.addfinalizer(fin)
-        return client
-
-
-@pytest.fixture(params=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
-def remote_connection(request):
-    try:
-        if request.param == 'graphbinaryv1':
-            remote_conn = DriverRemoteConnection(gremlin_server_url, 'gmodern',
-                                                 message_serializer=serializer.GraphBinarySerializersV1())
-        elif request.param == 'graphsonv2':
-            remote_conn = DriverRemoteConnection(gremlin_server_url, 'gmodern',
-                                                 message_serializer=serializer.GraphSONSerializersV2d0())
-        elif request.param == 'graphsonv3':
-            remote_conn = DriverRemoteConnection(gremlin_server_url, 'gmodern',
-                                                 message_serializer=serializer.GraphSONSerializersV3d0())
-        else:
-            raise ValueError("Invalid serializer option - " + request.param)
-    except OSError:
-        pytest.skip('Gremlin Server is not running')
-    else:
-        def fin():
-            remote_conn.close()
-        request.addfinalizer(fin)
-        return remote_conn
-
-
-@pytest.fixture
-def remote_connection_v2(request):
-    try:
-        remote_conn = DriverRemoteConnection(gremlin_server_url, 'g',
-                                             message_serializer=serializer.GraphSONSerializersV2d0())
-    except OSError:
-        pytest.skip('Gremlin Server is not running')
-    else:
-        def fin():
-            remote_conn.close()
-        request.addfinalizer(fin)
-        return remote_conn
-
-
-@pytest.fixture
-def graphson_serializer_v2(request):
-    return GraphSONSerializersV2d0()
-
-
-@pytest.fixture
-def graphson_serializer_v3(request):
-    return GraphSONSerializersV3d0()
-
-
-@pytest.fixture
-def graphbinary_serializer_v1(request):
-    return GraphBinarySerializersV1()
diff --git a/gremlin-python/src/main/jython/tests/driver/test_client.py b/gremlin-python/src/main/jython/tests/driver/test_client.py
deleted file mode 100644
index be45b48..0000000
--- a/gremlin-python/src/main/jython/tests/driver/test_client.py
+++ /dev/null
@@ -1,325 +0,0 @@
-#
-# 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.
-#
-import threading
-import uuid
-
-from gremlin_python.driver.client import Client
-from gremlin_python.driver.protocol import GremlinServerError
-from gremlin_python.driver.request import RequestMessage
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.strategies import OptionsStrategy
-from gremlin_python.structure.graph import Graph
-
-__author__ = 'David M. Brown (davebshow@gmail.com)'
-
-
-def test_connection(connection):
-    g = Graph().traversal()
-    t = g.V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    results_set = connection.write(message).result()
-    future = results_set.all()
-    results = future.result()
-    assert len(results) == 6
-    assert isinstance(results, list)
-    assert results_set.done.done()
-    assert 'host' in results_set.status_attributes
-
-
-def test_client_simple_eval(client):
-    assert client.submit('1 + 1').all().result()[0] == 2
-
-
-def test_client_simple_eval_bindings(client):
-    assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
-
-
-def test_client_eval_traversal(client):
-    assert len(client.submit('g.V()').all().result()) == 6
-
-
-def test_client_error(client):
-    try:
-        # should fire an exception
-        client.submit('1/0').all().result()
-        assert False
-    except GremlinServerError as ex:
-        assert 'exceptions' in ex.status_attributes
-        assert 'stackTrace' in ex.status_attributes
-
-
-def test_client_connection_pool_after_error(client):
-    # Overwrite fixture with pool_size=1 client
-    client = Client('ws://localhost:45940/gremlin', 'gmodern', pool_size=1)
-
-    try:
-        # should fire an exception
-        client.submit('1/0').all().result()
-        assert False
-    except GremlinServerError as gse:
-        # expecting the pool size to be 1 again after query returned
-        assert gse.status_code == 597
-        assert client.available_pool_size == 1
-
-
-def test_client_bytecode(client):
-    g = Graph().traversal()
-    t = g.V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    result_set = client.submit(message)
-    assert len(result_set.all().result()) == 6
-
-
-def test_client_bytecode_options(client):
-    # smoke test to validate serialization of OptionsStrategy. no way to really validate this from an integration
-    # test perspective because there's no way to access the internals of the strategy via bytecode
-    g = Graph().traversal()
-    t = g.withStrategies(OptionsStrategy(options={"x": "test", "y": True})).V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    result_set = client.submit(message)
-    assert len(result_set.all().result()) == 6
-    ##
-    t = g.with_("x", "test").with_("y", True).V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    result_set = client.submit(message)
-    assert len(result_set.all().result()) == 6
-
-
-def test_iterate_result_set(client):
-    g = Graph().traversal()
-    t = g.V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 6
-
-
-def test_client_async(client):
-    g = Graph().traversal()
-    t = g.V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    future = client.submitAsync(message)
-    result_set = future.result()
-    assert len(result_set.all().result()) == 6
-
-
-def test_connection_share(client):
-    # Overwrite fixture with pool_size=1 client
-    client = Client('ws://localhost:45940/gremlin', 'gmodern', pool_size=1)
-    g = Graph().traversal()
-    t = g.V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    message2 = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    future = client.submitAsync(message)
-    future2 = client.submitAsync(message2)
-
-    result_set2 = future2.result()
-    assert len(result_set2.all().result()) == 6
-
-    # This future has to finish for the second to yield result - pool_size=1
-    assert future.done()
-    result_set = future.result()
-    assert len(result_set.all().result()) == 6
-
-
-def test_multi_conn_pool(client):
-    g = Graph().traversal()
-    t = g.V()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    message2 = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    client = Client('ws://localhost:45940/gremlin', 'g', pool_size=1)
-    future = client.submitAsync(message)
-    future2 = client.submitAsync(message2)
-
-    result_set2 = future2.result()
-    assert len(result_set2.all().result()) == 6
-
-    # with connection pool `future` may or may not be done here
-    result_set = future.result()
-    assert len(result_set.all().result()) == 6
-
-
-def test_multi_thread_pool(client):
-    g = Graph().traversal()
-    traversals = [g.V(),
-                  g.V().count(),
-                  g.E(),
-                  g.E().count()
-                  ]
-    results = [[] for _ in traversals]
-
-    # Use a condition variable to synchronise a group of threads, which should also inject some
-    # non-determinism into the run-time execution order
-    condition = threading.Condition()
-
-    def thread_run(tr, result_list):
-        message = RequestMessage('traversal', 'bytecode', {'gremlin': tr.bytecode, 'aliases': {'g': 'gmodern'}})
-        with condition:
-            condition.wait(5)
-        result_set = client.submit(message)
-        for result in result_set:
-            result_list.append(result)
-
-    threads = []
-    for i in range(len(results)):
-        thread = threading.Thread(target=thread_run,
-                                  args=(traversals[i], results[i]),
-                                  name="test_multi_thread_pool_%d" % i)
-        thread.daemon = True
-        threads.append(thread)
-        thread.start()
-    with condition:
-        condition.notify_all()
-
-    for t in threads:
-        t.join(5)
-
-    assert len(results[0][0]) == 6
-    assert results[1][0][0].object == 6
-    assert len(results[2][0]) == 6
-    assert results[3][0][0].object == 6
-
-
-def test_client_bytecode_with_int(client):
-    g = Graph().traversal()
-    t = g.V().has('age', 851401972585122).count()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 1
-
-
-def test_multi_request_in_session(client):
-    # Overwrite fixture with session client
-    session_id = str(uuid.uuid4())
-    client = Client('ws://localhost:45940/gremlin', 'g', session=session_id)
-
-    assert client.submit('x = 1').all().result()[0] == 1
-    assert client.submit('x + 2').all().result()[0] == 3
-
-    client.close()
-
-    # attempt reconnect to session and make sure "x" is no longer a thing
-    client = Client('ws://localhost:45940/gremlin', 'g', session=session_id)
-    try:
-        # should fire an exception
-        client.submit('x').all().result()
-        assert False
-    except Exception:
-        assert True
-
-
-def test_client_pool_in_session(client):
-    # Overwrite fixture with pool_size=2 client
-    try:
-        # should fire an exception
-        client = Client('ws://localhost:45940/gremlin', 'g', session=str(uuid.uuid4()), pool_size=2)
-        assert False
-    except Exception:
-        assert True
-
-
-def test_big_result_set(client):
-    g = Graph().traversal()
-    t = g.inject(1).repeat(__.addV('person').property('name', __.loops())).times(20000).count()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 1
-
-    t = g.V().limit(10)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 10
-
-    t = g.V().limit(100)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 100
-
-    t = g.V().limit(1000)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 1000
-
-    t = g.V().limit(10000)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 10000
-
-
-def test_big_result_set_secure(secure_client):
-    g = Graph().traversal()
-    t = g.inject(1).repeat(__.addV('person').property('name', __.loops())).times(20000).count()
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = secure_client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 1
-
-    t = g.V().limit(10)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = secure_client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 10
-
-    t = g.V().limit(100)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = secure_client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 100
-
-    t = g.V().limit(1000)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = secure_client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 1000
-
-    t = g.V().limit(10000)
-    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
-    result_set = secure_client.submit(message)
-    results = []
-    for result in result_set:
-        results += result
-    assert len(results) == 10000
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
deleted file mode 100644
index 44d8dea..0000000
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ /dev/null
@@ -1,314 +0,0 @@
-#
-# 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.
-#
-import pytest
-
-from tornado import ioloop, gen
-
-from gremlin_python import statics
-from gremlin_python.driver.protocol import GremlinServerError
-from gremlin_python.statics import long
-from gremlin_python.driver.driver_remote_connection import (
-    DriverRemoteConnection)
-from gremlin_python.process.traversal import Traverser
-from gremlin_python.process.traversal import TraversalStrategy
-from gremlin_python.process.traversal import Bindings
-from gremlin_python.process.traversal import P
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.anonymous_traversal import traversal
-from gremlin_python.structure.graph import Vertex
-from gremlin_python.process.strategies import SubgraphStrategy, ReservedKeysVerificationStrategy
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-
-class TestDriverRemoteConnection(object):
-    def test_traversals(self, remote_connection):
-        statics.load_statics(globals())
-        g = traversal().withRemote(remote_connection)
-
-        assert long(6) == g.V().count().toList()[0]
-        # #
-        assert Vertex(1) == g.V(1).next()
-        assert 1 == g.V(1).id().next()
-        assert Traverser(Vertex(1)) == g.V(1).nextTraverser()
-        assert 1 == len(g.V(1).toList())
-        assert isinstance(g.V(1).toList(), list)
-        results = g.V().repeat(out()).times(2).name
-        results = results.toList()
-        assert 2 == len(results)
-        assert "lop" in results
-        assert "ripple" in results
-        # #
-        assert 10 == g.V().repeat(both()).times(5)[0:10].count().next()
-        assert 1 == g.V().repeat(both()).times(5)[0:1].count().next()
-        assert 0 == g.V().repeat(both()).times(5)[0:0].count().next()
-        assert 4 == g.V()[2:].count().next()
-        assert 2 == g.V()[:2].count().next()
-        # #
-        results = g.withSideEffect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where(P.within('a')).toList()
-        assert 2 == len(results)
-        assert 'josh' in results
-        assert 'peter' in results
-        # #
-        results = g.V().out().profile().toList()
-        assert 1 == len(results)
-        assert 'metrics' in results[0]
-        assert 'dur' in results[0]
-        # #
-        results = g.V().has('name', 'peter').as_('a').out('created').as_('b').select('a', 'b').by(
-            __.valueMap()).toList()
-        assert 1 == len(results)
-        assert 'peter' == results[0]['a']['name'][0]
-        assert 35 == results[0]['a']['age'][0]
-        assert 'lop' == results[0]['b']['name'][0]
-        assert 'java' == results[0]['b']['lang'][0]
-        assert 2 == len(results[0]['a'])
-        assert 2 == len(results[0]['b'])
-        # #
-        results = g.V(1).inject(g.V(2).next()).values('name').toList()
-        assert 2 == len(results)
-        assert 'marko' in results
-        assert 'vadas' in results
-        # #
-        results = g.V().has('person', 'name', 'marko').map(lambda: ("it.get().value('name')", "gremlin-groovy")).toList()
-        assert 1 == len(results)
-        assert 'marko' in results
-        # #
-        # this test just validates that the underscored versions of steps conflicting with Gremlin work
-        # properly and can be removed when the old steps are removed - TINKERPOP-2272
-        results = g.V().filter_(__.values('age').sum_().and_(
-            __.max_().is_(gt(0)), __.min_().is_(gt(0)))).range_(0, 1).id_().next()
-        assert 1 == results
-        # #
-        # test binding in P
-        results = g.V().has('person', 'age', Bindings.of('x', lt(30))).count().next()
-        assert 2 == results
-
-
-    def test_lambda_traversals(self, remote_connection):
-        statics.load_statics(globals())
-        assert "remoteconnection[ws://localhost:45940/gremlin,gmodern]" == str(remote_connection)
-        g = traversal().withRemote(remote_connection)
-
-        assert 24.0 == g.withSack(1.0, lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum().next()
-        assert 24.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum().next()
-
-        assert 48.0 == g.withSack(1.0, lambda: ("x, y ->  x + y + 1", "gremlin-groovy")).V().both().sack().sum().next()
-        assert 48.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x, y ->  x + y + 1", "gremlin-groovy")).V().both().sack().sum().next()
-
-    def test_iteration(self, remote_connection):
-        statics.load_statics(globals())
-        g = traversal().withRemote(remote_connection)
-
-        t = g.V().count()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert 6 == t.next()
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-
-        t = g.V().has('name', P.within('marko', 'peter')).values('name').order()
-        assert "marko" == t.next()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert t.hasNext()
-        assert "peter" == t.next()
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-        assert not(t.hasNext())
-
-        try:
-            t.next()
-            assert False
-        except StopIteration:
-            assert True
-
-    def test_strategies(self, remote_connection):
-        statics.load_statics(globals())
-        g = traversal().withRemote(remote_connection). \
-            withStrategies(TraversalStrategy("SubgraphStrategy",
-                                             {"vertices": __.hasLabel("person"),
-                                              "edges": __.hasLabel("created")},
-                                              "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy"))
-        assert 4 == g.V().count().next()
-        assert 0 == g.E().count().next()
-        assert 1 == g.V().label().dedup().count().next()
-        assert 4 == g.V().filter(lambda: ("lambda x: True", "gremlin-python")).count().next()
-        assert "person" == g.V().label().dedup().next()
-        #
-        g = traversal().withRemote(remote_connection). \
-            withStrategies(SubgraphStrategy(vertices=__.hasLabel("person"), edges=__.hasLabel("created")))
-        assert 4 == g.V().count().next()
-        assert 0 == g.E().count().next()
-        assert 1 == g.V().label().dedup().count().next()
-        assert "person" == g.V().label().dedup().next()
-        #
-        g = traversal().withRemote(remote_connection). \
-            withStrategies(SubgraphStrategy(edges=__.hasLabel("created")))
-        assert 6 == g.V().count().next()
-        assert 4 == g.E().count().next()
-        assert 1 == g.E().label().dedup().count().next()
-        assert "created" == g.E().label().dedup().next()
-        #
-        g = g.withoutStrategies(SubgraphStrategy). \
-            withComputer(vertices=__.has("name", "marko"), edges=__.limit(0))
-        assert 1 == g.V().count().next()
-        assert 0 == g.E().count().next()
-        assert "person" == g.V().label().next()
-        assert "marko" == g.V().name.next()
-        #
-        g = traversal().withRemote(remote_connection).withComputer()
-        assert 6 == g.V().count().next()
-        assert 6 == g.E().count().next()
-        #
-        g = traversal().withRemote(remote_connection). \
-            withStrategies(ReservedKeysVerificationStrategy(throw_exception=True))
-        try:
-            g.addV("person").property("id", "please-don't-use-id").iterate()
-            assert False
-        except GremlinServerError as gse:
-            assert gse.status_code == 500
-
-    def test_side_effects(self, remote_connection):
-        statics.load_statics(globals())
-        #
-        g = traversal().withRemote(remote_connection)
-        ###
-        t = g.V().hasLabel("project").name.iterate()
-        assert 0 == len(t.side_effects.keys())
-        with pytest.raises(Exception):
-            m = t.side_effects["m"]
-        ###
-        t = g.V().out("created").groupCount("m").by("name")
-        results = t.toSet()
-        assert 2 == len(results)
-        assert Vertex(3) in results
-        assert Vertex(5) in results
-        assert 1 == len(t.side_effects.keys())
-        assert "m" in t.side_effects.keys()
-        m = t.side_effects["m"]
-        assert isinstance(m, dict)
-        assert 2 == len(m)
-        assert 3 == m["lop"]
-        assert 1 == m["ripple"]
-
-        # check status attributes
-        assert "host" in t.side_effects.status_attributes
-
-        ##
-        t = g.V().out("created").groupCount("m").by("name").name.aggregate("n")
-        results = t.toSet()
-        assert 2 == len(results)
-        assert "lop" in results
-        assert "ripple" in results
-        assert 2 == len(t.side_effects.keys())
-        assert "m" in t.side_effects.keys()
-        assert "n" in t.side_effects.keys()
-        n = t.side_effects.get("n")
-        assert isinstance(n, dict)
-        assert 2 == len(n)
-        assert "lop" in n.keys()
-        assert "ripple" in n.keys()
-        assert 3 == n["lop"]
-        assert 1 == n["ripple"]
-
-        t = g.withSideEffect('m', 32).V().map(lambda: "x: x.sideEffects('m')")
-        results = t.toSet()
-        assert 1 == len(results)
-        assert 32 == list(results)[0]
-        assert 32 == t.side_effects['m']
-        assert 1 == len(t.side_effects.keys())
-        with pytest.raises(Exception):
-            x = t.side_effects["x"]
-
-        a = g.V().has("name", "marko").next()
-        b = g.V().has("name", "peter").next()
-        edge = g.withSideEffect("b", b).V(a).addE("knows").to("b").next()
-        assert "knows" == edge.label
-        assert a == edge.outV
-        assert b == edge.inV
-        g.V().has("name", "marko").outE("knows").where(__.inV().has("name", "peter")).drop().iterate()
-        ##
-        edge = g.withSideEffect("a", a).withSideEffect("b", b).V().limit(1).addE("knows").from_("a").to("b").next()
-        assert "knows" == edge.label
-        assert a == edge.outV
-        assert b == edge.inV
-        g.V().has("name", "marko").outE("knows").where(__.inV().has("name", "peter")).drop().iterate()
-
-    def test_side_effect_close(self, remote_connection):
-        g = traversal().withRemote(remote_connection)
-        t = g.V().aggregate('a').aggregate('b')
-        t.toList()
-
-        # The 'a' key should return some side effects
-        results = t.side_effects.get('a')
-        assert results
-
-        # Close result is None
-        results = t.side_effects.close()
-        assert not results
-
-        # Shouldn't get any new info from server
-        # 'b' isn't in local cache
-        results = t.side_effects.get('b')
-        assert not results
-
-        # But 'a' should still be cached locally
-        results = t.side_effects.get('a')
-        assert results
-
-        # 'a' should have been added to local keys cache, but not 'b'
-        results = t.side_effects.keys()
-        assert len(results) == 1
-        a, = results
-        assert a == 'a'
-
-        # Try to get 'b' directly from server, should throw error
-        with pytest.raises(Exception):
-            t.side_effects.value_lambda('b')
-
-    def test_promise(self, remote_connection):
-        g = traversal().withRemote(remote_connection)
-        future = g.V().aggregate('a').promise()
-        t = future.result()
-        assert len(t.toList()) == 6
-        a, = t.side_effects.keys()
-        assert a == 'a'
-        results = t.side_effects.get('a')
-        assert results
-        results = t.side_effects.close()
-        assert not results
-
-    def test_clone(self, remote_connection):
-        g = traversal().withRemote(remote_connection)
-        t = g.V().count()
-        assert 6 == t.next()
-        assert 6 == t.clone().next()
-        assert 6 == t.clone().next()
-
diff --git a/gremlin-python/src/main/jython/tests/process/test_traversal.py b/gremlin-python/src/main/jython/tests/process/test_traversal.py
deleted file mode 100644
index 5b9b619..0000000
--- a/gremlin-python/src/main/jython/tests/process/test_traversal.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-from gremlin_python.structure.graph import Graph
-from gremlin_python.process.anonymous_traversal import traversal
-from gremlin_python.process.traversal import P
-from gremlin_python.process.traversal import Binding, Bindings
-from gremlin_python.process.graph_traversal import __
-
-
-class TestTraversal(object):
-    def test_bytecode(self):
-        g = traversal().withGraph(Graph())
-        bytecode = g.V().out("created").bytecode
-        assert 0 == len(bytecode.bindings.keys())
-        assert 0 == len(bytecode.source_instructions)
-        assert 2 == len(bytecode.step_instructions)
-        assert "V" == bytecode.step_instructions[0][0]
-        assert "out" == bytecode.step_instructions[1][0]
-        assert "created" == bytecode.step_instructions[1][1]
-        assert 1 == len(bytecode.step_instructions[0])
-        assert 2 == len(bytecode.step_instructions[1])
-        ##
-        bytecode = g.withSack(1).E().groupCount().by("weight").bytecode
-        assert 0 == len(bytecode.bindings.keys())
-        assert 1 == len(bytecode.source_instructions)
-        assert "withSack" == bytecode.source_instructions[0][0]
-        assert 1 == bytecode.source_instructions[0][1]
-        assert 3 == len(bytecode.step_instructions)
-        assert "E" == bytecode.step_instructions[0][0]
-        assert "groupCount" == bytecode.step_instructions[1][0]
-        assert "by" == bytecode.step_instructions[2][0]
-        assert "weight" == bytecode.step_instructions[2][1]
-        assert 1 == len(bytecode.step_instructions[0])
-        assert 1 == len(bytecode.step_instructions[1])
-        assert 2 == len(bytecode.step_instructions[2])
-        ##
-        bytecode = g.V(Bindings.of('a', [1,2,3])) \
-            .out(Bindings.of('b','created')) \
-            .where(__.in_(Bindings.of('c','created'), Bindings.of('d','knows')) \
-            .count().is_(Bindings.of('e',P.gt(2)))).bytecode
-        assert 5 == len(bytecode.bindings.keys())
-        assert [1,2,3] == bytecode.bindings['a']
-        assert 'created' == bytecode.bindings['b']
-        assert 'created' == bytecode.bindings['c']
-        assert 'knows' == bytecode.bindings['d']
-        assert P.gt(2) == bytecode.bindings['e']
-        assert Binding('b','created') == bytecode.step_instructions[1][1]
-        assert 'binding[b=created]' == str(bytecode.step_instructions[1][1])
-        assert isinstance(hash(bytecode.step_instructions[1][1]),int)
-
-    def test_P(self):
-        # verify that the order of operations is respected
-        assert "and(eq(a),lt(b))" == str(P.eq("a").and_(P.lt("b")))
-        assert "and(or(lt(b),gt(c)),neq(d))" == str(P.lt("b").or_(P.gt("c")).and_(P.neq("d")))
-        assert "and(or(lt(b),gt(c)),or(neq(d),gte(e)))" == str(
-            P.lt("b").or_(P.gt("c")).and_(P.neq("d").or_(P.gte("e"))))
-
-    def test_anonymous_traversal(self):
-        bytecode = __.__(1).bytecode
-        assert 0 == len(bytecode.bindings.keys())
-        assert 0 == len(bytecode.source_instructions)
-        assert 1 == len(bytecode.step_instructions)
-        assert "inject" == bytecode.step_instructions[0][0]
-        assert 1 == bytecode.step_instructions[0][1]
-        ##
-        bytecode = __.start().bytecode
-        assert 0 == len(bytecode.bindings.keys())
-        assert 0 == len(bytecode.source_instructions)
-        assert 0 == len(bytecode.step_instructions)
-
-    def test_clone_traversal(self):
-        g = traversal().withGraph(Graph())
-        original = g.V().out("created")
-        clone = original.clone().out("knows")
-        cloneClone = clone.clone().out("created")
-
-        assert 2 == len(original.bytecode.step_instructions)
-        assert 3 == len(clone.bytecode.step_instructions)
-        assert 4 == len(cloneClone.bytecode.step_instructions)
-
-        original.has("person", "name", "marko")
-        clone.V().out()
-
-        assert 3 == len(original.bytecode.step_instructions)
-        assert 5 == len(clone.bytecode.step_instructions)
-        assert 4 == len(cloneClone.bytecode.step_instructions)
-
-
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_functionalityio.py b/gremlin-python/src/main/jython/tests/structure/io/test_functionalityio.py
deleted file mode 100644
index 26a62a2..0000000
--- a/gremlin-python/src/main/jython/tests/structure/io/test_functionalityio.py
+++ /dev/null
@@ -1,97 +0,0 @@
-'''
-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.
-'''
-
-import datetime
-import uuid
-
-from gremlin_python.driver.serializer import GraphSONSerializersV2d0
-from gremlin_python.structure.graph import Graph
-from gremlin_python.statics import *
-
-
-def test_timestamp(remote_connection):
-    g = Graph().traversal().withRemote(remote_connection)
-    ts = timestamp(1481750076295 / 1000)
-    resp = g.addV('test_vertex').property('ts', ts)
-    resp = resp.toList()
-    vid = resp[0].id
-    try:
-        ts_prop = g.V(vid).properties('ts').toList()[0]
-        assert isinstance(ts_prop.value, timestamp)
-        assert ts_prop.value == ts
-    finally:
-        g.V(vid).drop().iterate()
-
-
-def test_datetime(remote_connection):
-    g = Graph().traversal().withRemote(remote_connection)
-    dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
-    resp = g.addV('test_vertex').property('dt', dt).toList()
-    vid = resp[0].id
-    try:
-        dt_prop = g.V(vid).properties('dt').toList()[0]
-        assert isinstance(dt_prop.value, datetime.datetime)
-        assert dt_prop.value == dt
-    finally:
-        g.V(vid).drop().iterate()
-
-
-def test_uuid(remote_connection):
-    g = Graph().traversal().withRemote(remote_connection)
-    uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
-    resp = g.addV('test_vertex').property('uuid', uid).toList()
-    vid = resp[0].id
-    try:
-        uid_prop = g.V(vid).properties('uuid').toList()[0]
-        assert isinstance(uid_prop.value, uuid.UUID)
-        assert uid_prop.value == uid
-    finally:
-        g.V(vid).drop().iterate()
-
-
-def test_odd_bits(remote_connection):
-    if not isinstance(remote_connection._client._message_serializer, GraphSONSerializersV2d0):
-        g = Graph().traversal().withRemote(remote_connection)
-        char_lower = str.__new__(SingleChar, chr(78))
-        resp = g.addV('test_vertex').property('char_lower', char_lower).toList()
-        vid = resp[0].id
-        try:
-            v = g.V(vid).values('char_lower').toList()[0]
-            assert v == char_lower
-        finally:
-            g.V(vid).drop().iterate()
-
-        if six.PY3:
-            char_upper = str.__new__(SingleChar, chr(57344))
-            resp = g.addV('test_vertex').property('char_upper', char_upper).toList()
-            vid = resp[0].id
-            try:
-                v = g.V(vid).values('char_upper').toList()[0]
-                assert v == char_upper
-            finally:
-                g.V(vid).drop().iterate()
-                
-        dur = datetime.timedelta(seconds=1000, microseconds=1000)
-        resp = g.addV('test_vertex').property('dur', dur).toList()
-        vid = resp[0].id
-        try:
-            v = g.V(vid).values('dur').toList()[0]
-            assert v == dur
-        finally:
-            g.V(vid).drop().iterate()
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py
deleted file mode 100644
index a2320bc..0000000
--- a/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py
+++ /dev/null
@@ -1,215 +0,0 @@
-"""
-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.
-"""
-
-import datetime
-import calendar
-import time
-import uuid
-import math
-from decimal import *
-
-from mock import Mock
-
-import six
-
-from gremlin_python.statics import timestamp, long, SingleByte, SingleChar, ByteBufferType
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
-from gremlin_python.structure.io.graphbinaryV1 import GraphBinaryWriter, GraphBinaryReader, DataType
-from gremlin_python.process.traversal import P, Barrier, Binding, Bytecode
-from gremlin_python.process.strategies import SubgraphStrategy
-from gremlin_python.process.graph_traversal import __
-
-
-class TestGraphBinaryReader(object):
-    graphbinary_reader = GraphBinaryReader()
-
-
-class TestGraphSONWriter(object):
-    graphbinary_writer = GraphBinaryWriter()
-    graphbinary_reader = GraphBinaryReader()
-
-    def test_int(self):
-        x = 100
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_long(self):
-        x = long(100)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_float(self):
-        x = float(100.001)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-        x = float('nan')
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert math.isnan(output)
-
-        x = float('-inf')
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert math.isinf(output) and output < 0
-
-        x = float('inf')
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert math.isinf(output) and output > 0
-
-    def test_double(self):
-        x = 100.001
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_date(self):
-        x = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_timestamp(self):
-        x = timestamp(1481750076295 / 1000)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_string(self):
-        x = "serialize this!"
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_homogeneous_list(self):
-        x = ["serialize this!", "serialize that!", "serialize that!","stop telling me what to serialize"]
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_heterogeneous_list(self):
-        x = ["serialize this!", 0, "serialize that!", "serialize that!", 1, "stop telling me what to serialize", 2]
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_homogeneous_set(self):
-        x = {"serialize this!", "serialize that!", "stop telling me what to serialize"}
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_heterogeneous_set(self):
-        x = {"serialize this!", 0, "serialize that!", 1, "stop telling me what to serialize", 2}
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_dict(self):
-        x = {"yo": "what?",
-             "go": "no!",
-             "number": 123,
-             321: "crazy with the number for a key",
-             987: ["go", "deep", {"here": "!"}]}
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-        x = {"marko": [666], "noone": ["blah"]}
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-        x = {"ripple": [], "peter": ["created"], "noone": ["blah"], "vadas": [],
-             "josh": ["created", "created"], "lop": [], "marko": [666, "created", "knows", "knows"]}
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_uuid(self):
-        x = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_edge(self):
-        x = Edge(123, Vertex(1, 'person'), "developed", Vertex(10, "software"))
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-        assert x.inV == output.inV
-        assert x.outV == output.outV
-
-    def test_path(self):
-        x = Path(["x", "y", "z"], [1, 2, 3])
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_property(self):
-        x = Property("name", "stephen", None)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_vertex(self):
-        x = Vertex(123, "person")
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_vertexproperty(self):
-        x = VertexProperty(123, "name", "stephen", None)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-        
-    def test_barrier(self):
-        x = Barrier.normSack
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_binding(self):
-        x = Binding("name", "marko")
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_bytecode(self):
-        x = Bytecode()
-        x.source_instructions.append(["withStrategies", "SubgraphStrategy"])
-        x.step_instructions.append(["V", 1, 2, 3])
-        x.step_instructions.append(["out"])
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_byte(self):
-        x = int.__new__(SingleByte, 1)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_bytebuffer(self):
-        x = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_boolean(self):
-        x = True
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-        x = False
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-    def test_char(self):
-        x = str.__new__(SingleChar, chr(76))
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-
-        if six.PY3:
-            x = str.__new__(SingleChar, chr(57344))
-            output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-            assert x == output
-
-    def test_duration(self):
-        x = datetime.timedelta(seconds=1000, microseconds=1000)
-        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
-        assert x == output
-        
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py
deleted file mode 100644
index c06d57c..0000000
--- a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py
+++ /dev/null
@@ -1,514 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-import datetime
-import calendar
-import json
-import uuid
-import math
-from decimal import *
-
-from mock import Mock
-
-from gremlin_python.statics import *
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
-from gremlin_python.structure.io.graphsonV2d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
-import gremlin_python.structure.io.graphsonV2d0
-from gremlin_python.process.traversal import P
-from gremlin_python.process.strategies import SubgraphStrategy
-from gremlin_python.process.graph_traversal import __
-
-
-class TestGraphSONReader(object):
-    graphson_reader = GraphSONReader()
-
-    def test_number_input(self):
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:Byte",
-            "@value": 1
-        }))
-        assert isinstance(x, SingleByte)
-        assert 1 == x
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Int32",
-            "@value": 31
-        }))
-        assert isinstance(x, int)
-        assert 31 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Int64",
-            "@value": 31
-        }))
-        assert isinstance(x, long)
-        assert long(31) == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Float",
-            "@value": 31.3
-        }))
-        assert isinstance(x, float)
-        assert 31.3 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": 31.2
-        }))
-        assert isinstance(x, float)
-        assert 31.2 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": "NaN"
-        }))
-        assert isinstance(x, float)
-        assert math.isnan(x)
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": "Infinity"
-        }))
-        assert isinstance(x, float)
-        assert math.isinf(x) and x > 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": "-Infinity"
-        }))
-        assert isinstance(x, float)
-        assert math.isinf(x) and x < 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": 31.2
-        }))
-        assert isinstance(x, Decimal)
-        assert Decimal(31.2) == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": 123456789987654321123456789987654321
-        }))
-        assert isinstance(x, Decimal)
-        assert Decimal('123456789987654321123456789987654321') == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": "NaN"
-        }))
-        assert isinstance(x, Decimal)
-        assert math.isnan(x)
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": "Infinity"
-        }))
-        assert isinstance(x, Decimal)
-        assert math.isinf(x) and x > 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": "-Infinity"
-        }))
-        assert isinstance(x, Decimal)
-        assert math.isinf(x) and x < 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigInteger",
-            "@value": 31
-        }))
-        assert isinstance(x, long)
-        assert 31 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigInteger",
-            "@value": 123456789987654321123456789987654321
-        }))
-        assert isinstance(x, long)
-        assert 123456789987654321123456789987654321 == x
-
-    def test_graph(self):
-        vertex = self.graphson_reader.readObject("""
-        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type":"g:Double","@value":1.0}}}]},"properties":{"name":[{"id":{"@type":"g:Int64","@value":0},"value":"marko"}],"age":[{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29}}]}}}""")
-        assert isinstance(vertex, Vertex)
-        assert "person" == vertex.label
-        assert 1 == vertex.id
-        assert isinstance(vertex.id, int)
-        assert vertex == Vertex(1)
-        ##
-        vertex = self.graphson_reader.readObject("""
-        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
-        assert isinstance(vertex, Vertex)
-        assert 45.23 == vertex.id
-        assert isinstance(vertex.id, FloatType)
-        assert "vertex" == vertex.label
-        assert vertex == Vertex(45.23)
-        ##
-        vertex_property = self.graphson_reader.readObject("""
-        {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
-        assert isinstance(vertex_property, VertexProperty)
-        assert "anId" == vertex_property.id
-        assert "aKey" == vertex_property.label
-        assert vertex_property.value
-        assert vertex_property.vertex == Vertex(9)
-        ##
-        vertex_property = self.graphson_reader.readObject("""
-        {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
-        assert isinstance(vertex_property, VertexProperty)
-        assert 1 == vertex_property.id
-        assert "name" == vertex_property.label
-        assert "marko" == vertex_property.value
-        assert vertex_property.vertex is None
-        ##
-        edge = self.graphson_reader.readObject("""
-        {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
-        # print edge
-        assert isinstance(edge, Edge)
-        assert 17 == edge.id
-        assert "knows" == edge.label
-        assert edge.inV == Vertex("x", "xLabel")
-        assert edge.outV == Vertex("y", "vertex")
-        ##
-        property = self.graphson_reader.readObject("""
-        {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
-        # print property
-        assert isinstance(property, Property)
-        assert "aKey" == property.key
-        assert 17 == property.value
-        assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
-
-    def test_path(self):
-        path = self.graphson_reader.readObject(
-            """{"@type":"g:Path","@value":{"labels":[["a"],["b","c"],[]],"objects":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}"""
-        )
-        assert isinstance(path, Path)
-        assert "path[v[1], v[3], lop]" == str(path)
-        assert Vertex(1) == path[0]
-        assert Vertex(1) == path["a"]
-        assert "lop" == path[2]
-        assert 3 == len(path)
-
-    def test_custom_mapping(self):
-
-        # extended mapping
-        class X(object):
-            pass
-
-        type_string = "test:Xtype"
-        override_string = "g:Int64"
-        serdes = Mock()
-
-        reader = GraphSONReader(deserializer_map={type_string: serdes})
-        assert type_string in reader.deserializers
-
-        # base dicts are not modified
-        assert type_string not in gremlin_python.structure.io.graphsonV2d0._deserializers
-
-        x = X()
-        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
-        serdes.objectify.assert_called_once_with(x, reader)
-        assert o is serdes.objectify()
-
-        # overridden mapping
-        type_string = "g:Int64"
-        serdes = Mock()
-        reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
-        assert gremlin_python.structure.io.graphsonV2d0._deserializers[type_string] is not reader.deserializers[type_string]
-
-        value = 3
-        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
-        serdes.objectify.assert_called_once_with(value, reader)
-        assert o is serdes.objectify()
-
-    def test_datetime(self):
-        expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
-        pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
-        ts = int(round(pts * 1000))
-        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Date", "@value": ts}))
-        assert isinstance(dt, datetime.datetime)
-        # TINKERPOP-1848
-        assert dt == expected
-
-    def test_timestamp(self):
-        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
-        assert isinstance(dt, timestamp)
-        assert float(dt) == 1481750076.295
-
-    def test_duration(self):
-        d = self.graphson_reader.readObject(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
-        assert isinstance(d, datetime.timedelta)
-        assert d == datetime.timedelta(hours=120)
-
-    def test_uuid(self):
-        prop = self.graphson_reader.readObject(
-            json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
-        assert isinstance(prop, uuid.UUID)
-        assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
-
-    def test_metrics(self):
-        prop = self.graphson_reader.readObject(
-            json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
-                {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
-                {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
-            ]}}]))
-        assert isinstance(prop, list)
-        assert prop == [{'dur': 1.468594, 'metrics': [
-                {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
-                {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
-                ]}]
-
-    def test_bytebuffer(self):
-        bb = self.graphson_reader.readObject(
-            json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
-        assert isinstance(bb, ByteBufferType)
-        assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
-
-    def test_char(self):
-        c = self.graphson_reader.readObject(json.dumps({"@type": "gx:Char", "@value": "L"}))
-        assert isinstance(c, SingleChar)
-        assert chr(76) == c
-
-
-class TestGraphSONWriter(object):
-    graphson_writer = GraphSONWriter()
-    graphson_reader = GraphSONReader()
-
-    def test_numbers(self):
-        assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.writeObject(int.__new__(SingleByte, 1)))
-        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
-        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(long(851401972585122)))
-        assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.writeObject(long(-2)))
-        assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.writeObject(long(-851401972585122)))
-        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
-        assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.writeObject(-1))
-        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(851401972585122))
-        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
-        assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(float('nan')))
-        assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(float('inf')))
-        assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(float('-inf')))
-        assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(Decimal('123456789987654321123456789987654321')))
-        assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(Decimal('nan')))
-        assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('inf')))
-        assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('-inf')))
-        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(long(123456789987654321123456789987654321)))
-        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(123456789987654321123456789987654321))
-        assert """true""" == self.graphson_writer.writeObject(True)
-
-    def test_P(self):
-        result = {'@type': 'g:P',
-                  '@value': {
-                      'predicate': 'and',
-                      'value': [{
-                          '@type': 'g:P',
-                          '@value': {
-                              'predicate': 'or',
-                              'value': [{
-                                  '@type': 'g:P',
-                                  '@value': {'predicate': 'lt', 'value': 'b'}
-                              },
-                                  {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
-                              ]
-                          }
-                      },
-                          {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
-
-        assert result == json.loads(
-            self.graphson_writer.writeObject(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
-
-        result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1},{"@type": "g:Int32", "@value": 2}]}}
-        assert result == json.loads(self.graphson_writer.writeObject(P.within([1, 2])))
-        assert result == json.loads(self.graphson_writer.writeObject(P.within(1, 2)))
-
-        result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1}]}}
-        assert result == json.loads(self.graphson_writer.writeObject(P.within([1])))
-        assert result == json.loads(self.graphson_writer.writeObject(P.within(1)))
-
-    def test_strategies(self):
-        # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the Gremlin traversal machine (yet)
-        assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
-            self.graphson_writer.writeObject(SubgraphStrategy))
-        assert {"@type": "g:SubgraphStrategy", "@value": {
-            "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
-            self.graphson_writer.writeObject(SubgraphStrategy(vertices=__.has("name", "marko"))))
-
-    def test_graph(self):
-        # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
-        assert {"@type": "g:Vertex", "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(self.graphson_writer.writeObject(Vertex(long(12), "person")))
-
-        assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
-                                              "outV": {"@type": "g:Int32", "@value": 0},
-                                              "outVLabel": "person",
-                                              "label": "knows",
-                                              "inV": {"@type": "g:Int32", "@value": 1},
-                                              "inVLabel": "dog"}} == json.loads(
-            self.graphson_writer.writeObject(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
-        assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
-                                                        "vertex": "stephen"}} == json.loads(
-            self.graphson_writer.writeObject(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
-
-        assert {"@type": "g:Property",
-                "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
-                                                                        "@value": {
-                                                                            "vertex": "vertexId",
-                                                                            "id": {"@type": "g:Int32", "@value": 1234},
-                                                                            "label": "aKey"}}}} == json.loads(
-            self.graphson_writer.writeObject(
-                Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
-
-        vertex = self.graphson_reader.readObject(self.graphson_writer.writeObject(Vertex(1, "person")))
-        assert 1 == vertex.id
-        assert "person" == vertex.label
-
-        edge = self.graphson_reader.readObject(
-            self.graphson_writer.writeObject(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
-        assert "knows" == edge.label
-        assert 3 == edge.id
-        assert 1 == edge.outV.id
-        assert 2 == edge.inV.id
-
-        vertex_property = self.graphson_reader.readObject(
-            self.graphson_writer.writeObject(VertexProperty(1, "age", 32, Vertex(1))))
-        assert 1 == vertex_property.id
-        assert "age" == vertex_property.key
-        assert 32 == vertex_property.value
-
-        property = self.graphson_reader.readObject(self.graphson_writer.writeObject(Property("age", 32.2, Edge(1,Vertex(2),"knows",Vertex(3)))))
-        assert "age" == property.key
-        assert 32.2 == property.value
-
-    def test_custom_mapping(self):
-        # extended mapping
-        class X(object):
-            pass
-
-        serdes = Mock()
-        writer = GraphSONWriter(serializer_map={X: serdes})
-        assert X in writer.serializers
-
-        # base dicts are not modified
-        assert X not in gremlin_python.structure.io.graphsonV2d0._serializers
-
-        obj = X()
-        d = writer.toDict(obj)
-        serdes.dictify.assert_called_once_with(obj, writer)
-        assert d is serdes.dictify()
-
-        # overridden mapping
-        serdes = Mock()
-        writer = GraphSONWriter(serializer_map={int: serdes})
-        assert gremlin_python.structure.io.graphsonV2d0._serializers[int] is not writer.serializers[int]
-
-        value = 3
-        d = writer.toDict(value)
-        serdes.dictify.assert_called_once_with(value, writer)
-        assert d is serdes.dictify()
-
-    def test_write_long(self):
-        mapping = self.graphson_writer.toDict(1)
-        assert mapping['@type'] == 'g:Int32'
-        assert mapping['@value'] == 1
-
-        mapping = self.graphson_writer.toDict(long(1))
-        assert mapping['@type'] == 'g:Int64'
-        assert mapping['@value'] == 1
-
-    def test_datetime(self):
-        expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
-        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
-        output = self.graphson_writer.writeObject(dt)
-        assert expected == output
-
-    def test_timestamp(self):
-        expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
-        ts = timestamp(1481750076295 / 1000.0)
-        output = self.graphson_writer.writeObject(ts)
-        assert expected == output
-
-    def test_duration(self):
-        expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
-        d = datetime.timedelta(hours=120)
-        output = self.graphson_writer.writeObject(d)
-        assert expected == output
-
-    def test_uuid(self):
-        expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
-        prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
-        output = self.graphson_writer.writeObject(prop)
-        assert expected == output
-
-    def test_bytebuffer(self):
-        expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
-        bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
-        output = self.graphson_writer.writeObject(bb)
-        assert expected == output
-
-    def test_char(self):
-        expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
-        c = str.__new__(SingleChar, chr(76))
-        output = self.graphson_writer.writeObject(c)
-        assert expected == output
-
-
-class TestFunctionalGraphSONIO(object):
-    """Functional IO tests"""
-
-    def test_timestamp(self, remote_connection_v2):
-        g = Graph().traversal().withRemote(remote_connection_v2)
-        ts = timestamp(1481750076295 / 1000)
-        resp = g.addV('test_vertex').property('ts', ts)
-        resp = resp.toList()
-        vid = resp[0].id
-        try:
-            ts_prop = g.V(vid).properties('ts').toList()[0]
-            assert isinstance(ts_prop.value, timestamp)
-            assert ts_prop.value == ts
-        except OSError:
-            assert False, "Error making request"
-        finally:
-            g.V(vid).drop().iterate()
-
-    def test_datetime(self, remote_connection_v2):
-        g = Graph().traversal().withRemote(remote_connection_v2)
-        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
-        resp = g.addV('test_vertex').property('dt', dt).toList()
-        vid = resp[0].id
-        try:
-            dt_prop = g.V(vid).properties('dt').toList()[0]
-            assert isinstance(dt_prop.value, datetime.datetime)
-            assert dt_prop.value == dt
-        except OSError:
-            assert False, "Error making request"
-        finally:
-            g.V(vid).drop().iterate()
-
-    def test_uuid(self, remote_connection_v2):
-        g = Graph().traversal().withRemote(remote_connection_v2)
-        uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
-        resp = g.addV('test_vertex').property('uuid', uid).toList()
-        vid = resp[0].id
-        try:
-            uid_prop = g.V(vid).properties('uuid').toList()[0]
-            assert isinstance(uid_prop.value, uuid.UUID)
-            assert uid_prop.value == uid
-        except OSError:
-            assert False, "Error making request"
-        finally:
-            g.V(vid).drop().iterate()
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py
deleted file mode 100644
index f3948fd..0000000
--- a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py
+++ /dev/null
@@ -1,534 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-import datetime
-import calendar
-import json
-import uuid
-import math
-from decimal import *
-
-from mock import Mock
-
-import six
-
-from gremlin_python.statics import *
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
-from gremlin_python.structure.io.graphsonV3d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
-import gremlin_python.structure.io.graphsonV3d0
-from gremlin_python.process.traversal import P
-from gremlin_python.process.strategies import SubgraphStrategy
-from gremlin_python.process.graph_traversal import __
-
-
-class TestGraphSONReader(object):
-    graphson_reader = GraphSONReader()
-
-    def test_collections(self):
-        x = self.graphson_reader.readObject(
-            json.dumps({"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
-                                                      {"@type": "g:Int32", "@value": 2},
-                                                      "3"]}))
-        assert isinstance(x, list)
-        assert x[0] == 1
-        assert x[1] == 2
-        assert x[2] == "3"
-        ##
-
-        x = self.graphson_reader.readObject(
-            json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
-                                                     {"@type": "g:Int32", "@value": 2},
-                                                     "3"]}))
-        # return a set as normal
-        assert isinstance(x, set)
-        assert x == set([1, 2, "3"])
-
-        x = self.graphson_reader.readObject(
-            json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
-                                                    {"@type": "g:Int32", "@value": 2},
-                                                    {"@type": "g:Float", "@value": 2.0},
-                                                    "3"]}))
-        # coerce to list here because Java might return numerics of different types which python won't recognize
-        # see comments of TINKERPOP-1844 for more details
-        assert isinstance(x, list)
-        assert x == list([1, 2, 2.0, "3"])
-        ##
-        x = self.graphson_reader.readObject(
-            json.dumps({"@type": "g:Map",
-                        "@value": ['a', {"@type": "g:Int32", "@value": 1}, 'b', "marko"]}))
-        assert isinstance(x, dict)
-        assert x['a'] == 1
-        assert x['b'] == "marko"
-        assert len(x) == 2
-
-        # BulkSet gets coerced to a List - both have the same behavior
-        x = self.graphson_reader.readObject(
-            json.dumps({"@type": "g:BulkSet",
-                        "@value": ["marko", {"@type": "g:Int64", "@value": 1}, "josh", {"@type": "g:Int64", "@value": 3}]}))
-        assert isinstance(x, list)
-        assert len(x) == 4
-        assert x.count("marko") == 1
-        assert x.count("josh") == 3
-
-    def test_number_input(self):
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:Byte",
-            "@value": 1
-        }))
-        assert isinstance(x, SingleByte)
-        assert 1 == x
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Int32",
-            "@value": 31
-        }))
-        assert isinstance(x, int)
-        assert 31 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Int64",
-            "@value": 31
-        }))
-        assert isinstance(x, long)
-        assert long(31) == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Float",
-            "@value": 31.3
-        }))
-        assert isinstance(x, float)
-        assert 31.3 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": 31.2
-        }))
-        assert isinstance(x, float)
-        assert 31.2 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": "NaN"
-        }))
-        assert isinstance(x, float)
-        assert math.isnan(x)
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": "Infinity"
-        }))
-        assert isinstance(x, float)
-        assert math.isinf(x) and x > 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": "-Infinity"
-        }))
-        assert isinstance(x, float)
-        assert math.isinf(x) and x < 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": 31.2
-        }))
-        assert isinstance(x, Decimal)
-        assert Decimal(31.2) == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": 123456789987654321123456789987654321
-        }))
-        assert isinstance(x, Decimal)
-        assert Decimal('123456789987654321123456789987654321') == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": "NaN"
-        }))
-        assert isinstance(x, Decimal)
-        assert math.isnan(x)
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": "Infinity"
-        }))
-        assert isinstance(x, Decimal)
-        assert math.isinf(x) and x > 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigDecimal",
-            "@value": "-Infinity"
-        }))
-        assert isinstance(x, Decimal)
-        assert math.isinf(x) and x < 0
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigInteger",
-            "@value": 31
-        }))
-        assert isinstance(x, long)
-        assert 31 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "gx:BigInteger",
-            "@value": 123456789987654321123456789987654321
-        }))
-        assert isinstance(x, long)
-        assert 123456789987654321123456789987654321 == x
-
-    def test_graph(self):
-        vertex = self.graphson_reader.readObject("""
-        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type":"g:Double","@value":1.0}}}]},"properties":{"name":[{"id":{"@type":"g:Int64","@value":0},"value":"marko"}],"age":[{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29}}]}}}""")
-        assert isinstance(vertex, Vertex)
-        assert "person" == vertex.label
-        assert 1 == vertex.id
-        assert isinstance(vertex.id, int)
-        assert vertex == Vertex(1)
-        ##
-        vertex = self.graphson_reader.readObject("""
-        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
-        assert isinstance(vertex, Vertex)
-        assert 45.23 == vertex.id
-        assert isinstance(vertex.id, FloatType)
-        assert "vertex" == vertex.label
-        assert vertex == Vertex(45.23)
-        ##
-        vertex_property = self.graphson_reader.readObject("""
-        {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
-        assert isinstance(vertex_property, VertexProperty)
-        assert "anId" == vertex_property.id
-        assert "aKey" == vertex_property.label
-        assert vertex_property.value
-        assert vertex_property.vertex == Vertex(9)
-        ##
-        vertex_property = self.graphson_reader.readObject("""
-        {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
-        assert isinstance(vertex_property, VertexProperty)
-        assert 1 == vertex_property.id
-        assert "name" == vertex_property.label
-        assert "marko" == vertex_property.value
-        assert vertex_property.vertex is None
-        ##
-        edge = self.graphson_reader.readObject("""
-        {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
-        # print edge
-        assert isinstance(edge, Edge)
-        assert 17 == edge.id
-        assert "knows" == edge.label
-        assert edge.inV == Vertex("x", "xLabel")
-        assert edge.outV == Vertex("y", "vertex")
-        ##
-        property = self.graphson_reader.readObject("""
-        {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
-        # print property
-        assert isinstance(property, Property)
-        assert "aKey" == property.key
-        assert 17 == property.value
-        assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
-
-    def test_path(self):
-        path = self.graphson_reader.readObject(
-            """{"@type":"g:Path","@value":{"labels":{"@type":"g:List","@value":[{"@type":"g:Set","@value":["a"]},{"@type":"g:Set","@value":["b","c"]},{"@type":"g:Set","@value":[]}]},"objects":{"@type":"g:List","@value":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}}"""
-        )
-        assert isinstance(path, Path)
-        assert "path[v[1], v[3], lop]" == str(path)
-        assert Vertex(1) == path[0]
-        assert Vertex(1) == path["a"]
-        assert "lop" == path[2]
-        assert 3 == len(path)
-
-    def test_custom_mapping(self):
-
-        # extended mapping
-        class X(object):
-            pass
-
-        type_string = "test:Xtype"
-        override_string = "g:Int64"
-        serdes = Mock()
-
-        reader = GraphSONReader(deserializer_map={type_string: serdes})
-        assert type_string in reader.deserializers
-
-        # base dicts are not modified
-        assert type_string not in gremlin_python.structure.io.graphsonV3d0._deserializers
-
-        x = X()
-        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
-        serdes.objectify.assert_called_once_with(x, reader)
-        assert o is serdes.objectify()
-
-        # overridden mapping
-        type_string = "g:Int64"
-        serdes = Mock()
-        reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
-        assert gremlin_python.structure.io.graphsonV3d0._deserializers[type_string] is not reader.deserializers[
-            type_string]
-
-        value = 3
-        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
-        serdes.objectify.assert_called_once_with(value, reader)
-        assert o is serdes.objectify()
-
-    def test_datetime(self):
-        expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
-        pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
-        ts = int(round(pts * 1000))
-        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Date", "@value": ts}))
-        assert isinstance(dt, datetime.datetime)
-        # TINKERPOP-1848
-        assert dt == expected
-
-    def test_timestamp(self):
-        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
-        assert isinstance(dt, timestamp)
-        assert float(dt) == 1481750076.295
-
-    def test_duration(self):
-        d = self.graphson_reader.readObject(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
-        assert isinstance(d, datetime.timedelta)
-        assert d == datetime.timedelta(hours=120)
-
-    def test_uuid(self):
-        prop = self.graphson_reader.readObject(
-            json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
-        assert isinstance(prop, uuid.UUID)
-        assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
-
-    def test_metrics(self):
-        prop = self.graphson_reader.readObject(
-            json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
-                {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
-                {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
-            ]}}]))
-        assert isinstance(prop, list)
-        assert prop == [{'dur': 1.468594, 'metrics': [
-                {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
-                {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
-                ]}]
-
-    def test_bytebuffer(self):
-        bb = self.graphson_reader.readObject(
-            json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
-        assert isinstance(bb, ByteBufferType)
-        assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
-
-    def test_char(self):
-        c = self.graphson_reader.readObject(json.dumps({"@type": "gx:Char", "@value": "L"}))
-        assert isinstance(c, SingleChar)
-        assert chr(76) == c
-
-
-class TestGraphSONWriter(object):
-    graphson_writer = GraphSONWriter()
-    graphson_reader = GraphSONReader()
-
-    def test_collections(self):
-        assert {"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
-                                              {"@type": "g:Int32", "@value": 2},
-                                              {"@type": "g:Int32", "@value": 3}]} == json.loads(
-            self.graphson_writer.writeObject([1, 2, 3]))
-        assert {"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
-                                             {"@type": "g:Int32", "@value": 2},
-                                             {"@type": "g:Int32", "@value": 3}]} == json.loads(
-            self.graphson_writer.writeObject(set([1, 2, 3, 3])))
-        assert {"@type": "g:Map",
-                "@value": ['a', {"@type": "g:Int32", "@value": 1}]} == json.loads(
-            self.graphson_writer.writeObject({'a': 1}))
-
-    def test_numbers(self):
-        assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.writeObject(int.__new__(SingleByte, 1)))
-        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
-        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(long(851401972585122)))
-        assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.writeObject(long(-2)))
-        assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.writeObject(long(-851401972585122)))
-        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
-        assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.writeObject(-1))
-        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(851401972585122))
-        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
-        assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(float('nan')))
-        assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(float('inf')))
-        assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(float('-inf')))
-        assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(Decimal('123456789987654321123456789987654321')))
-        assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(Decimal('nan')))
-        assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('inf')))
-        assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('-inf')))
-        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(long(123456789987654321123456789987654321)))
-        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(123456789987654321123456789987654321))
-        assert """true""" == self.graphson_writer.writeObject(True)
-
-    def test_P(self):
-        result = {'@type': 'g:P',
-                  '@value': {
-                      'predicate': 'and',
-                      'value': [{
-                          '@type': 'g:P',
-                          '@value': {
-                              'predicate': 'or',
-                              'value': [{
-                                  '@type': 'g:P',
-                                  '@value': {'predicate': 'lt', 'value': 'b'}
-                              },
-                                  {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
-                              ]
-                          }
-                      },
-                          {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
-
-        assert result == json.loads(
-            self.graphson_writer.writeObject(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
-
-        result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
-            {"@type": "g:Int32", "@value": 1}, {"@type": "g:Int32", "@value": 2}]}}}
-        assert result == json.loads(self.graphson_writer.writeObject(P.within([1, 2])))
-        assert result == json.loads(self.graphson_writer.writeObject(P.within(1, 2)))
-
-        result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
-            {"@type": "g:Int32", "@value": 1}]}}}
-        assert result == json.loads(self.graphson_writer.writeObject(P.within([1])))
-        assert result == json.loads(self.graphson_writer.writeObject(P.within(1)))
-
-    def test_strategies(self):
-        # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the 
-        # Gremlin traversal machine (yet)
-        assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
-            self.graphson_writer.writeObject(SubgraphStrategy))
-        assert {"@type": "g:SubgraphStrategy", "@value": {
-            "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
-            self.graphson_writer.writeObject(SubgraphStrategy(vertices=__.has("name", "marko"))))
-
-    def test_graph(self):
-        # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
-        assert {"@type": "g:Vertex",
-                "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(
-            self.graphson_writer.writeObject(Vertex(long(12), "person")))
-
-        assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
-                                              "outV": {"@type": "g:Int32", "@value": 0},
-                                              "outVLabel": "person",
-                                              "label": "knows",
-                                              "inV": {"@type": "g:Int32", "@value": 1},
-                                              "inVLabel": "dog"}} == json.loads(
-            self.graphson_writer.writeObject(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
-        assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
-                                                        "vertex": "stephen"}} == json.loads(
-            self.graphson_writer.writeObject(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
-
-        assert {"@type": "g:Property",
-                "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
-                                                                        "@value": {
-                                                                            "vertex": "vertexId",
-                                                                            "id": {"@type": "g:Int32", "@value": 1234},
-                                                                            "label": "aKey"}}}} == json.loads(
-            self.graphson_writer.writeObject(
-                Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
-
-        vertex = self.graphson_reader.readObject(self.graphson_writer.writeObject(Vertex(1, "person")))
-        assert 1 == vertex.id
-        assert "person" == vertex.label
-
-        edge = self.graphson_reader.readObject(
-            self.graphson_writer.writeObject(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
-        assert "knows" == edge.label
-        assert 3 == edge.id
-        assert 1 == edge.outV.id
-        assert 2 == edge.inV.id
-
-        vertex_property = self.graphson_reader.readObject(
-            self.graphson_writer.writeObject(VertexProperty(1, "age", 32, Vertex(1))))
-        assert 1 == vertex_property.id
-        assert "age" == vertex_property.key
-        assert 32 == vertex_property.value
-
-        property = self.graphson_reader.readObject(self.graphson_writer.writeObject(Property("age", 32.2, Edge(1,Vertex(2),"knows",Vertex(3)))))
-        assert "age" == property.key
-        assert 32.2 == property.value
-
-    def test_custom_mapping(self):
-        # extended mapping
-        class X(object):
-            pass
-
-        serdes = Mock()
-        writer = GraphSONWriter(serializer_map={X: serdes})
-        assert X in writer.serializers
-
-        # base dicts are not modified
-        assert X not in gremlin_python.structure.io.graphsonV3d0._serializers
-
-        obj = X()
-        d = writer.toDict(obj)
-        serdes.dictify.assert_called_once_with(obj, writer)
-        assert d is serdes.dictify()
-
-        # overridden mapping
-        serdes = Mock()
-        writer = GraphSONWriter(serializer_map={int: serdes})
-        assert gremlin_python.structure.io.graphsonV3d0._serializers[int] is not writer.serializers[int]
-
-        value = 3
-        d = writer.toDict(value)
-        serdes.dictify.assert_called_once_with(value, writer)
-        assert d is serdes.dictify()
-
-    def test_write_long(self):
-        mapping = self.graphson_writer.toDict(1)
-        assert mapping['@type'] == 'g:Int32'
-        assert mapping['@value'] == 1
-
-        mapping = self.graphson_writer.toDict(long(1))
-        assert mapping['@type'] == 'g:Int64'
-        assert mapping['@value'] == 1
-
-    def test_datetime(self):
-        expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
-        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
-        output = self.graphson_writer.writeObject(dt)
-        assert expected == output
-
-    def test_timestamp(self):
-        expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
-        ts = timestamp(1481750076295 / 1000.0)
-        output = self.graphson_writer.writeObject(ts)
-        assert expected == output
-
-    def test_duration(self):
-        expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
-        d = datetime.timedelta(hours=120)
-        output = self.graphson_writer.writeObject(d)
-        assert expected == output
-
-    def test_uuid(self):
-        expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
-        prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
-        output = self.graphson_writer.writeObject(prop)
-        assert expected == output
-
-    def test_bytebuffer(self):
-        expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
-        bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
-        output = self.graphson_writer.writeObject(bb)
-        assert expected == output
-
-    def test_char(self):
-        expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
-        c = str.__new__(SingleChar, chr(76))
-        output = self.graphson_writer.writeObject(c)
-        assert expected == output
diff --git a/gremlin-python/src/main/jython/tests/structure/test_graph.py b/gremlin-python/src/main/jython/tests/structure/test_graph.py
deleted file mode 100644
index 67849f6..0000000
--- a/gremlin-python/src/main/jython/tests/structure/test_graph.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-import six
-
-from gremlin_python.statics import long
-from gremlin_python.structure.graph import Edge
-from gremlin_python.structure.graph import Property
-from gremlin_python.structure.graph import Vertex
-from gremlin_python.structure.graph import VertexProperty
-from gremlin_python.structure.graph import Path
-
-
-class TestGraph(object):
-    def test_graph_objects(self):
-        vertex = Vertex(1)
-        assert "v[1]" == str(vertex)
-        assert "vertex" == vertex.label
-        assert "person" == Vertex(1, "person").label
-        assert vertex == Vertex(1)
-        #
-        edge = Edge(2, Vertex(1), "said", Vertex("hello", "phrase"))
-        assert "e[2][1-said->hello]" == str(edge)
-        assert Vertex(1) == edge.outV
-        assert Vertex("hello") == edge.inV
-        assert "said" == edge.label
-        assert "phrase" == edge.inV.label
-        assert edge.inV != edge.outV
-        #
-        vertex_property = VertexProperty(long(24), "name", "marko", Vertex(1))
-        assert "vp[name->marko]" == str(vertex_property)
-        assert "name" == vertex_property.label
-        assert "name" == vertex_property.key
-        assert "marko" == vertex_property.value
-        assert long(24) == vertex_property.id
-        assert Vertex(1) == vertex_property.vertex
-        assert isinstance(vertex_property.id, long)
-        assert vertex_property == VertexProperty(long(24), "name", "marko", Vertex(1))
-        #
-        property = Property("age", 29, Vertex(1))
-        assert "p[age->29]" == str(property)
-        assert "age" == property.key
-        assert 29 == property.value
-        assert Vertex(1) == property.element
-        assert isinstance(property.value, int)
-        assert property == Property("age", 29, Vertex(1))
-        if not six.PY3:
-            assert property != Property("age", long(29), Vertex(1))
-        #
-        for i in [vertex, edge, vertex_property, property]:
-            for j in [vertex, edge, vertex_property, property]:
-                if type(i) != type(j):
-                    assert i != j
-                else:
-                    assert i == j
-                    assert i.__hash__() == hash(i)
-
-    def test_path(self):
-        path = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
-        assert "path[1, v[1], hello]" == str(path)
-        assert 1 == path["a"]
-        assert Vertex(1) == path["c"]
-        assert [1, Vertex(1)] == path["b"]
-        assert path[0] == 1
-        assert path[1] == Vertex(1)
-        assert path[2] == "hello"
-        assert 3 == len(path)
-        assert "hello" in path
-        assert "goodbye" not in path
-        assert Vertex(1) in path
-        assert Vertex(123) not in path
-        #
-        try:
-            temp = path[3]
-            raise Exception("Accessing beyond the list index should throw an index error")
-        except IndexError:
-            pass
-        #
-        try:
-            temp = path["zz"]
-            raise Exception("Accessing nothing should throw a key error")
-        except KeyError:
-            pass
-        #
-        try:
-            temp = path[1:2]
-            raise Exception("Accessing using slices should throw a type error")
-        except TypeError:
-            pass
-        #
-        assert path == path
-        assert hash(path) == hash(path)
-        path2 = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
-        assert path == path2
-        assert hash(path) == hash(path2)
-        assert path != Path([set(["a"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
-        assert path != Path([set(["a", "b"]), set(["c", "b"]), set([])], [3, Vertex(1), "hello"])
diff --git a/gremlin-python/src/main/jython/LICENSE b/gremlin-python/src/main/python/LICENSE
similarity index 100%
rename from gremlin-python/src/main/jython/LICENSE
rename to gremlin-python/src/main/python/LICENSE
diff --git a/gremlin-python/src/main/jython/MANIFEST.in b/gremlin-python/src/main/python/MANIFEST.in
similarity index 100%
rename from gremlin-python/src/main/jython/MANIFEST.in
rename to gremlin-python/src/main/python/MANIFEST.in
diff --git a/gremlin-python/src/main/jython/NOTICE b/gremlin-python/src/main/python/NOTICE
similarity index 100%
rename from gremlin-python/src/main/jython/NOTICE
rename to gremlin-python/src/main/python/NOTICE
diff --git a/gremlin-python/src/main/jython/README.rst b/gremlin-python/src/main/python/README.rst
similarity index 100%
rename from gremlin-python/src/main/jython/README.rst
rename to gremlin-python/src/main/python/README.rst
diff --git a/gremlin-python/src/main/jython/example.py b/gremlin-python/src/main/python/example.py
similarity index 100%
rename from gremlin-python/src/main/jython/example.py
rename to gremlin-python/src/main/python/example.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/__init__.py b/gremlin-python/src/main/python/gremlin_python/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/__init__.py
rename to gremlin-python/src/main/python/gremlin_python/__init__.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/__init__.py b/gremlin-python/src/main/python/gremlin_python/driver/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/__init__.py
rename to gremlin-python/src/main/python/gremlin_python/driver/__init__.py
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/client.py b/gremlin-python/src/main/python/gremlin_python/driver/client.py
new file mode 100644
index 0000000..ff8dddb
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/driver/client.py
@@ -0,0 +1,147 @@
+#
+# 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.
+#
+from concurrent.futures import ThreadPoolExecutor
+
+from six.moves import queue
+
+from gremlin_python.driver import connection, protocol, request, serializer
+from gremlin_python.process import traversal
+
+# This is until concurrent.futures backport 3.1.0 release
+try:
+    from multiprocessing import cpu_count
+except ImportError:
+    # some platforms don't have multiprocessing
+    def cpu_count():
+        return None
+
+__author__ = 'David M. Brown (davebshow@gmail.com)'
+
+
+class Client:
+
+    def __init__(self, url, traversal_source, protocol_factory=None,
+                 transport_factory=None, pool_size=None, max_workers=None,
+                 message_serializer=None, username="", password="",
+                 kerberized_service="", headers=None, session=""):
+        self._url = url
+        self._headers = headers
+        self._traversal_source = traversal_source
+        if message_serializer is None:
+            message_serializer = serializer.GraphSONSerializersV3d0()
+        self._message_serializer = message_serializer
+        self._username = username
+        self._password = password
+        self._session = session
+        self._sessionEnabled = (session != "")
+        if transport_factory is None:
+            try:
+                from gremlin_python.driver.tornado.transport import (
+                    TornadoTransport)
+            except ImportError:
+                raise Exception("Please install Tornado or pass"
+                                "custom transport factory")
+            else:
+                transport_factory = lambda: TornadoTransport()
+        self._transport_factory = transport_factory
+        if protocol_factory is None:
+            protocol_factory = lambda: protocol.GremlinServerWSProtocol(
+                self._message_serializer,
+                username=self._username,
+                password=self._password,
+                kerberized_service=kerberized_service)
+        self._protocol_factory = protocol_factory
+        if self._sessionEnabled:
+            if pool_size is None:
+                pool_size = 1
+            elif pool_size != 1:
+                raise Exception("PoolSize must be 1 on session mode!")
+        if pool_size is None:
+            pool_size = 4
+        self._pool_size = pool_size
+        # This is until concurrent.futures backport 3.1.0 release
+        if max_workers is None:
+            # If your application is overlapping Gremlin I/O on multiple threads
+            # consider passing kwarg max_workers = (cpu_count() or 1) * 5
+            max_workers = pool_size
+        self._executor = ThreadPoolExecutor(max_workers=max_workers)
+        # Threadsafe queue
+        self._pool = queue.Queue()
+        self._fill_pool()
+
+    @property
+    def available_pool_size(self):
+        return self._pool.qsize()
+
+    @property
+    def executor(self):
+        return self._executor
+
+    @property
+    def traversal_source(self):
+        return self._traversal_source
+
+    def _fill_pool(self):
+        for i in range(self._pool_size):
+            conn = self._get_connection()
+            self._pool.put_nowait(conn)
+
+    def close(self):
+        if self._sessionEnabled:
+            self._close_session()
+        while not self._pool.empty():
+            conn = self._pool.get(True)
+            conn.close()
+        self._executor.shutdown()
+
+    def _close_session(self):
+        message = request.RequestMessage(
+            processor='session', op='close',
+            args={'session': self._session})
+        conn = self._pool.get(True)
+        return conn.write(message).result()
+
+    def _get_connection(self):
+        protocol = self._protocol_factory()
+        return connection.Connection(
+            self._url, self._traversal_source, protocol,
+            self._transport_factory, self._executor, self._pool,
+            headers=self._headers)
+
+    def submit(self, message, bindings=None):
+        return self.submitAsync(message, bindings=bindings).result()
+
+    def submitAsync(self, message, bindings=None):
+        if isinstance(message, traversal.Bytecode):
+            message = request.RequestMessage(
+                processor='traversal', op='bytecode',
+                args={'gremlin': message,
+                      'aliases': {'g': self._traversal_source}})
+        elif isinstance(message, str):
+            message = request.RequestMessage(
+                processor='', op='eval',
+                args={'gremlin': message,
+                      'aliases': {'g': self._traversal_source}})
+            if bindings:
+                message.args.update({'bindings': bindings})
+            if self._sessionEnabled:
+                message = message._replace(processor='session')
+                message.args.update({'session': self._session})
+        conn = self._pool.get(True)
+        return conn.write(message)
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/connection.py b/gremlin-python/src/main/python/gremlin_python/driver/connection.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/connection.py
rename to gremlin-python/src/main/python/gremlin_python/driver/connection.py
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
new file mode 100644
index 0000000..2b617b3
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
@@ -0,0 +1,73 @@
+#
+# 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.
+#
+from concurrent.futures import Future
+
+from gremlin_python.driver import client, serializer
+from gremlin_python.driver.remote_connection import (
+    RemoteConnection, RemoteTraversal)
+
+__author__ = 'David M. Brown (davebshow@gmail.com)'
+
+
+class DriverRemoteConnection(RemoteConnection):
+
+    def __init__(self, url, traversal_source, protocol_factory=None,
+                 transport_factory=None, pool_size=None, max_workers=None,
+                 username="", password="", kerberized_service='',
+                 message_serializer=None, graphson_reader=None,
+                 graphson_writer=None, headers=None):
+        if message_serializer is None:
+            message_serializer = serializer.GraphSONMessageSerializer(
+                reader=graphson_reader,
+                writer=graphson_writer)
+        self._client = client.Client(url, traversal_source,
+                                     protocol_factory=protocol_factory,
+                                     transport_factory=transport_factory,
+                                     pool_size=pool_size,
+                                     max_workers=max_workers,
+                                     message_serializer=message_serializer,
+                                     username=username,
+                                     password=password,
+                                     kerberized_service=kerberized_service,
+                                     headers=headers)
+        self._url = self._client._url
+        self._traversal_source = self._client._traversal_source
+
+    def close(self):
+        self._client.close()
+
+    def submit(self, bytecode):
+        result_set = self._client.submit(bytecode)
+        results = result_set.all().result()
+        return RemoteTraversal(iter(results))
+
+    def submitAsync(self, bytecode):
+        future = Future()
+        future_result_set = self._client.submitAsync(bytecode)
+
+        def cb(f):
+            try:
+                result_set = f.result()
+                results = result_set.all().result()
+                future.set_result(RemoteTraversal(iter(results)))
+            except Exception as e:
+                future.set_exception(e)
+
+        future_result_set.add_done_callback(cb)
+        return future
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/protocol.py b/gremlin-python/src/main/python/gremlin_python/driver/protocol.py
new file mode 100644
index 0000000..74773b8
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/driver/protocol.py
@@ -0,0 +1,185 @@
+#
+# 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.
+#
+import abc
+import base64
+import struct
+
+# import kerberos    Optional dependency imported in relevant codeblock
+import six
+
+try:
+    import ujson as json
+except ImportError:
+    import json
+
+from gremlin_python.driver import request
+from gremlin_python.driver.resultset import ResultSet
+
+__author__ = 'David M. Brown (davebshow@gmail.com)'
+
+
+class GremlinServerError(Exception):
+    def __init__(self, status):
+        super(GremlinServerError, self).__init__('{0}: {1}'.format(status['code'], status['message']))
+        self._status_attributes = status['attributes']
+        self.status_code = status['code']
+
+    @property
+    def status_attributes(self):
+        return self._status_attributes
+
+
+class ConfigurationError(Exception):
+    pass
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AbstractBaseProtocol:
+
+    @abc.abstractmethod
+    def connection_made(self, transport):
+        self._transport = transport
+
+    @abc.abstractmethod
+    def data_received(self, message, results_dict):
+        pass
+
+    @abc.abstractmethod
+    def write(self, request_id, request_message):
+        pass
+
+
+class GremlinServerWSProtocol(AbstractBaseProtocol):
+
+    MAX_CONTENT_LENGTH = 65536
+    QOP_AUTH_BIT = 1
+    _kerberos_context = None
+
+    def __init__(self, message_serializer, username='', password='', kerberized_service=''):
+        self._message_serializer = message_serializer
+        self._username = username
+        self._password = password
+        self._kerberized_service = kerberized_service
+
+    def connection_made(self, transport):
+        super(GremlinServerWSProtocol, self).connection_made(transport)
+
+    def write(self, request_id, request_message):
+        message = self._message_serializer.serialize_message(
+            request_id, request_message)
+        self._transport.write(message)
+
+    def data_received(self, message, results_dict):
+        # if Gremlin Server cuts off then we get a None for the message
+        if message is None:
+            raise GremlinServerError({'code': 500,
+                                      'message': 'Server disconnected - please try to reconnect', 'attributes': {}})
+
+        message = self._message_serializer.deserialize_message(message)
+        request_id = message['requestId']
+        result_set = results_dict[request_id] if request_id in results_dict else ResultSet(None, None)
+        status_code = message['status']['code']
+        aggregate_to = message['result']['meta'].get('aggregateTo', 'list')
+        data = message['result']['data']
+        result_set.aggregate_to = aggregate_to
+        if status_code == 407:
+            if self._username and self._password:
+                auth_bytes = b''.join([b'\x00', self._username.encode('utf-8'),
+                                       b'\x00', self._password.encode('utf-8')])
+                auth = base64.b64encode(auth_bytes)
+                request_message = request.RequestMessage(
+                    'traversal', 'authentication', {'sasl': auth.decode()})
+            elif self._kerberized_service:
+                request_message = self._kerberos_received(message)
+            else:
+                raise ConfigurationError(
+                    'Gremlin server requires authentication credentials in DriverRemoteConnection.'
+                    'For basic authentication provide username and password. '
+                    'For kerberos authentication provide the kerberized_service parameter.')
+            self.write(request_id, request_message)
+            data = self._transport.read()
+            # Allow for auth handshake with multiple steps
+            return self.data_received(data, results_dict)
+        elif status_code == 204:
+            result_set.stream.put_nowait([])
+            del results_dict[request_id]
+            return status_code
+        elif status_code in [200, 206]:
+            result_set.stream.put_nowait(data)
+            if status_code == 200:
+                result_set.status_attributes = message['status']['attributes']
+                del results_dict[request_id]
+            return status_code
+        else:
+            del results_dict[request_id]
+            raise GremlinServerError(message['status'])
+
+    def _kerberos_received(self, message):
+        # Inspired by: https://github.com/thobbs/pure-sasl/blob/0.6.2/puresasl/mechanisms.py
+        #              https://github.com/thobbs/pure-sasl/blob/0.6.2/LICENSE
+        try:
+            import kerberos
+        except ImportError:
+            raise ImportError('Please install gremlinpython[kerberos].')
+
+        # First pass: get service granting ticket and return it to gremlin-server
+        if not self._kerberos_context:
+            try:
+                _, kerberos_context = kerberos.authGSSClientInit(
+                    self._kerberized_service, gssflags=kerberos.GSS_C_MUTUAL_FLAG)
+                kerberos.authGSSClientStep(kerberos_context, '')
+                auth = kerberos.authGSSClientResponse(kerberos_context)
+                self._kerberos_context = kerberos_context
+            except kerberos.KrbError as e:
+                raise ConfigurationError(
+                    'Kerberos authentication requires a valid service name in DriverRemoteConnection, '
+                    'as well as a valid tgt (export KRB5CCNAME) or keytab (export KRB5_KTNAME): ' + str(e))
+            return request.RequestMessage('', 'authentication', {'sasl': auth})
+
+        # Second pass: completion of authentication
+        sasl_response = message['status']['attributes']['sasl']
+        if not self._username:
+            result_code = kerberos.authGSSClientStep(self._kerberos_context, sasl_response)
+            if result_code == kerberos.AUTH_GSS_COMPLETE:
+                self._username = kerberos.authGSSClientUserName(self._kerberos_context)
+            return request.RequestMessage('', 'authentication', {'sasl': ''})
+
+        # Third pass: sasl quality of protection (qop) handshake
+
+        # Gremlin-server Krb5Authenticator only supports qop=QOP_AUTH; use ssl for confidentiality.
+        # Handshake content format:
+        # byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
+        # byte 1-3: the max length for any buffer sent back and forth on this connection. (big endian)
+        # the rest of the buffer: the authorization user name in UTF-8 - not null terminated.
+        kerberos.authGSSClientUnwrap(self._kerberos_context, sasl_response)
+        data = kerberos.authGSSClientResponse(self._kerberos_context)
+        plaintext_data = base64.b64decode(data)
+        assert len(plaintext_data) == 4, "Unexpected response from gremlin server sasl handshake"
+        word, = struct.unpack('!I', plaintext_data)
+        qop_bits = word >> 24
+        assert self.QOP_AUTH_BIT & qop_bits, "Unexpected sasl qop level received from gremlin server"
+
+        name_length = len(self._username)
+        fmt = '!I' + str(name_length) + 's'
+        word = self.QOP_AUTH_BIT << 24 | self.MAX_CONTENT_LENGTH
+        out = struct.pack(fmt, word, self._username.encode("utf-8"),)
+        encoded = base64.b64encode(out).decode('ascii')
+        kerberos.authGSSClientWrap(self._kerberos_context, encoded)
+        auth = kerberos.authGSSClientResponse(self._kerberos_context)
+        return request.RequestMessage('', 'authentication', {'sasl': auth})
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py
new file mode 100644
index 0000000..667354e
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py
@@ -0,0 +1,70 @@
+#
+# 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.
+#
+import abc
+import six
+
+from gremlin_python.driver import request
+from gremlin_python.process import traversal
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+
+@six.add_metaclass(abc.ABCMeta)
+class RemoteConnection(object):
+    def __init__(self, url, traversal_source):
+        self._url = url
+        self._traversal_source = traversal_source
+
+    @property
+    def url(self):
+        return self._url
+
+    @property
+    def traversal_source(self):
+        return self._traversal_source
+
+    @abc.abstractmethod
+    def submit(self, bytecode):
+        pass
+
+    def __repr__(self):
+        return "remoteconnection[" + self._url + "," + self._traversal_source + "]"
+
+
+class RemoteTraversal(traversal.Traversal):
+    def __init__(self, traversers):
+        super(RemoteTraversal, self).__init__(None, None, None)
+        self.traversers = traversers
+
+
+class RemoteStrategy(traversal.TraversalStrategy):
+    def __init__(self, remote_connection):
+        traversal.TraversalStrategy.__init__(self)
+        self.remote_connection = remote_connection
+
+    def apply(self, traversal):
+        if traversal.traversers is None:
+            remote_traversal = self.remote_connection.submit(traversal.bytecode)
+            traversal.remote_results = remote_traversal
+            traversal.traversers = remote_traversal.traversers
+
+    def apply_async(self, traversal):
+        if traversal.traversers is None:
+            traversal.remote_results = self.remote_connection.submitAsync(
+                traversal.bytecode)
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/request.py b/gremlin-python/src/main/python/gremlin_python/driver/request.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/request.py
rename to gremlin-python/src/main/python/gremlin_python/driver/request.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/resultset.py b/gremlin-python/src/main/python/gremlin_python/driver/resultset.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/resultset.py
rename to gremlin-python/src/main/python/gremlin_python/driver/resultset.py
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/serializer.py b/gremlin-python/src/main/python/gremlin_python/driver/serializer.py
new file mode 100644
index 0000000..6818dc9
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/driver/serializer.py
@@ -0,0 +1,276 @@
+#
+# 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.
+#
+try:
+    import ujson as json
+except ImportError:
+    import json
+import struct
+import uuid
+import io
+
+from gremlin_python.structure.io import graphbinaryV1
+from gremlin_python.structure.io import graphsonV2d0
+from gremlin_python.structure.io import graphsonV3d0
+
+__author__ = 'David M. Brown (davebshow@gmail.com)'
+
+
+class Processor:
+    """Base class for OpProcessor serialization system."""
+
+    def __init__(self, writer):
+        self._writer = writer
+
+    def get_op_args(self, op, args):
+        op_method = getattr(self, op, None)
+        if not op_method:
+            raise Exception("Processor does not support op: {}".format(op))
+        return op_method(args)
+
+
+class Standard(Processor):
+
+    def authentication(self, args):
+        return args
+
+    def eval(self, args):
+        return args
+
+
+class Session(Processor):
+
+    def authentication(self, args):
+        return args
+
+    def eval(self, args):
+        return args
+
+    def close(self, args):
+        return args
+
+class Traversal(Processor):
+
+    def authentication(self, args):
+        return args
+
+    def bytecode(self, args):
+        gremlin = args['gremlin']
+        args['gremlin'] = self._writer.toDict(gremlin)
+        aliases = args.get('aliases', '')
+        if not aliases:
+            aliases = {'g': 'g'}
+        args['aliases'] = aliases
+        return args
+
+
+class GraphSONMessageSerializer(object):
+    """
+    Message serializer for GraphSON. Allow users to pass custom reader,
+    writer, and version kwargs for custom serialization. Otherwise,
+    use current GraphSON version as default.
+    """
+
+    # KEEP TRACK OF CURRENT DEFAULTS
+    DEFAULT_READER_CLASS = graphsonV3d0.GraphSONReader
+    DEFAULT_WRITER_CLASS = graphsonV3d0.GraphSONWriter
+    DEFAULT_VERSION = b"application/vnd.gremlin-v3.0+json"
+
+    def __init__(self, reader=None, writer=None, version=None):
+        if not version:
+            version = self.DEFAULT_VERSION
+        self._version = version
+        if not reader:
+            reader = self.DEFAULT_READER_CLASS()
+        self._graphson_reader = reader
+        if not writer:
+            writer = self.DEFAULT_WRITER_CLASS()
+        self.standard = Standard(writer)
+        self.traversal = Traversal(writer)
+        self.session = Session(writer)
+
+    @property
+    def version(self):
+        """Read only property"""
+        return self._version
+
+    def get_processor(self, processor):
+        processor = getattr(self, processor, None)
+        if not processor:
+            raise Exception("Unknown processor")
+        return processor
+
+    def serialize_message(self, request_id, request_message):
+        processor = request_message.processor
+        op = request_message.op
+        args = request_message.args
+        if not processor:
+            processor_obj = self.get_processor('standard')
+        else:
+            processor_obj = self.get_processor(processor)
+        args = processor_obj.get_op_args(op, args)
+        message = self.build_message(request_id, processor, op, args)
+        return message
+
+    def build_message(self, request_id, processor, op, args):
+        message = {
+            'requestId': {'@type': 'g:UUID', '@value': request_id},
+            'processor': processor,
+            'op': op,
+            'args': args
+        }
+        return self.finalize_message(message, b"\x21", self.version)
+
+    def finalize_message(self, message, mime_len, mime_type):
+        message = json.dumps(message)
+        message = b''.join([mime_len, mime_type, message.encode('utf-8')])
+        return message
+
+    def deserialize_message(self, message):
+        msg = json.loads(message.decode('utf-8'))
+        return self._graphson_reader.toObject(msg)
+
+
+class GraphSONSerializersV2d0(GraphSONMessageSerializer):
+    """Message serializer for GraphSON 2.0"""
+    def __init__(self):
+        reader = graphsonV2d0.GraphSONReader()
+        writer = graphsonV2d0.GraphSONWriter()
+        version = b"application/vnd.gremlin-v2.0+json"
+        super(GraphSONSerializersV2d0, self).__init__(reader, writer, version)
+
+
+class GraphSONSerializersV3d0(GraphSONMessageSerializer):
+    """Message serializer for GraphSON 3.0"""
+    def __init__(self):
+        reader = graphsonV3d0.GraphSONReader()
+        writer = graphsonV3d0.GraphSONWriter()
+        version = b"application/vnd.gremlin-v3.0+json"
+        super(GraphSONSerializersV3d0, self).__init__(reader, writer, version)
+
+
+class GraphBinarySerializersV1(object):
+    DEFAULT_READER_CLASS = graphbinaryV1.GraphBinaryReader
+    DEFAULT_WRITER_CLASS = graphbinaryV1.GraphBinaryWriter
+    DEFAULT_VERSION = b"application/vnd.graphbinary-v1.0"
+
+    max_int64 = 0xFFFFFFFFFFFFFFFF
+    header_struct = struct.Struct('>b32sBQQ')
+    header_pack = header_struct.pack
+    int_pack = graphbinaryV1.int32_pack
+    int32_unpack = struct.Struct(">i").unpack
+
+    def __init__(self, reader=None, writer=None, version=None):
+        if not version:
+            version = self.DEFAULT_VERSION
+        self._version = version
+        if not reader:
+            reader = self.DEFAULT_READER_CLASS()
+        self._graphbinary_reader = reader
+        if not writer:
+            writer = self.DEFAULT_WRITER_CLASS()
+        self._graphbinary_writer = writer
+        self.standard = Standard(writer)
+        self.traversal = Traversal(writer)
+
+    @property
+    def version(self):
+        """Read only property"""
+        return self._version
+
+    def get_processor(self, processor):
+        processor = getattr(self, processor, None)
+        if not processor:
+            raise Exception("Unknown processor")
+        return processor
+
+    def serialize_message(self, request_id, request_message):
+        processor = request_message.processor
+        op = request_message.op
+        args = request_message.args
+        if not processor:
+            processor_obj = self.get_processor('standard')
+        else:
+            processor_obj = self.get_processor(processor)
+        args = processor_obj.get_op_args(op, args)
+        message = self.build_message(request_id, processor, op, args)
+        return message
+
+    def build_message(self, request_id, processor, op, args):
+        message = {
+            'requestId': request_id,
+            'processor': processor,
+            'op': op,
+            'args': args
+        }
+        return self.finalize_message(message, 0x20, self.version)
+
+    def finalize_message(self, message, mime_len, mime_type):
+        ba = bytearray()
+
+        request_id = uuid.UUID(message['requestId'])
+        ba.extend(self.header_pack(mime_len, mime_type, 0x81,
+                                   (request_id.int >> 64) & self.max_int64, request_id.int & self.max_int64))
+
+        op_bytes = message['op'].encode("utf-8")
+        ba.extend(self.int_pack(len(op_bytes)))
+        ba.extend(op_bytes)
+
+        processor_bytes = message['processor'].encode("utf-8")
+        ba.extend(self.int_pack(len(processor_bytes)))
+        ba.extend(processor_bytes)
+
+        args = message["args"]
+        ba.extend(self.int_pack(len(args)))
+        for k, v in args.items():
+            self._graphbinary_writer.toDict(k, ba)
+
+            # processor_obj.get_op_args in serialize_message() seems to already handle bytecode. in python 3
+            # because bytearray isn't bound to a type in graphbinary it falls through the writeObject() and
+            # just works but python 2 bytearray is bound to ByteBufferType so it writes DataType.bytebuffer
+            # rather than DataType.bytecode and the server gets confused. special casing this for now until
+            # it can be refactored
+            if k == "gremlin":
+                ba.extend(v)
+            else:
+                self._graphbinary_writer.toDict(v, ba)
+
+        return bytes(ba)
+
+    def deserialize_message(self, message):
+        b = io.BytesIO(message)
+
+        b.read(1)  # version
+
+        request_id = str(self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.uuid))
+        status_code = self.int32_unpack(b.read(4))[0]
+        status_msg = self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.string)
+        status_attrs = self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.map, nullable=False)
+        meta_attrs = self._graphbinary_reader.toObject(b, graphbinaryV1.DataType.map, nullable=False)
+        result = self._graphbinary_reader.toObject(b)
+
+        b.close()
+
+        msg = {'requestId': request_id,
+               'status': {'code': status_code,
+                          'message': status_msg,
+                          'attributes': status_attrs},
+               'result': {'meta': meta_attrs,
+                          'data': result}}
+
+        return msg
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/tornado/__init__.py b/gremlin-python/src/main/python/gremlin_python/driver/tornado/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/tornado/__init__.py
rename to gremlin-python/src/main/python/gremlin_python/driver/tornado/__init__.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/tornado/transport.py b/gremlin-python/src/main/python/gremlin_python/driver/tornado/transport.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/tornado/transport.py
rename to gremlin-python/src/main/python/gremlin_python/driver/tornado/transport.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/transport.py b/gremlin-python/src/main/python/gremlin_python/driver/transport.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/driver/transport.py
rename to gremlin-python/src/main/python/gremlin_python/driver/transport.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/__init__.py b/gremlin-python/src/main/python/gremlin_python/process/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/process/__init__.py
rename to gremlin-python/src/main/python/gremlin_python/process/__init__.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/anonymous_traversal.py b/gremlin-python/src/main/python/gremlin_python/process/anonymous_traversal.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/process/anonymous_traversal.py
rename to gremlin-python/src/main/python/gremlin_python/process/anonymous_traversal.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
rename to gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
diff --git a/gremlin-python/src/main/python/gremlin_python/process/strategies.py b/gremlin-python/src/main/python/gremlin_python/process/strategies.py
new file mode 100644
index 0000000..c2ee615
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/process/strategies.py
@@ -0,0 +1,220 @@
+#
+# 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.
+#
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+from gremlin_python.process.traversal import TraversalStrategy
+
+
+#########################
+# DECORATION STRATEGIES #
+#########################
+
+class ConnectiveStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy")
+
+
+class ElementIdStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy")
+
+
+# EventStrategy doesn't make sense outside JVM traversal machine
+
+class HaltedTraverserStrategy(TraversalStrategy):
+    def __init__(self, halted_traverser_factory=None):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy")
+        if halted_traverser_factory is not None:
+            self.configuration["haltedTraverserFactory"] = halted_traverser_factory
+
+
+class OptionsStrategy(TraversalStrategy):
+    def __init__(self, options=None):
+        TraversalStrategy.__init__(self, configuration=options, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy")
+
+
+class PartitionStrategy(TraversalStrategy):
+    def __init__(self, partition_key=None, write_partition=None, read_partitions=None, include_meta_properties=None):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy")
+        if partition_key is not None:
+            self.configuration["partitionKey"] = partition_key
+        if write_partition is not None:
+            self.configuration["writePartition"] = write_partition
+        if write_partition is not None:
+            self.configuration["readPartitions"] = read_partitions
+        if include_meta_properties is not None:
+            self.configuration["includeMetaProperties"] = include_meta_properties
+
+
+class SeedStrategy(TraversalStrategy):
+    def __init__(self, seed):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy")
+        self.configuration["seed"] = seed
+
+
+class SubgraphStrategy(TraversalStrategy):
+
+    def __init__(self, vertices=None, edges=None, vertex_properties=None):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy")
+        if vertices is not None:
+            self.configuration["vertices"] = vertices
+        if edges is not None:
+            self.configuration["edges"] = edges
+        if vertex_properties is not None:
+            self.configuration["vertexProperties"] = vertex_properties
+
+
+class VertexProgramStrategy(TraversalStrategy):
+    def __init__(self, graph_computer=None, workers=None, persist=None, result=None, vertices=None, edges=None,
+                 configuration=None):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy")
+        if graph_computer is not None:
+            self.configuration["graphComputer"] = graph_computer
+        if workers is not None:
+            self.configuration["workers"] = workers
+        if persist is not None:
+            self.configuration["persist"] = persist
+        if result is not None:
+            self.configuration["result"] = result
+        if vertices is not None:
+            self.configuration["vertices"] = vertices
+        if edges is not None:
+            self.configuration["edges"] = edges
+        if configuration is not None:
+            self.configuration.update(configuration)
+
+
+###########################
+# FINALIZATION STRATEGIES #
+###########################
+
+class MatchAlgorithmStrategy(TraversalStrategy):
+    def __init__(self, match_algorithm=None):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy")
+        if match_algorithm is not None:
+            self.configuration["matchAlgorithm"] = match_algorithm
+
+
+###########################
+# OPTIMIZATION STRATEGIES #
+###########################
+
+class AdjacentToIncidentStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy")
+
+
+class ByModulatorOptimizationStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy")
+
+
+class CountStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy")
+
+
+class FilterRankingStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy")
+
+
+class IdentityRemovalStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy")
+
+
+class IncidentToAdjacentStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy")
+
+
+class InlineFilterStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.InlineFilterStrategy")
+
+
+class LazyBarrierStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.LazyBarrierStrategy")
+
+
+class MatchPredicateStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy")
+
+
+class OrderLimitStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy")
+
+
+class PathProcessorStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy")
+
+
+class PathRetractionStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy")
+
+class RepeatUnrollStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy")
+
+
+class GraphFilterStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy")
+
+
+
+class EarlyLimitStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy")
+
+###########################
+# VERIFICATION STRATEGIES #
+###########################
+
+
+class LambdaRestrictionStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy")
+
+
+class ReadOnlyStrategy(TraversalStrategy):
+    def __init__(self):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy")
+
+
+class EdgeLabelVerificationStrategy(TraversalStrategy):
+    def __init__(self, log_warning=False, throw_exception=False):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy")
+        self.configuration["logWarning"] = log_warning
+        self.configuration["throwException"] = throw_exception
+
+
+class ReservedKeysVerificationStrategy(TraversalStrategy):
+    def __init__(self, log_warning=False, throw_exception=False, keys=["id", "label"]):
+        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy")
+        self.configuration["logWarning"] = log_warning
+        self.configuration["throwException"] = throw_exception
+        self.configuration["keys"] = keys
diff --git a/gremlin-python/src/main/python/gremlin_python/process/traversal.py b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
new file mode 100644
index 0000000..ad88812
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
@@ -0,0 +1,715 @@
+#
+# 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.
+#
+
+import copy
+from aenum import Enum
+from .. import statics
+from ..statics import long
+
+class Traversal(object):
+    def __init__(self, graph, traversal_strategies, bytecode):
+        self.graph = graph
+        self.traversal_strategies = traversal_strategies
+        self.bytecode = bytecode
+        self.traversers = None
+        self.last_traverser = None
+
+    def __repr__(self):
+        return str(self.bytecode)
+
+    def __eq__(self, other):
+        if isinstance(other, self.__class__):
+            return self.bytecode == other.bytecode
+        else:
+            return False
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if self.traversers is None:
+            self.traversal_strategies.apply_strategies(self)
+        if self.last_traverser is None:
+            self.last_traverser = next(self.traversers)
+        object = self.last_traverser.object
+        self.last_traverser.bulk = self.last_traverser.bulk - 1
+        if self.last_traverser.bulk <= 0:
+            self.last_traverser = None
+        return object
+
+    def toList(self):
+        return list(iter(self))
+
+    def toSet(self):
+        return set(iter(self))
+
+    def iterate(self):
+        self.bytecode.add_step("none")
+        while True:
+            try: self.nextTraverser()
+            except StopIteration: return self
+
+    def nextTraverser(self):
+        if self.traversers is None:
+            self.traversal_strategies.apply_strategies(self)
+        if self.last_traverser is None:
+            return next(self.traversers)
+        else:
+            temp = self.last_traverser
+            self.last_traverser = None
+            return temp
+
+    def hasNext(self):
+        if self.traversers is None:
+            self.traversal_strategies.apply_strategies(self)
+        if self.last_traverser is None:
+            try: self.last_traverser = next(self.traversers)
+            except StopIteration: return False
+        return not(self.last_traverser is None) and self.last_traverser.bulk > 0
+
+    def next(self, amount=None):
+        if amount is None:
+            return self.__next__()
+        else:
+            count = 0
+            tempList = []
+            while count < amount:
+                count = count + 1
+                try: temp = self.__next__()
+                except StopIteration: return tempList
+                tempList.append(temp)
+            return tempList
+
+    def promise(self, cb=None):
+        self.traversal_strategies.apply_async_strategies(self)
+        future_traversal = self.remote_results
+        future = type(future_traversal)()
+        def process(f):
+            try:
+                traversal = f.result()
+            except Exception as e:
+                future.set_exception(e)
+            else:
+                self.traversers = iter(traversal.traversers)
+                if cb:
+                    try:
+                        result = cb(self)
+                    except Exception as e:
+                        future.set_exception(e)
+                    else:
+                        future.set_result(result)
+                else:
+                    future.set_result(self)
+        future_traversal.add_done_callback(process)
+        return future
+
+
+Barrier = Enum('Barrier', ' normSack')
+
+statics.add_static('normSack', Barrier.normSack)
+
+Cardinality = Enum('Cardinality', ' list_ set_ single')
+
+statics.add_static('single', Cardinality.single)
+statics.add_static('list_', Cardinality.list_)
+statics.add_static('set_', Cardinality.set_)
+
+Column = Enum('Column', ' keys values')
+
+statics.add_static('keys', Column.keys)
+statics.add_static('values', Column.values)
+
+Direction = Enum('Direction', ' BOTH IN OUT')
+
+statics.add_static('OUT', Direction.OUT)
+statics.add_static('IN', Direction.IN)
+statics.add_static('BOTH', Direction.BOTH)
+
+GraphSONVersion = Enum('GraphSONVersion', ' V1_0 V2_0 V3_0')
+
+statics.add_static('V1_0', GraphSONVersion.V1_0)
+statics.add_static('V2_0', GraphSONVersion.V2_0)
+statics.add_static('V3_0', GraphSONVersion.V3_0)
+
+GryoVersion = Enum('GryoVersion', ' V1_0 V3_0')
+
+statics.add_static('V1_0', GryoVersion.V1_0)
+statics.add_static('V3_0', GryoVersion.V3_0)
+
+Order = Enum('Order', ' asc desc shuffle')
+
+statics.add_static('shuffle', Order.shuffle)
+statics.add_static('asc', Order.asc)
+statics.add_static('desc', Order.desc)
+
+Pick = Enum('Pick', ' any none')
+
+statics.add_static('any', Pick.any)
+statics.add_static('none', Pick.none)
+
+Pop = Enum('Pop', ' all_ first last mixed')
+
+statics.add_static('first', Pop.first)
+statics.add_static('last', Pop.last)
+statics.add_static('all_', Pop.all_)
+statics.add_static('mixed', Pop.mixed)
+
+Scope = Enum('Scope', ' global_ local')
+
+statics.add_static('global_', Scope.global_)
+statics.add_static('local', Scope.local)
+
+
+T = Enum('T', ' id id_ key label value')
+
+statics.add_static('id', T.id)
+statics.add_static('label', T.label)
+statics.add_static('id_', T.id_)
+statics.add_static('key', T.key)
+statics.add_static('value', T.value)
+
+
+Operator = Enum('Operator', ' addAll and_ assign div max max_ min min_ minus mult or_ sum sum_ sumLong')
+
+statics.add_static('sum_', Operator.sum_)
+statics.add_static('sum', Operator.sum_)
+statics.add_static('minus', Operator.minus)
+statics.add_static('mult', Operator.mult)
+statics.add_static('div', Operator.div)
+statics.add_static('min', Operator.min_)
+statics.add_static('min_', Operator.min_)
+statics.add_static('max_', Operator.max_)
+statics.add_static('assign', Operator.assign)
+statics.add_static('and_', Operator.and_)
+statics.add_static('or_', Operator.or_)
+statics.add_static('addAll', Operator.addAll)
+statics.add_static('sumLong', Operator.sumLong)
+
+
+class P(object):
+    def __init__(self, operator, value, other=None):
+        self.operator = operator
+        self.value = value
+        self.other = other
+
+    @staticmethod
+    def between(*args):
+        return P("between", *args)
+
+    @staticmethod
+    def eq(*args):
+        return P("eq", *args)
+
+    @staticmethod
+    def gt(*args):
+        return P("gt", *args)
+
+    @staticmethod
+    def gte(*args):
+        return P("gte", *args)
+
+    @staticmethod
+    def inside(*args):
+        return P("inside", *args)
+
+    @staticmethod
+    def lt(*args):
+        return P("lt", *args)
+
+    @staticmethod
+    def lte(*args):
+        return P("lte", *args)
+
+    @staticmethod
+    def neq(*args):
+        return P("neq", *args)
+
+    @staticmethod
+    def not_(*args):
+        return P("not", *args)
+
+    @staticmethod
+    def outside(*args):
+        return P("outside", *args)
+
+    @staticmethod
+    def test(*args):
+        return P("test", *args)
+
+    @staticmethod
+    def within(*args):
+        if len(args) == 1 and type(args[0]) == list:
+            return P("within", args[0])
+        else:
+            return P("within", list(args))
+        
+    @staticmethod
+    def without(*args):
+        if len(args) == 1 and type(args[0]) == list:
+            return P("without", args[0])
+        else:
+            return P("without", list(args))
+
+    def and_(self, arg):
+        return P("and", self, arg)
+
+    def or_(self, arg):
+        return P("or", self, arg)
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
+
+    def __repr__(self):
+        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
+
+
+def between(*args):
+    return P.between(*args)
+
+
+def eq(*args):
+    return P.eq(*args)
+
+
+def gt(*args):
+    return P.gt(*args)
+
+
+def gte(*args):
+    return P.gte(*args)
+
+
+def inside(*args):
+    return P.inside(*args)
+
+
+def lt(*args):
+    return P.lt(*args)
+
+
+def lte(*args):
+    return P.lte(*args)
+
+
+def neq(*args):
+    return P.neq(*args)
+
+
+def not_(*args):
+    return P.not_(*args)
+
+
+def outside(*args):
+    return P.outside(*args)
+
+
+def test(*args):
+    return P.test(*args)
+
+
+def within(*args):
+    return P.within(*args)
+
+
+def without(*args):
+    return P.without(*args)
+
+
+statics.add_static('between', between)
+
+statics.add_static('eq', eq)
+
+statics.add_static('gt', gt)
+
+statics.add_static('gte', gte)
+
+statics.add_static('inside', inside)
+
+statics.add_static('lt', lt)
+
+statics.add_static('lte', lte)
+
+statics.add_static('neq', neq)
+
+statics.add_static('not_', not_)
+
+statics.add_static('outside', outside)
+
+statics.add_static('test', test)
+
+statics.add_static('within', within)
+
+statics.add_static('without', without)
+
+
+class TextP(P):
+    def __init__(self, operator, value, other=None):
+        P.__init__(self, operator, value, other)
+
+    @staticmethod
+    def containing(*args):
+        return TextP("containing", *args)
+
+    @staticmethod
+    def endingWith(*args):
+        return TextP("endingWith", *args)
+
+    @staticmethod
+    def notContaining(*args):
+        return TextP("notContaining", *args)
+
+    @staticmethod
+    def notEndingWith(*args):
+        return TextP("notEndingWith", *args)
+
+    @staticmethod
+    def notStartingWith(*args):
+        return TextP("notStartingWith", *args)
+
+    @staticmethod
+    def startingWith(*args):
+        return TextP("startingWith", *args)
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
+
+    def __repr__(self):
+        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
+
+
+def containing(*args):
+    return TextP.containing(*args)
+
+
+def endingWith(*args):
+    return TextP.endingWith(*args)
+
+
+def notContaining(*args):
+    return TextP.notContaining(*args)
+
+
+def notEndingWith(*args):
+    return TextP.notEndingWith(*args)
+
+
+def notStartingWith(*args):
+    return TextP.notStartingWith(*args)
+
+
+def startingWith(*args):
+    return TextP.startingWith(*args)
+
+
+statics.add_static('containing', containing)
+
+statics.add_static('endingWith', endingWith)
+
+statics.add_static('notContaining', notContaining)
+
+statics.add_static('notEndingWith', notEndingWith)
+
+statics.add_static('notStartingWith', notStartingWith)
+
+statics.add_static('startingWith', startingWith)
+
+
+
+
+'''
+IO
+'''
+
+
+class IO(object):
+
+    graphml = "graphml"
+
+    graphson = "graphson"
+
+    gryo = "gryo"
+
+    reader = "~tinkerpop.io.reader"
+
+    registry = "~tinkerpop.io.registry"
+
+    writer = "~tinkerpop.io.writer"
+
+
+'''
+ConnectedComponent
+'''
+
+
+class ConnectedComponent(object):
+
+    component = "gremlin.connectedComponentVertexProgram.component"
+
+    edges = "~tinkerpop.connectedComponent.edges"
+
+    propertyName = "~tinkerpop.connectedComponent.propertyName"
+
+
+'''
+ShortestPath
+'''
+
+
+class ShortestPath(object):
+
+    distance = "~tinkerpop.shortestPath.distance"
+
+    edges = "~tinkerpop.shortestPath.edges"
+
+    includeEdges = "~tinkerpop.shortestPath.includeEdges"
+
+    maxDistance = "~tinkerpop.shortestPath.maxDistance"
+
+    target = "~tinkerpop.shortestPath.target"
+
+
+'''
+PageRank
+'''
+
+
+class PageRank(object):
+
+    edges = "~tinkerpop.pageRank.edges"
+
+    propertyName = "~tinkerpop.pageRank.propertyName"
+
+    times = "~tinkerpop.pageRank.times"
+
+
+'''
+PeerPressure
+'''
+
+
+class PeerPressure(object):
+
+    edges = "~tinkerpop.peerPressure.edges"
+
+    propertyName = "~tinkerpop.peerPressure.propertyName"
+
+    times = "~tinkerpop.peerPressure.times"
+
+
+'''
+TRAVERSER
+'''
+
+
+class Traverser(object):
+    def __init__(self, object, bulk=None):
+        if bulk is None:
+            bulk = long(1)
+        self.object = object
+        self.bulk = bulk
+
+    def __repr__(self):
+        return str(self.object)
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.object == other.object
+
+
+'''
+TRAVERSAL STRATEGIES
+'''
+
+
+class TraversalStrategies(object):
+    global_cache = {}
+
+    def __init__(self, traversal_strategies=None):
+        self.traversal_strategies =             traversal_strategies.traversal_strategies if traversal_strategies is not None else []
+
+    def add_strategies(self, traversal_strategies):
+        self.traversal_strategies = self.traversal_strategies + traversal_strategies
+
+    def apply_strategies(self, traversal):
+        for traversal_strategy in self.traversal_strategies:
+            traversal_strategy.apply(traversal)
+
+    def apply_async_strategies(self, traversal):
+        for traversal_strategy in self.traversal_strategies:
+            traversal_strategy.apply_async(traversal)
+
+    def __repr__(self):
+        return str(self.traversal_strategies)
+
+
+class TraversalStrategy(object):
+    def __init__(self, strategy_name=None, configuration=None, fqcn=None):
+        self.fqcn = fqcn
+        self.strategy_name = type(self).__name__ if strategy_name is None else strategy_name
+        self.configuration = {} if configuration is None else configuration
+
+    def apply(self, traversal):
+        return
+
+    def apply_async(self, traversal):
+        return
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__)
+
+    def __hash__(self):
+        return hash(self.strategy_name)
+
+    def __repr__(self):
+        return self.strategy_name
+
+
+'''
+BYTECODE
+'''
+
+
+class Bytecode(object):
+    def __init__(self, bytecode=None):
+        self.source_instructions = []
+        self.step_instructions = []
+        self.bindings = {}
+        if bytecode is not None:
+            self.source_instructions = list(bytecode.source_instructions)
+            self.step_instructions = list(bytecode.step_instructions)
+
+    def add_source(self, source_name, *args):
+        instruction = [source_name]
+        for arg in args:
+            instruction.append(self.__convertArgument(arg))
+        self.source_instructions.append(instruction)
+
+    def add_step(self, step_name, *args):
+        instruction = [step_name]
+        for arg in args:
+            instruction.append(self.__convertArgument(arg))
+        self.step_instructions.append(instruction)
+
+    def __eq__(self, other):
+        if isinstance(other, self.__class__):
+            return self.source_instructions == other.source_instructions and self.step_instructions == other.step_instructions
+        else:
+            return False
+
+    def __copy__(self):
+        bb = Bytecode()
+        bb.source_instructions = self.source_instructions
+        bb.step_instructions = self.step_instructions
+        bb.bindings = self.bindings
+        return bb
+
+    def __deepcopy__(self, memo={}):
+        bb = Bytecode()
+        bb.source_instructions = copy.deepcopy(self.source_instructions, memo)
+        bb.step_instructions = copy.deepcopy(self.step_instructions, memo)
+        bb.bindings = copy.deepcopy(self.bindings, memo)
+        return bb
+
+    def __convertArgument(self,arg):
+        if isinstance(arg, Traversal):
+            if arg.graph is not None:
+                raise TypeError("The child traversal of " + arg + " was not spawned anonymously - use the __ class rather than a TraversalSource to construct the child traversal")
+            self.bindings.update(arg.bytecode.bindings)
+            return arg.bytecode
+        elif isinstance(arg, dict):
+            newDict = {}
+            for key in arg:
+                newDict[self.__convertArgument(key)] = self.__convertArgument(arg[key])
+            return newDict
+        elif isinstance(arg, list):
+            newList = []
+            for item in arg:
+                newList.append(self.__convertArgument(item))
+            return newList
+        elif isinstance(arg, set):
+            newSet = set()
+            for item in arg:
+                newSet.add(self.__convertArgument(item))
+            return newSet
+        elif isinstance(arg, Binding):
+            self.bindings[arg.key] = arg.value
+            return Binding(arg.key, self.__convertArgument(arg.value))
+        else:
+            return arg
+
+    def __repr__(self):
+        return (str(self.source_instructions) if len(self.source_instructions) > 0 else "") + \
+               (str(self.step_instructions) if len(self.step_instructions) > 0 else "")
+
+
+'''
+BINDINGS
+'''
+
+
+class Bindings(object):
+
+    @staticmethod
+    def of(key, value):
+        if not isinstance(key, str):
+            raise TypeError("Key must be str")
+        return Binding(key, value)
+
+
+class Binding(object):
+    def __init__(self, key, value):
+        self.key = key
+        self.value = value
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value
+
+    def __hash__(self):
+        return hash(self.key) + hash(self.value)
+
+    def __repr__(self):
+        return "binding[" + self.key + "=" + str(self.value) + "]"
+
+
+'''
+WITH OPTIONS
+'''
+
+
+class WithOptions(object):
+
+    tokens = "~tinkerpop.valueMap.tokens"
+
+    none = 0
+
+    ids = 1
+
+    labels = 2
+
+    keys = 4
+
+    values = 8
+
+    all = 15
+
+    indexer = "~tinkerpop.index.indexer"
+
+    list = 0
+
+    map = 1
+
diff --git a/gremlin-python/src/main/python/gremlin_python/statics.py b/gremlin-python/src/main/python/gremlin_python/statics.py
new file mode 100644
index 0000000..567a7a3
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/statics.py
@@ -0,0 +1,101 @@
+#
+# 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.
+#
+
+from types import FunctionType
+from aenum import Enum
+
+
+class long(int):
+    pass
+
+
+FloatType = float
+IntType = int
+LongType = long
+TypeType = type
+ListType = list
+DictType = dict
+SetType = set
+ByteBufferType = bytes
+
+
+class timestamp(float):
+    """
+    In Python a timestamp is simply a float. This dummy class (similar to long), allows users to wrap a float
+    in a GLV script to make sure the value is serialized as a Gremlin timestamp.
+    """
+    pass
+
+
+class SingleByte(int):
+    """
+    Provides a way to pass a single byte via Gremlin.
+    """
+    def __new__(cls, b):
+        if -128 <= b < 128:
+            int.__new__(cls, b)
+        else:
+            raise ValueError("value must be between -128 and 127 inclusive")
+
+
+class SingleChar(str):
+    """
+    Provides a way to pass a single character via Gremlin.
+    """
+    def __new__(cls, c):
+        if len(b) == 1:
+            str.__new__(cls, c)
+        else:
+            raise ValueError("string must contain a single character")
+
+
+class GremlinType(object):
+    """
+    Provides a way to represent a "Java class" for Gremlin.
+    """
+    def __init__(self, gremlin_type):
+        self.gremlin_type = gremlin_type
+        
+
+staticMethods = {}
+staticEnums = {}
+default_lambda_language = "gremlin-groovy"
+
+
+def add_static(key, value):
+    if isinstance(value, Enum):
+        staticEnums[key] = value
+    else:
+        staticMethods[key] = value
+
+
+def load_statics(global_dict):
+    for key in staticMethods:
+        global_dict[key] = staticMethods[key]
+    for key in staticEnums:
+        global_dict[key] = staticEnums[key]
+
+
+def unload_statics(global_dict):
+    for key in staticMethods:
+        if key in global_dict:
+            del global_dict[key]
+    for key in staticEnums:
+        if key in global_dict:
+            del global_dict[key]
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/__init__.py b/gremlin-python/src/main/python/gremlin_python/structure/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/structure/__init__.py
rename to gremlin-python/src/main/python/gremlin_python/structure/__init__.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py b/gremlin-python/src/main/python/gremlin_python/structure/graph.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/structure/graph.py
rename to gremlin-python/src/main/python/gremlin_python/structure/graph.py
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/__init__.py b/gremlin-python/src/main/python/gremlin_python/structure/io/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/gremlin_python/structure/io/__init__.py
rename to gremlin-python/src/main/python/gremlin_python/structure/io/__init__.py
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
new file mode 100644
index 0000000..a5a258a
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
@@ -0,0 +1,1080 @@
+"""
+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.
+"""
+
+import six
+import datetime
+import calendar
+import uuid
+import math
+import io
+import struct
+from collections import OrderedDict
+import logging
+
+from struct import pack, unpack
+from aenum import Enum
+from datetime import timedelta
+from gremlin_python import statics
+from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, \
+                                   SingleByte, ByteBufferType, GremlinType, SingleChar
+from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Cardinality, Column, Direction, Operator, \
+                                             Order, Pick, Pop, P, Scope, TextP, Traversal, Traverser, \
+                                             TraversalStrategy, T
+from gremlin_python.process.graph_traversal import GraphTraversal
+from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path
+from gremlin_python.structure.io.util import HashableDict
+
+log = logging.getLogger(__name__)
+
+# When we fall back to a superclass's serializer, we iterate over this map.
+# We want that iteration order to be consistent, so we use an OrderedDict,
+# not a dict.
+_serializers = OrderedDict()
+_deserializers = {}
+
+
+class DataType(Enum):
+    null = 0xfe
+    int = 0x01
+    long = 0x02
+    string = 0x03
+    date = 0x04
+    timestamp = 0x05
+    clazz = 0x06
+    double = 0x07
+    float = 0x08
+    list = 0x09
+    map = 0x0a
+    set = 0x0b
+    uuid = 0x0c
+    edge = 0x0d
+    path = 0x0e
+    property = 0x0f
+    graph = 0x10                  # not supported - no graph object in python yet
+    vertex = 0x11
+    vertexproperty = 0x12
+    barrier = 0x13
+    binding = 0x14
+    bytecode = 0x15
+    cardinality = 0x16
+    column = 0x17
+    direction = 0x18
+    operator = 0x19
+    order = 0x1a
+    pick = 0x1b
+    pop = 0x1c
+    lambda_ = 0x1d
+    p = 0x1e
+    scope = 0x1f
+    t = 0x20
+    traverser = 0x21
+    bigdecimal = 0x22             # todo
+    biginteger = 0x23             # todo
+    byte = 0x24
+    bytebuffer = 0x25
+    short = 0x26                  # todo
+    boolean = 0x27
+    textp = 0x28
+    traversalstrategy = 0x29
+    bulkset = 0x2a
+    tree = 0x2b                   # not supported - no tree object in Python yet
+    metrics = 0x2c
+    traversalmetrics = 0x2d
+    char = 0x80
+    duration = 0x81
+    inetaddress = 0x82            # todo
+    instant = 0x83                # todo
+    localdate = 0x84              # todo
+    localdatetime = 0x85          # todo
+    localtime = 0x86              # todo
+    monthday = 0x87               # todo
+    offsetdatetime = 0x88         # todo
+    offsettime = 0x89             # todo
+    period = 0x8a                 # todo
+    year = 0x8b                   # todo
+    yearmonth = 0x8c              # todo
+    zonedatetime = 0x8d           # todo
+    zoneoffset = 0x8e             # todo
+    custom = 0x00                 # todo
+
+
+NULL_BYTES = [DataType.null.value, 0x01]
+
+
+def _make_packer(format_string):
+    packer = struct.Struct(format_string)
+    pack = packer.pack
+    unpack = lambda s: packer.unpack(s)[0]
+    return pack, unpack
+
+
+int64_pack, int64_unpack = _make_packer('>q')
+int32_pack, int32_unpack = _make_packer('>i')
+int8_pack, int8_unpack = _make_packer('>b')
+uint64_pack, uint64_unpack = _make_packer('>Q')
+uint8_pack, uint8_unpack = _make_packer('>B')
+float_pack, float_unpack = _make_packer('>f')
+double_pack, double_unpack = _make_packer('>d')
+
+
+class GraphBinaryTypeType(type):
+    def __new__(mcs, name, bases, dct):
+        cls = super(GraphBinaryTypeType, mcs).__new__(mcs, name, bases, dct)
+        if not name.startswith('_'):
+            if cls.python_type:
+                _serializers[cls.python_type] = cls
+            if cls.graphbinary_type:
+                _deserializers[cls.graphbinary_type] = cls
+        return cls
+
+
+class GraphBinaryWriter(object):
+    def __init__(self, serializer_map=None):
+        self.serializers = _serializers.copy()
+        if serializer_map:
+            self.serializers.update(serializer_map)
+
+    def writeObject(self, objectData):
+        return self.toDict(objectData)
+
+    def toDict(self, obj, to_extend=None):
+        if to_extend is None:
+            to_extend = bytearray()
+
+        if obj is None:
+            to_extend.extend(NULL_BYTES)
+            return
+
+        try:
+            t = type(obj)
+            return self.serializers[t].dictify(obj, self, to_extend)
+        except KeyError:
+            for key, serializer in self.serializers.items():
+                if isinstance(obj, key):
+                    return serializer.dictify(obj, self, to_extend)
+
+        if isinstance(obj, dict):
+            return dict((self.toDict(k, to_extend), self.toDict(v, to_extend)) for k, v in obj.items())
+        elif isinstance(obj, set):
+            return set([self.toDict(o, to_extend) for o in obj])
+        elif isinstance(obj, list):
+            return [self.toDict(o, to_extend) for o in obj]
+        else:
+            return obj
+
+
+class GraphBinaryReader(object):
+    def __init__(self, deserializer_map=None):
+        self.deserializers = _deserializers.copy()
+        if deserializer_map:
+            self.deserializers.update(deserializer_map)
+
+    def readObject(self, b):
+        if isinstance(b, bytearray):
+            return self.toObject(io.BytesIO(b))
+        elif isinstance(b, io.BufferedIOBase):
+            return self.toObject(b)
+
+    def toObject(self, buff, data_type=None, nullable=True):
+        if data_type is None:
+            bt = uint8_unpack(buff.read(1))
+            if bt == DataType.null.value:
+                if nullable:
+                    buff.read(1)
+                return None
+            return self.deserializers[DataType(bt)].objectify(buff, self, nullable)
+        else:
+            return self.deserializers[data_type].objectify(buff, self, nullable)
+
+
+@six.add_metaclass(GraphBinaryTypeType)
+class _GraphBinaryTypeIO(object):
+    python_type = None
+    graphbinary_type = None
+
+    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
+                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
+                 "set_": "set", "list_": "list", "all_": "all", "with_": "with",
+                 "filter_": "filter", "id_": "id", "max_": "max", "min_": "min", "sum_": "sum"}
+
+    @classmethod
+    def prefix_bytes(cls, graphbin_type, as_value=False, nullable=True, to_extend=None):
+        if to_extend is None:
+            to_extend = bytearray()
+
+        if not as_value:
+            to_extend += uint8_pack(graphbin_type.value)
+
+        if nullable:
+            to_extend += int8_pack(0)
+
+        return to_extend
+
+    @classmethod
+    def read_int(cls, buff):
+        return int32_unpack(buff.read(4))
+
+    @classmethod
+    def unmangle_keyword(cls, symbol):
+        return cls.symbolMap.get(symbol, symbol)
+
+    @classmethod
+    def is_null(cls, buff, reader, else_opt, nullable=True):
+        return None if nullable and buff.read(1)[0] == 0x01 else else_opt(buff, reader)
+
+    def dictify(self, obj, writer, to_extend, as_value=False, nullable=True):
+        raise NotImplementedError()
+
+    def objectify(self, d, reader, nullable=True):
+        raise NotImplementedError()
+        
+
+class LongIO(_GraphBinaryTypeIO):
+
+    python_type = LongType
+    graphbinary_type = DataType.long
+    byte_format_pack = int64_pack
+    byte_format_unpack = int64_unpack
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        if obj < -9223372036854775808 or obj > 9223372036854775807:
+            raise Exception("TODO: don't forget bigint")
+        else:
+            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+            to_extend.extend(cls.byte_format_pack(obj))
+            return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+            return cls.is_null(buff, reader, lambda b, r: int64_unpack(buff.read(8)), nullable)
+
+
+class IntIO(LongIO):
+
+    python_type = IntType
+    graphbinary_type = DataType.int
+    byte_format_pack = int32_pack
+    byte_format_unpack = int32_unpack
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: cls.read_int(b), nullable)
+
+
+class DateIO(_GraphBinaryTypeIO):
+
+    python_type = datetime.datetime
+    graphbinary_type = DataType.date
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        try:
+            timestamp_seconds = calendar.timegm(obj.utctimetuple())
+            pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
+        except AttributeError:
+            pts = calendar.timegm(obj.timetuple()) * 1e3
+
+        ts = int(round(pts))
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int64_pack(ts))
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader,
+                           lambda b, r: datetime.datetime.utcfromtimestamp(int64_unpack(b.read(8)) / 1000.0),
+                           nullable)
+
+
+# Based on current implementation, this class must always be declared before FloatIO.
+# Seems pretty fragile for future maintainers. Maybe look into this.
+class TimestampIO(_GraphBinaryTypeIO):
+    python_type = statics.timestamp
+    graphbinary_type = DataType.timestamp
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        # Java timestamp expects milliseconds integer - Have to use int because of legacy Python
+        ts = int(round(obj * 1000))
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int64_pack(ts))
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        # Python timestamp expects seconds
+        return cls.is_null(buff, reader, lambda b, r: statics.timestamp(int64_unpack(b.read(8)) / 1000.0),
+                           nullable)
+    
+
+def _long_bits_to_double(bits):
+    return unpack('d', pack('Q', bits))[0]
+
+
+NAN = _long_bits_to_double(0x7ff8000000000000)
+POSITIVE_INFINITY = _long_bits_to_double(0x7ff0000000000000)
+NEGATIVE_INFINITY = _long_bits_to_double(0xFff0000000000000)
+
+
+class FloatIO(LongIO):
+
+    python_type = FloatType
+    graphbinary_type = DataType.float
+    graphbinary_base_type = DataType.float
+    byte_format_pack = float_pack
+    byte_format_unpack = float_unpack
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        if math.isnan(obj):
+            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+            to_extend.extend(cls.byte_format_pack(NAN))
+        elif math.isinf(obj) and obj > 0:
+            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+            to_extend.extend(cls.byte_format_pack(POSITIVE_INFINITY))
+        elif math.isinf(obj) and obj < 0:
+            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+            to_extend.extend(cls.byte_format_pack(NEGATIVE_INFINITY))
+        else:
+            cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+            to_extend.extend(cls.byte_format_pack(obj))
+
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: float_unpack(b.read(4)), nullable)
+
+
+class DoubleIO(FloatIO):
+    """
+    Floats basically just fall through to double serialization.
+    """
+
+    graphbinary_type = DataType.double
+    graphbinary_base_type = DataType.double
+    byte_format_pack = double_pack
+    byte_format_unpack = double_unpack
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: double_unpack(b.read(8)), nullable)
+
+
+class CharIO(_GraphBinaryTypeIO):
+    python_type = SingleChar
+    graphbinary_type = DataType.char
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(obj.encode("utf-8"))
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_char, nullable)
+
+    @classmethod
+    def _read_char(cls, b, r):
+        max_bytes = 4
+        x = b.read(1)
+        while max_bytes > 0:
+            max_bytes = max_bytes - 1
+            try:
+                return x.decode("utf-8")
+            except UnicodeDecodeError:
+                x += b.read(1)
+
+
+class StringIO(_GraphBinaryTypeIO):
+
+    python_type = str
+    graphbinary_type = DataType.string
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        str_bytes = obj.encode("utf-8")
+        to_extend += int32_pack(len(str_bytes))
+        to_extend += str_bytes
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: b.read(cls.read_int(b)).decode("utf-8"), nullable)
+
+
+class ListIO(_GraphBinaryTypeIO):
+
+    python_type = list
+    graphbinary_type = DataType.list
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int32_pack(len(obj)))
+        for item in obj:
+            writer.toDict(item, to_extend)
+
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_list, nullable)
+
+    @classmethod
+    def _read_list(cls, b, r):
+        size = cls.read_int(b)
+        the_list = []
+        while size > 0:
+            the_list.append(r.readObject(b))
+            size = size - 1
+
+        return the_list
+
+
+class SetDeserializer(ListIO):
+
+    python_type = SetType
+    graphbinary_type = DataType.set
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return set(ListIO.objectify(buff, reader, nullable))
+
+
+class MapIO(_GraphBinaryTypeIO):
+
+    python_type = DictType
+    graphbinary_type = DataType.map
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+
+        to_extend.extend(int32_pack(len(obj)))
+        for k, v in obj.items():
+            writer.toDict(k, to_extend)
+            writer.toDict(v, to_extend)
+
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_map, nullable)
+
+    @classmethod
+    def _read_map(cls, b, r):
+        size = cls.read_int(b)
+        the_dict = {}
+        while size > 0:
+            k = HashableDict.of(r.readObject(b))
+            v = r.readObject(b)
+            the_dict[k] = v
+            size = size - 1
+
+        return the_dict
+
+
+class UuidIO(_GraphBinaryTypeIO):
+
+    python_type = uuid.UUID
+    graphbinary_type = DataType.uuid
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(obj.bytes)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: uuid.UUID(bytes=b.read(16)), nullable)
+
+
+class EdgeIO(_GraphBinaryTypeIO):
+
+    python_type = Edge
+    graphbinary_type = DataType.edge
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+
+        writer.toDict(obj.id, to_extend)
+        StringIO.dictify(obj.label, writer, to_extend, True, False)
+        writer.toDict(obj.inV.id, to_extend)
+        StringIO.dictify(obj.inV.label, writer, to_extend, True, False)
+        writer.toDict(obj.outV.id, to_extend)
+        StringIO.dictify(obj.outV.label, writer, to_extend, True, False)
+        to_extend.extend(NULL_BYTES)
+        to_extend.extend(NULL_BYTES)
+
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_edge, nullable)
+
+    @classmethod
+    def _read_edge(cls, b, r):
+        edgeid = r.readObject(b)
+        edgelbl = r.toObject(b, DataType.string, False)
+        inv = Vertex(r.readObject(b), r.toObject(b, DataType.string, False))
+        outv = Vertex(r.readObject(b), r.toObject(b, DataType.string, False))
+        edge = Edge(edgeid, outv, edgelbl, inv)
+        b.read(4)
+        return edge
+
+
+class PathIO(_GraphBinaryTypeIO):
+
+    python_type = Path
+    graphbinary_type = DataType.path
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        writer.toDict(obj.labels, to_extend)
+        writer.toDict(obj.objects, to_extend)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: Path(r.readObject(b), r.readObject(b)), nullable)
+
+
+class PropertyIO(_GraphBinaryTypeIO):
+
+    python_type = Property
+    graphbinary_type = DataType.property
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        StringIO.dictify(obj.key, writer, to_extend, True, False)
+        writer.toDict(obj.value, to_extend)
+        to_extend.extend(NULL_BYTES)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_property, nullable)
+
+    @classmethod
+    def _read_property(cls, b, r):
+        p = Property(r.toObject(b, DataType.string, False), r.readObject(b), None)
+        b.read(2)
+        return p
+
+
+class TinkerGraphIO(_GraphBinaryTypeIO):
+
+    python_type = Graph
+    graphbinary_type = DataType.graph
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        raise AttributeError("TinkerGraph serialization is not currently supported by gremlin-python")
+
+    @classmethod
+    def objectify(cls, b, reader, as_value=False):
+        raise AttributeError("TinkerGraph deserialization is not currently supported by gremlin-python")
+
+
+class VertexIO(_GraphBinaryTypeIO):
+
+    python_type = Vertex
+    graphbinary_type = DataType.vertex
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        writer.toDict(obj.id, to_extend)
+        StringIO.dictify(obj.label, writer, to_extend, True, False)
+        to_extend.extend(NULL_BYTES)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_vertex, nullable)
+
+    @classmethod
+    def _read_vertex(cls, b, r):
+        vertex = Vertex(r.readObject(b), r.toObject(b, DataType.string, False))
+        b.read(2)
+        return vertex
+
+
+class VertexPropertyIO(_GraphBinaryTypeIO):
+
+    python_type = VertexProperty
+    graphbinary_type = DataType.vertexproperty
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        writer.toDict(obj.id, to_extend)
+        StringIO.dictify(obj.label, writer, to_extend, True, False)
+        writer.toDict(obj.value, to_extend)
+        to_extend.extend(NULL_BYTES)
+        to_extend.extend(NULL_BYTES)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_vertexproperty, nullable)
+
+    @classmethod
+    def _read_vertexproperty(cls, b, r):
+        vp = VertexProperty(r.readObject(b), r.toObject(b, DataType.string, False), r.readObject(b), None)
+        b.read(4)
+        return vp
+
+
+class _EnumIO(_GraphBinaryTypeIO):
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        StringIO.dictify(cls.unmangle_keyword(str(obj.name)), writer, to_extend)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_enumval, nullable)
+
+    @classmethod
+    def _read_enumval(cls, b, r):
+        enum_name = r.toObject(b)
+        return cls.python_type[enum_name]
+
+
+class BarrierIO(_EnumIO):
+    graphbinary_type = DataType.barrier
+    python_type = Barrier
+
+
+class CardinalityIO(_EnumIO):
+    graphbinary_type = DataType.cardinality
+    python_type = Cardinality
+
+
+class ColumnIO(_EnumIO):
+    graphbinary_type = DataType.column
+    python_type = Column
+
+
+class DirectionIO(_EnumIO):
+    graphbinary_type = DataType.direction
+    python_type = Direction
+
+
+class OperatorIO(_EnumIO):
+    graphbinary_type = DataType.operator
+    python_type = Operator
+
+
+class OrderIO(_EnumIO):
+    graphbinary_type = DataType.order
+    python_type = Order
+
+
+class PickIO(_EnumIO):
+    graphbinary_type = DataType.pick
+    python_type = Pick
+
+
+class PopIO(_EnumIO):
+    graphbinary_type = DataType.pop
+    python_type = Pop
+
+
+class BindingIO(_GraphBinaryTypeIO):
+
+    python_type = Binding
+    graphbinary_type = DataType.binding
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        StringIO.dictify(obj.key, writer, to_extend, True, False)
+        writer.toDict(obj.value, to_extend)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, lambda b, r: Binding(r.toObject(b, DataType.string, False),
+                                                              reader.readObject(b)), nullable)
+
+
+class BytecodeIO(_GraphBinaryTypeIO):
+    python_type = Bytecode
+    graphbinary_type = DataType.bytecode
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        bc = obj.bytecode if isinstance(obj, Traversal) else obj
+        to_extend.extend(int32_pack(len(bc.step_instructions)))
+        for inst in bc.step_instructions:
+            inst_name, inst_args = inst[0], inst[1:] if len(inst) > 1 else []
+            StringIO.dictify(inst_name, writer, to_extend, True, False)
+            to_extend.extend(int32_pack(len(inst_args)))
+            for arg in inst_args:
+                writer.toDict(arg, to_extend)
+
+        to_extend.extend(int32_pack(len(bc.source_instructions)))
+        for inst in bc.source_instructions:
+            inst_name, inst_args = inst[0], inst[1:] if len(inst) > 1 else []
+            StringIO.dictify(inst_name, writer, to_extend, True, False)
+            to_extend.extend(int32_pack(len(inst_args)))
+            for arg in inst_args:
+                if isinstance(arg, TypeType):
+                    writer.toDict(GremlinType(arg().fqcn), to_extend)
+                else:
+                    writer.toDict(arg, to_extend)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_bytecode, nullable)
+
+    @classmethod
+    def _read_bytecode(cls, b, r):
+        bytecode = Bytecode()
+
+        step_count = cls.read_int(b)
+        ix = 0
+        while ix < step_count:
+            inst = [r.toObject(b, DataType.string, False)]
+            inst_ct = cls.read_int(b)
+            iy = 0
+            while iy < inst_ct:
+                inst.append(r.readObject(b))
+                iy += 1
+            bytecode.step_instructions.append(inst)
+            ix += 1
+
+        source_count = cls.read_int(b)
+        ix = 0
+        while ix < source_count:
+            inst = [r.toObject(b, DataType.string, False)]
+            inst_ct = cls.read_int(b)
+            iy = 0
+            while iy < inst_ct:
+                inst.append(r.readObject(b))
+                iy += 1
+            bytecode.source_instructions.append(inst)
+            ix += 1
+
+        return bytecode
+
+
+class TraversalIO(BytecodeIO):
+    python_type = GraphTraversal
+
+
+class LambdaSerializer(_GraphBinaryTypeIO):
+
+    python_type = FunctionType
+    graphbinary_type = DataType.lambda_
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+
+        lambda_result = obj()
+        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
+        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
+
+        StringIO.dictify(language, writer, to_extend, True, False)
+
+        script_cleaned = script
+        script_args = -1
+
+        if language == "gremlin-groovy" and "->" in script:
+            # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
+            # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
+            args = script[0:script.find("->")]
+            script_args = 2 if "," in args else 1
+
+        StringIO.dictify(script_cleaned, writer, to_extend, True, False)
+        to_extend.extend(int32_pack(script_args))
+
+        return to_extend
+
+
+class PSerializer(_GraphBinaryTypeIO):
+    graphbinary_type = DataType.p
+    python_type = P
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+
+        StringIO.dictify(obj.operator, writer, to_extend, True, False)
+
+        args = []
+        if obj.other is None:
+            if isinstance(obj.value, ListType):
+                args = obj.value
+            else:
+                args.append(obj.value)
+        else:
+            args.append(obj.value)
+            args.append(obj.other)
+
+        to_extend.extend(int32_pack(len(args)))
+        for a in args:
+            writer.toDict(a, to_extend)
+
+        return to_extend
+
+
+class ScopeIO(_EnumIO):
+    graphbinary_type = DataType.scope
+    python_type = Scope
+
+
+class TIO(_EnumIO):
+    graphbinary_type = DataType.t
+    python_type = T
+
+
+class TraverserIO(_GraphBinaryTypeIO):
+    graphbinary_type = DataType.traverser
+    python_type = Traverser
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int64_pack(obj.bulk))
+        writer.toDict(obj.object, to_extend)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_traverser, nullable)
+
+    @classmethod
+    def _read_traverser(cls, b, r):
+        bulk = int64_unpack(b.read(8))
+        obj = r.readObject(b)
+        return Traverser(obj, bulk=bulk)
+
+
+class ByteIO(_GraphBinaryTypeIO):
+    python_type = SingleByte
+    graphbinary_type = DataType.byte
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int8_pack(obj))
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader,
+                           lambda b, r: int.__new__(SingleByte, int8_unpack(b.read(1))),
+                           nullable)
+
+
+class ByteBufferIO(_GraphBinaryTypeIO):
+    python_type = ByteBufferType
+    graphbinary_type = DataType.bytebuffer
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int32_pack(len(obj)))
+        to_extend.extend(obj)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_bytebuffer, nullable)
+
+    @classmethod
+    def _read_bytebuffer(cls, b, r):
+        size = cls.read_int(b)
+        return ByteBufferType(b.read(size))
+
+
+class BooleanIO(_GraphBinaryTypeIO):
+    python_type = bool
+    graphbinary_type = DataType.boolean
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        to_extend.extend(int8_pack(0x01 if obj else 0x00))
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader,
+                           lambda b, r: True if int8_unpack(b.read(1)) == 0x01 else False,
+                           nullable)
+
+
+class TextPSerializer(_GraphBinaryTypeIO):
+    graphbinary_type = DataType.textp
+    python_type = TextP
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+
+        StringIO.dictify(obj.operator, writer, to_extend, True, False)
+
+        args = []
+        if obj.other is None:
+            if isinstance(obj.value, ListType):
+                args = obj.value
+            else:
+                args.append(obj.value)
+        else:
+            args.append(obj.value)
+            args.append(obj.other)
+
+        to_extend.extend(int32_pack(len(args)))
+        for a in args:
+            writer.toDict(a, to_extend)
+
+        return to_extend
+
+
+class BulkSetDeserializer(_GraphBinaryTypeIO):
+
+    graphbinary_type = DataType.bulkset
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_bulkset, nullable)
+
+    @classmethod
+    def _read_bulkset(cls, b, r):
+        size = cls.read_int(b)
+        the_list = []
+        while size > 0:
+            itm = r.readObject(b)
+            bulk = int64_unpack(b.read(8))
+            for y in range(bulk):
+                the_list.append(itm)            
+            size = size - 1
+
+        return the_list
+
+
+class MetricsDeserializer(_GraphBinaryTypeIO):
+
+    graphbinary_type = DataType.metrics
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_metrics, nullable)
+
+    @classmethod
+    def _read_metrics(cls, b, r):
+        metricid = r.toObject(b, DataType.string, False)
+        name = r.toObject(b, DataType.string, False)
+        duration = r.toObject(b, DataType.long, nullable=False)
+        counts = r.toObject(b, DataType.map, nullable=False)
+        annotations = r.toObject(b, DataType.map, nullable=False)
+        metrics = r.toObject(b, DataType.list, nullable=False)
+
+        return {"id": metricid,
+                "name": name,
+                "dur": duration,
+                "counts": counts,
+                "annotations": annotations,
+                "metrics": metrics}
+
+
+class TraversalMetricsDeserializer(_GraphBinaryTypeIO):
+
+    graphbinary_type = DataType.traversalmetrics
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_traversalmetrics, nullable)
+
+    @classmethod
+    def _read_traversalmetrics(cls, b, r):
+        duration = r.toObject(b, DataType.long, nullable=False)
+        metrics = r.toObject(b, DataType.list, nullable=False)
+
+        return {"dur": duration,
+                "metrics": metrics}
+
+
+class ClassSerializer(_GraphBinaryTypeIO):
+    graphbinary_type = DataType.clazz
+    python_type = GremlinType
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        StringIO.dictify(obj.gremlin_type, writer, to_extend, True, False)
+        return to_extend
+
+
+class TraversalStrategySerializer(_GraphBinaryTypeIO):
+    graphbinary_type = DataType.traversalstrategy
+    python_type = TraversalStrategy
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+
+        ClassSerializer.dictify(GremlinType(obj.fqcn), writer, to_extend, True, False)
+        conf = {k: cls._convert(v) for k, v in obj.configuration.items()}
+        MapIO.dictify(conf, writer, to_extend, True, False)
+
+        return to_extend
+
+    @classmethod
+    def _convert(cls, v):
+        return v.bytecode if isinstance(v, Traversal) else v
+
+
+class DurationIO(_GraphBinaryTypeIO):
+    python_type = timedelta
+    graphbinary_type = DataType.duration
+
+    @classmethod
+    def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
+        cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
+        LongIO.dictify(obj.seconds, writer, to_extend, True, False)
+        IntIO.dictify(obj.microseconds * 1000, writer, to_extend, True, False)
+        return to_extend
+
+    @classmethod
+    def objectify(cls, buff, reader, nullable=True):
+        return cls.is_null(buff, reader, cls._read_duration, nullable)
+    
+    @classmethod
+    def _read_duration(cls, b, r):
+        seconds = r.toObject(b, DataType.long, False)
+        nanos = r.toObject(b, DataType.int, False)
+        return timedelta(seconds=seconds, microseconds=nanos / 1000)
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py
new file mode 100644
index 0000000..20d186e
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py
@@ -0,0 +1,632 @@
+#
+# 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.
+#
+
+import calendar
+import datetime
+import json
+import uuid
+import math
+from collections import OrderedDict
+from decimal import *
+from datetime import timedelta
+
+import six
+from aenum import Enum
+from isodate import parse_duration, duration_isoformat
+
+from gremlin_python import statics
+from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, SingleByte, ByteBufferType, SingleChar
+from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy
+from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
+
+# When we fall back to a superclass's serializer, we iterate over this map.
+# We want that iteration order to be consistent, so we use an OrderedDict,
+# not a dict.
+_serializers = OrderedDict()
+_deserializers = {}
+
+
+class GraphSONTypeType(type):
+    def __new__(mcs, name, bases, dct):
+        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
+        if not name.startswith('_'):
+            if cls.python_type:
+                _serializers[cls.python_type] = cls
+            if cls.graphson_type:
+                _deserializers[cls.graphson_type] = cls
+        return cls
+
+
+class GraphSONUtil(object):
+    TYPE_KEY = "@type"
+    VALUE_KEY = "@value"
+
+    @classmethod
+    def typedValue(cls, type_name, value, prefix="g"):
+        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
+        if value is not None:
+            out[cls.VALUE_KEY] = value
+        return out
+
+    @classmethod
+    def formatType(cls, prefix, type_name):
+        return "%s:%s" % (prefix, type_name)
+
+
+# Read/Write classes split to follow precedence of the Java API
+class GraphSONWriter(object):
+    def __init__(self, serializer_map=None):
+        """
+        :param serializer_map: map from Python type to serializer instance implementing `dictify`
+        """
+        self.serializers = _serializers.copy()
+        if serializer_map:
+            self.serializers.update(serializer_map)
+
+    def writeObject(self, objectData):
+        # to JSON
+        return json.dumps(self.toDict(objectData), separators=(',', ':'))
+
+    def toDict(self, obj):
+        """
+        Encodes python objects in GraphSON type-tagged dict values
+        """
+        try:
+            return self.serializers[type(obj)].dictify(obj, self)
+        except KeyError:
+            for key, serializer in self.serializers.items():
+                if isinstance(obj, key):
+                    return serializer.dictify(obj, self)
+
+        # list and map are treated as normal json objs (could be isolated serializers)
+        if isinstance(obj, (list, set)):
+            return [self.toDict(o) for o in obj]
+        elif isinstance(obj, dict):
+            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
+        else:
+            return obj
+
+
+class GraphSONReader(object):
+    def __init__(self, deserializer_map=None):
+        """
+        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
+        """
+        self.deserializers = _deserializers.copy()
+        if deserializer_map:
+            self.deserializers.update(deserializer_map)
+
+    def readObject(self, jsonData):
+        # from JSON
+        return self.toObject(json.loads(jsonData))
+
+    def toObject(self, obj):
+        """
+        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
+        """
+        if isinstance(obj, dict):
+            try:
+                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
+            except KeyError:
+                pass
+            # list and map are treated as normal json objs (could be isolated deserializers)
+            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
+        elif isinstance(obj, list):
+            return [self.toObject(o) for o in obj]
+        else:
+            return obj
+
+
+@six.add_metaclass(GraphSONTypeType)
+class _GraphSONTypeIO(object):
+    python_type = None
+    graphson_type = None
+
+    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
+                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
+                 "set_": "set", "list_": "list", "all_": "all", "with_": "with",
+                 "filter_": "filter", "id_": "id", "max_": "max", "min_": "min", "sum_": "sum"}
+
+    @classmethod
+    def unmangleKeyword(cls, symbol):
+        return cls.symbolMap.get(symbol, symbol)
+
+    def dictify(self, obj, writer):
+        raise NotImplementedError()
+
+    def objectify(self, d, reader):
+        raise NotImplementedError()
+
+
+class _BytecodeSerializer(_GraphSONTypeIO):
+    @classmethod
+    def _dictify_instructions(cls, instructions, writer):
+        out = []
+        for instruction in instructions:
+            inst = [instruction[0]]
+            inst.extend(writer.toDict(arg) for arg in instruction[1:])
+            out.append(inst)
+        return out
+
+    @classmethod
+    def dictify(cls, bytecode, writer):
+        if isinstance(bytecode, Traversal):
+            bytecode = bytecode.bytecode
+        out = {}
+        if bytecode.source_instructions:
+            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
+        if bytecode.step_instructions:
+            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
+        return GraphSONUtil.typedValue("Bytecode", out)
+
+class TraversalSerializer(_BytecodeSerializer):
+    python_type = Traversal
+
+
+class BytecodeSerializer(_BytecodeSerializer):
+    python_type = Bytecode
+
+
+class VertexSerializer(_GraphSONTypeIO):
+    python_type = Vertex
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def dictify(cls, vertex, writer):
+        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
+                                                  "label": writer.toDict(vertex.label)})
+
+
+class EdgeSerializer(_GraphSONTypeIO):
+    python_type = Edge
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def dictify(cls, edge, writer):
+        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
+                                                "outV": writer.toDict(edge.outV.id),
+                                                "outVLabel": writer.toDict(edge.outV.label),
+                                                "label": writer.toDict(edge.label),
+                                                "inV": writer.toDict(edge.inV.id),
+                                                "inVLabel": writer.toDict(edge.inV.label)})
+
+
+class VertexPropertySerializer(_GraphSONTypeIO):
+    python_type = VertexProperty
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def dictify(cls, vertex_property, writer):
+        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
+                                                          "label": writer.toDict(vertex_property.label),
+                                                          "value": writer.toDict(vertex_property.value),
+                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
+
+
+class PropertySerializer(_GraphSONTypeIO):
+    python_type = Property
+    graphson_type = "g:Property"
+
+    @classmethod
+    def dictify(cls, property, writer):
+        elementDict = writer.toDict(property.element)
+        if elementDict is not None:
+            valueDict = elementDict["@value"]
+            if "outVLabel" in valueDict:
+                del valueDict["outVLabel"]
+            if "inVLabel" in valueDict:
+                del valueDict["inVLabel"]
+            if "properties" in valueDict:
+                del valueDict["properties"]
+            if "value" in valueDict:
+                del valueDict["value"]
+        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
+                                                    "value": writer.toDict(property.value),
+                                                    "element": elementDict})
+
+
+class TraversalStrategySerializer(_GraphSONTypeIO):
+    python_type = TraversalStrategy
+
+    @classmethod
+    def dictify(cls, strategy, writer):
+        return GraphSONUtil.typedValue(strategy.strategy_name, writer.toDict(strategy.configuration))
+
+
+class TraverserIO(_GraphSONTypeIO):
+    python_type = Traverser
+    graphson_type = "g:Traverser"
+
+    @classmethod
+    def dictify(cls, traverser, writer):
+        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
+                                                     "bulk": writer.toDict(traverser.bulk)})
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Traverser(reader.toObject(d["value"]),
+                         reader.toObject(d["bulk"]))
+
+
+class EnumSerializer(_GraphSONTypeIO):
+    python_type = Enum
+
+    @classmethod
+    def dictify(cls, enum, _):
+        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
+                                       cls.unmangleKeyword(str(enum.name)))
+
+
+class PSerializer(_GraphSONTypeIO):
+    python_type = P
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("P", out)
+
+
+class TextPSerializer(_GraphSONTypeIO):
+    python_type = TextP
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("TextP", out)
+
+
+class BindingSerializer(_GraphSONTypeIO):
+    python_type = Binding
+
+    @classmethod
+    def dictify(cls, binding, writer):
+        out = {"key": binding.key,
+               "value": writer.toDict(binding.value)}
+        return GraphSONUtil.typedValue("Binding", out)
+
+
+class LambdaSerializer(_GraphSONTypeIO):
+    python_type = FunctionType
+
+    @classmethod
+    def dictify(cls, lambda_object, writer):
+        lambda_result = lambda_object()
+        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
+        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
+        out = {"script": script,
+               "language": language}
+        if language == "gremlin-groovy" and "->" in script:
+            # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
+            # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
+            args = script[0:script.find("->")]
+            out["arguments"] = 2 if "," in args else 1
+        else:
+            out["arguments"] = -1
+
+        return GraphSONUtil.typedValue("Lambda", out)
+
+
+class TypeSerializer(_GraphSONTypeIO):
+    python_type = TypeType
+
+    @classmethod
+    def dictify(cls, typ, writer):
+        return writer.toDict(typ())
+
+
+class UUIDIO(_GraphSONTypeIO):
+    python_type = uuid.UUID
+    graphson_type = "g:UUID"
+    graphson_base_type = "UUID"
+
+    @classmethod
+    def dictify(cls, obj, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, str(obj))
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return cls.python_type(d)
+
+
+class DateIO(_GraphSONTypeIO):
+    python_type = datetime.datetime
+    graphson_type = "g:Date"
+    graphson_base_type = "Date"
+
+    @classmethod
+    def dictify(cls, obj, writer):
+        try:
+            timestamp_seconds = calendar.timegm(obj.utctimetuple())
+            pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
+        except AttributeError:
+            pts = calendar.timegm(obj.timetuple()) * 1e3
+
+        ts = int(round(pts))
+        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
+
+    @classmethod
+    def objectify(cls, ts, reader):
+        # Python timestamp expects seconds
+        return datetime.datetime.utcfromtimestamp(ts / 1000.0)
+
+
+# Based on current implementation, this class must always be declared before FloatIO.
+# Seems pretty fragile for future maintainers. Maybe look into this.
+class TimestampIO(_GraphSONTypeIO):
+    """A timestamp in Python is type float"""
+    python_type = statics.timestamp
+    graphson_type = "g:Timestamp"
+    graphson_base_type = "Timestamp"
+
+    @classmethod
+    def dictify(cls, obj, writer):
+        # Java timestamp expects milliseconds integer
+        # Have to use int because of legacy Python
+        ts = int(round(obj * 1000))
+        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
+
+    @classmethod
+    def objectify(cls, ts, reader):
+        # Python timestamp expects seconds
+        return cls.python_type(ts / 1000.0)
+
+
+class _NumberIO(_GraphSONTypeIO):
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+    @classmethod
+    def objectify(cls, v, _):
+        return cls.python_type(v)
+
+
+class FloatIO(_NumberIO):
+    python_type = FloatType
+    graphson_type = "g:Float"
+    graphson_base_type = "Float"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        elif math.isnan(n):
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN")
+        elif math.isinf(n) and n > 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity")
+        elif math.isinf(n) and n < 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity")
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+    @classmethod
+    def objectify(cls, v, _):
+        if isinstance(v, str):
+            if v == 'NaN':
+                return float('nan')
+            elif v == "Infinity":
+                return float('inf')
+            elif v == "-Infinity":
+                return float('-inf')
+
+        return cls.python_type(v)
+
+
+class BigDecimalIO(_NumberIO):
+    python_type = Decimal
+    graphson_type = "gx:BigDecimal"
+    graphson_base_type = "BigDecimal"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        elif math.isnan(n):
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN", "gx")
+        elif math.isinf(n) and n > 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity", "gx")
+        elif math.isinf(n) and n < 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity", "gx")
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, str(n), "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        if isinstance(v, str):
+            if v == 'NaN':
+                return Decimal('nan')
+            elif v == "Infinity":
+                return Decimal('inf')
+            elif v == "-Infinity":
+                return Decimal('-inf')
+
+        return Decimal(v)
+
+
+class DoubleIO(FloatIO):
+    graphson_type = "g:Double"
+    graphson_base_type = "Double"
+
+
+class Int64IO(_NumberIO):
+    python_type = LongType
+    graphson_type = "g:Int64"
+    graphson_base_type = "Int64"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        # if we exceed Java long range then we need a BigInteger
+        if isinstance(n, bool):
+            return n
+        elif n < -9223372036854775808 or n > 9223372036854775807:
+            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+
+class BigIntegerIO(Int64IO):
+    graphson_type = "gx:BigInteger"
+
+
+class Int32IO(Int64IO):
+    python_type = IntType
+    graphson_type = "g:Int32"
+    graphson_base_type = "Int32"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        # if we exceed Java int range then we need a long
+        if isinstance(n, bool):
+            return n
+        elif n < -9223372036854775808 or n > 9223372036854775807:
+            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
+        elif n < -2147483648 or n > 2147483647:
+            return GraphSONUtil.typedValue("Int64", n)
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+
+class ByteIO(_NumberIO):
+    python_type = SingleByte
+    graphson_type = "gx:Byte"
+    graphson_base_type = "Byte"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return int.__new__(SingleByte, v)
+
+
+class ByteBufferIO(_GraphSONTypeIO):
+    python_type = ByteBufferType
+    graphson_type = "gx:ByteBuffer"
+    graphson_base_type = "ByteBuffer"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, "".join(chr(x) for x in n), "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return cls.python_type(v, "utf8")
+
+
+class CharIO(_GraphSONTypeIO):
+    python_type = SingleChar
+    graphson_type = "gx:Char"
+    graphson_base_type = "Char"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return str.__new__(SingleChar, v)
+
+
+class DurationIO(_GraphSONTypeIO):
+    python_type = timedelta
+    graphson_type = "gx:Duration"
+    graphson_base_type = "Duration"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, duration_isoformat(n), "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return parse_duration(v)
+
+
+class VertexDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
+
+
+class EdgeDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Edge(reader.toObject(d["id"]),
+                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
+                    d.get("label", "edge"),
+                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
+
+
+class VertexPropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
+        return VertexProperty(reader.toObject(d["id"]),
+                              d["label"],
+                              reader.toObject(d["value"]),
+                              vertex)
+
+
+class PropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Property"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        element = reader.toObject(d["element"]) if "element" in d else None
+        return Property(d["key"], reader.toObject(d["value"]), element)
+
+
+class PathDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Path"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        labels = [set(label) for label in d["labels"]]
+        objects = [reader.toObject(o) for o in d["objects"]]
+        return Path(labels, objects)
+
+
+class TraversalMetricsDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:TraversalMetrics"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return reader.toObject(d)
+
+
+class MetricsDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Metrics"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return reader.toObject(d)
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py
new file mode 100644
index 0000000..9ba2127
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py
@@ -0,0 +1,750 @@
+# 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.
+import calendar
+import datetime
+import json
+import uuid
+import math
+from collections import OrderedDict
+from decimal import *
+import logging
+from datetime import timedelta
+
+import six
+from aenum import Enum
+from isodate import parse_duration, duration_isoformat
+
+from gremlin_python import statics
+from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
+from gremlin_python.process.traversal import Binding, Bytecode, Direction, P, TextP, Traversal, Traverser, TraversalStrategy, T
+from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
+from gremlin_python.structure.io.util import HashableDict
+
+log = logging.getLogger(__name__)
+
+# When we fall back to a superclass's serializer, we iterate over this map.
+# We want that iteration order to be consistent, so we use an OrderedDict,
+# not a dict.
+_serializers = OrderedDict()
+_deserializers = {}
+
+class GraphSONTypeType(type):
+    def __new__(mcs, name, bases, dct):
+        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
+        if not name.startswith('_'):
+            if cls.python_type:
+                _serializers[cls.python_type] = cls
+            if cls.graphson_type:
+                _deserializers[cls.graphson_type] = cls
+        return cls
+
+
+class GraphSONUtil(object):
+    TYPE_KEY = "@type"
+    VALUE_KEY = "@value"
+
+    @classmethod
+    def typedValue(cls, type_name, value, prefix="g"):
+        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
+        if value is not None:
+            out[cls.VALUE_KEY] = value
+        return out
+
+    @classmethod
+    def formatType(cls, prefix, type_name):
+        return "%s:%s" % (prefix, type_name)
+
+
+# Read/Write classes split to follow precedence of the Java API
+class GraphSONWriter(object):
+    def __init__(self, serializer_map=None):
+        """
+        :param serializer_map: map from Python type to serializer instance implementing `dictify`
+        """
+        self.serializers = _serializers.copy()
+        if serializer_map:
+            self.serializers.update(serializer_map)
+
+    def writeObject(self, objectData):
+        # to JSON
+        return json.dumps(self.toDict(objectData), separators=(',', ':'))
+
+    def toDict(self, obj):
+        """
+        Encodes python objects in GraphSON type-tagged dict values
+        """
+        try:
+            return self.serializers[type(obj)].dictify(obj, self)
+        except KeyError:
+            for key, serializer in self.serializers.items():
+                if isinstance(obj, key):
+                    return serializer.dictify(obj, self)
+
+        if isinstance(obj, dict):
+            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
+        elif isinstance(obj, set):
+            return set([self.toDict(o) for o in obj])
+        elif isinstance(obj, list):
+            return [self.toDict(o) for o in obj]
+        else:
+            return obj
+
+
+class GraphSONReader(object):
+    def __init__(self, deserializer_map=None):
+        """
+        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
+        """
+        self.deserializers = _deserializers.copy()
+        if deserializer_map:
+            self.deserializers.update(deserializer_map)
+
+    def readObject(self, jsonData):
+        # from JSON
+        return self.toObject(json.loads(jsonData))
+
+    def toObject(self, obj):
+        """
+        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
+        """
+        if isinstance(obj, dict):
+            try:
+                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
+            except KeyError:
+                pass
+            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
+        elif isinstance(obj, set):
+            return set([self.toObject(o) for o in obj])
+        elif isinstance(obj, list):
+            return [self.toObject(o) for o in obj]
+        else:
+            return obj
+
+
+@six.add_metaclass(GraphSONTypeType)
+class _GraphSONTypeIO(object):
+    python_type = None
+    graphson_type = None
+
+    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
+                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
+                 "set_": "set", "list_": "list", "all_": "all", "with_": "with",
+                 "filter_": "filter", "id_": "id", "max_": "max", "min_": "min", "sum_": "sum"}
+
+    @classmethod
+    def unmangleKeyword(cls, symbol):
+        return cls.symbolMap.get(symbol, symbol)
+
+    def dictify(self, obj, writer):
+        raise NotImplementedError()
+
+    def objectify(self, d, reader):
+        raise NotImplementedError()
+
+
+class _BytecodeSerializer(_GraphSONTypeIO):
+    @classmethod
+    def _dictify_instructions(cls, instructions, writer):
+        out = []
+        for instruction in instructions:
+            inst = [instruction[0]]
+            inst.extend(writer.toDict(arg) for arg in instruction[1:])
+            out.append(inst)
+        return out
+
+    @classmethod
+    def dictify(cls, bytecode, writer):
+        if isinstance(bytecode, Traversal):
+            bytecode = bytecode.bytecode
+        out = {}
+        if bytecode.source_instructions:
+            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
+        if bytecode.step_instructions:
+            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
+        return GraphSONUtil.typedValue("Bytecode", out)
+
+
+class TraversalSerializer(_BytecodeSerializer):
+    python_type = Traversal
+
+
+class BytecodeSerializer(_BytecodeSerializer):
+    python_type = Bytecode
+
+
+class VertexSerializer(_GraphSONTypeIO):
+    python_type = Vertex
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def dictify(cls, vertex, writer):
+        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
+                                                  "label": writer.toDict(vertex.label)})
+
+
+class EdgeSerializer(_GraphSONTypeIO):
+    python_type = Edge
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def dictify(cls, edge, writer):
+        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
+                                                "outV": writer.toDict(edge.outV.id),
+                                                "outVLabel": writer.toDict(edge.outV.label),
+                                                "label": writer.toDict(edge.label),
+                                                "inV": writer.toDict(edge.inV.id),
+                                                "inVLabel": writer.toDict(edge.inV.label)})
+
+
+class VertexPropertySerializer(_GraphSONTypeIO):
+    python_type = VertexProperty
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def dictify(cls, vertex_property, writer):
+        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
+                                                          "label": writer.toDict(vertex_property.label),
+                                                          "value": writer.toDict(vertex_property.value),
+                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
+
+
+class PropertySerializer(_GraphSONTypeIO):
+    python_type = Property
+    graphson_type = "g:Property"
+
+    @classmethod
+    def dictify(cls, property, writer):
+        elementDict = writer.toDict(property.element)
+        if elementDict is not None:
+            valueDict = elementDict["@value"]
+            if "outVLabel" in valueDict:
+                del valueDict["outVLabel"]
+            if "inVLabel" in valueDict:
+                del valueDict["inVLabel"]
+            if "properties" in valueDict:
+                del valueDict["properties"]
+            if "value" in valueDict:
+                del valueDict["value"]
+        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
+                                                    "value": writer.toDict(property.value),
+                                                    "element": elementDict})
+
+
+class TraversalStrategySerializer(_GraphSONTypeIO):
+    python_type = TraversalStrategy
+
+    @classmethod
+    def dictify(cls, strategy, writer):
+        configuration = {}
+        for key in strategy.configuration:
+            configuration[key] = writer.toDict(strategy.configuration[key])
+        return GraphSONUtil.typedValue(strategy.strategy_name, configuration)
+
+
+class TraverserIO(_GraphSONTypeIO):
+    python_type = Traverser
+    graphson_type = "g:Traverser"
+
+    @classmethod
+    def dictify(cls, traverser, writer):
+        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
+                                                     "bulk": writer.toDict(traverser.bulk)})
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Traverser(reader.toObject(d["value"]),
+                         reader.toObject(d["bulk"]))
+
+
+class EnumSerializer(_GraphSONTypeIO):
+    python_type = Enum
+
+    @classmethod
+    def dictify(cls, enum, _):
+        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
+                                       cls.unmangleKeyword(str(enum.name)))
+
+
+class PSerializer(_GraphSONTypeIO):
+    python_type = P
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("P", out)
+
+
+class TextPSerializer(_GraphSONTypeIO):
+    python_type = TextP
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("TextP", out)
+
+
+class BindingSerializer(_GraphSONTypeIO):
+    python_type = Binding
+
+    @classmethod
+    def dictify(cls, binding, writer):
+        out = {"key": binding.key,
+               "value": writer.toDict(binding.value)}
+        return GraphSONUtil.typedValue("Binding", out)
+
+
+class LambdaSerializer(_GraphSONTypeIO):
+    python_type = FunctionType
+
+    @classmethod
+    def dictify(cls, lambda_object, writer):
+        lambda_result = lambda_object()
+        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
+        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
+        out = {"script": script,
+               "language": language}
+        if language == "gremlin-groovy" and "->" in script:
+            # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
+            # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
+            args = script[0:script.find("->")]
+            out["arguments"] = 2 if "," in args else 1
+        else:
+            out["arguments"] = -1
+
+        return GraphSONUtil.typedValue("Lambda", out)
+
+
+class TypeSerializer(_GraphSONTypeIO):
+    python_type = TypeType
+
+    @classmethod
+    def dictify(cls, typ, writer):
+        return writer.toDict(typ())
+
+
+class UUIDIO(_GraphSONTypeIO):
+    python_type = uuid.UUID
+    graphson_type = "g:UUID"
+    graphson_base_type = "UUID"
+
+    @classmethod
+    def dictify(cls, obj, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, str(obj))
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return cls.python_type(d)
+
+
+class DateIO(_GraphSONTypeIO):
+    python_type = datetime.datetime
+    graphson_type = "g:Date"
+    graphson_base_type = "Date"
+
+    @classmethod
+    def dictify(cls, obj, writer):
+        try:
+            timestamp_seconds = calendar.timegm(obj.utctimetuple())
+            pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
+        except AttributeError:
+            pts = calendar.timegm(obj.timetuple()) * 1e3
+
+        ts = int(round(pts))
+        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
+
+    @classmethod
+    def objectify(cls, ts, reader):
+        # Python timestamp expects seconds
+        return datetime.datetime.utcfromtimestamp(ts / 1000.0)
+
+
+# Based on current implementation, this class must always be declared before FloatIO.
+# Seems pretty fragile for future maintainers. Maybe look into this.
+class TimestampIO(_GraphSONTypeIO):
+    """A timestamp in Python is type float"""
+    python_type = statics.timestamp
+    graphson_type = "g:Timestamp"
+    graphson_base_type = "Timestamp"
+
+    @classmethod
+    def dictify(cls, obj, writer):
+        # Java timestamp expects milliseconds integer
+        # Have to use int because of legacy Python
+        ts = int(round(obj * 1000))
+        return GraphSONUtil.typedValue(cls.graphson_base_type, ts)
+
+    @classmethod
+    def objectify(cls, ts, reader):
+        # Python timestamp expects seconds
+        return cls.python_type(ts / 1000.0)
+
+
+class _NumberIO(_GraphSONTypeIO):
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+    @classmethod
+    def objectify(cls, v, _):
+        return cls.python_type(v)
+
+
+class ListIO(_GraphSONTypeIO):
+    python_type = ListType
+    graphson_type = "g:List"
+
+    @classmethod
+    def dictify(cls, l, writer):
+        new_list = []
+        for obj in l:
+            new_list.append(writer.toDict(obj))
+        return GraphSONUtil.typedValue("List", new_list)
+
+    @classmethod
+    def objectify(cls, l, reader):
+        new_list = []
+        for obj in l:
+            new_list.append(reader.toObject(obj))
+        return new_list
+
+
+class SetIO(_GraphSONTypeIO):
+    python_type = SetType
+    graphson_type = "g:Set"
+
+    @classmethod
+    def dictify(cls, s, writer):
+        new_list = []
+        for obj in s:
+            new_list.append(writer.toDict(obj))
+        return GraphSONUtil.typedValue("Set", new_list)
+
+    @classmethod
+    def objectify(cls, s, reader):
+        """
+        By default, returns a python set
+
+        In case Java returns numeric values of different types which
+        python don't recognize, coerce and return a list.
+        See comments of TINKERPOP-1844 for more details
+        """
+        new_list = [reader.toObject(obj) for obj in s]
+        new_set = set(new_list)
+        if len(new_list) != len(new_set):
+            log.warning("Coercing g:Set to list due to java numeric values. "
+                        "See TINKERPOP-1844 for more details.")
+            return new_list
+
+        return new_set
+
+
+class MapType(_GraphSONTypeIO):
+    python_type = DictType
+    graphson_type = "g:Map"
+
+    @classmethod
+    def dictify(cls, d, writer):
+        l = []
+        for key in d:
+            l.append(writer.toDict(key))
+            l.append(writer.toDict(d[key]))
+        return GraphSONUtil.typedValue("Map", l)
+
+    @classmethod
+    def objectify(cls, l, reader):
+        new_dict = {}
+        if len(l) > 0:
+            x = 0
+            while x < len(l):
+                new_dict[HashableDict.of(reader.toObject(l[x]))] = reader.toObject(l[x + 1])
+                x = x + 2
+        return new_dict
+
+
+class BulkSetIO(_GraphSONTypeIO):
+    graphson_type = "g:BulkSet"
+
+    @classmethod
+    def objectify(cls, l, reader):
+        new_list = []
+
+        # this approach basically mimics what currently existed in 3.3.4 and prior versions where BulkSet is
+        # basically just coerced to list. the limitation here is that if the value of a bulk exceeds the size of
+        # a list (into the long space) then stuff won't work nice.
+        if len(l) > 0:
+            x = 0
+            while x < len(l):
+                obj = reader.toObject(l[x])
+                bulk = reader.toObject(l[x + 1])
+                for y in range(bulk):
+                    new_list.append(obj)
+                x = x + 2
+        return new_list
+
+
+class FloatIO(_NumberIO):
+    python_type = FloatType
+    graphson_type = "g:Float"
+    graphson_base_type = "Float"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        elif math.isnan(n):
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN")
+        elif math.isinf(n) and n > 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity")
+        elif math.isinf(n) and n < 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity")
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+    @classmethod
+    def objectify(cls, v, _):
+        if isinstance(v, str):
+            if v == 'NaN':
+                return float('nan')
+            elif v == "Infinity":
+                return float('inf')
+            elif v == "-Infinity":
+                return float('-inf')
+
+        return cls.python_type(v)
+
+
+class BigDecimalIO(_NumberIO):
+    python_type = Decimal
+    graphson_type = "gx:BigDecimal"
+    graphson_base_type = "BigDecimal"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        elif math.isnan(n):
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN", "gx")
+        elif math.isinf(n) and n > 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity", "gx")
+        elif math.isinf(n) and n < 0:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity", "gx")
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, str(n), "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        if isinstance(v, str):
+            if v == 'NaN':
+                return Decimal('nan')
+            elif v == "Infinity":
+                return Decimal('inf')
+            elif v == "-Infinity":
+                return Decimal('-inf')
+
+        return Decimal(v)
+
+
+class DoubleIO(FloatIO):
+    graphson_type = "g:Double"
+    graphson_base_type = "Double"
+
+
+class Int64IO(_NumberIO):
+    python_type = LongType
+    graphson_type = "g:Int64"
+    graphson_base_type = "Int64"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        # if we exceed Java long range then we need a BigInteger
+        if isinstance(n, bool):
+            return n
+        elif n < -9223372036854775808 or n > 9223372036854775807:
+            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+
+class BigIntegerIO(Int64IO):
+    graphson_type = "gx:BigInteger"
+
+
+class Int32IO(Int64IO):
+    python_type = IntType
+    graphson_type = "g:Int32"
+    graphson_base_type = "Int32"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        # if we exceed Java int range then we need a long
+        if isinstance(n, bool):
+            return n
+        elif n < -9223372036854775808 or n > 9223372036854775807:
+            return GraphSONUtil.typedValue("BigInteger", str(n), "gx")
+        elif n < -2147483648 or n > 2147483647:
+            return GraphSONUtil.typedValue("Int64", n)
+        else:
+            return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+class ByteIO(_NumberIO):
+    python_type = SingleByte
+    graphson_type = "gx:Byte"
+    graphson_base_type = "Byte"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return int.__new__(SingleByte, v)
+
+
+class ByteBufferIO(_GraphSONTypeIO):
+    python_type = ByteBufferType
+    graphson_type = "gx:ByteBuffer"
+    graphson_base_type = "ByteBuffer"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, "".join(chr(x) for x in n), "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return cls.python_type(v, "utf8")
+
+
+class CharIO(_GraphSONTypeIO):
+    python_type = SingleChar
+    graphson_type = "gx:Char"
+    graphson_base_type = "Char"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n, "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return str.__new__(SingleChar, v)
+
+
+class DurationIO(_GraphSONTypeIO):
+    python_type = timedelta
+    graphson_type = "gx:Duration"
+    graphson_base_type = "Duration"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, duration_isoformat(n), "gx")
+
+    @classmethod
+    def objectify(cls, v, _):
+        return parse_duration(v)
+
+
+class VertexDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
+
+
+class EdgeDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Edge(reader.toObject(d["id"]),
+                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
+                    d.get("label", "edge"),
+                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
+
+
+class VertexPropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
+        return VertexProperty(reader.toObject(d["id"]),
+                              d["label"],
+                              reader.toObject(d["value"]),
+                              vertex)
+
+
+class PropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Property"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        element = reader.toObject(d["element"]) if "element" in d else None
+        return Property(d["key"], reader.toObject(d["value"]), element)
+
+
+class PathDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Path"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Path(reader.toObject(d["labels"]), reader.toObject(d["objects"]))
+
+
+class TDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:T"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return T[d]
+
+
+class DirectionIO(_GraphSONTypeIO):
+    graphson_type = "g:Direction"
+    graphson_base_type = "Direction"
+    python_type = Direction
+
+    @classmethod
+    def dictify(cls, d, writer):
+        return GraphSONUtil.typedValue(cls.graphson_base_type, d.name, "g")
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Direction[d]
+
+
+class TraversalMetricsDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:TraversalMetrics"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return reader.toObject(d)
+
+
+class MetricsDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Metrics"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return reader.toObject(d)
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/util.py b/gremlin-python/src/main/python/gremlin_python/structure/io/util.py
new file mode 100644
index 0000000..86fd72a
--- /dev/null
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/util.py
@@ -0,0 +1,37 @@
+# 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.
+
+
+class HashableDict(dict):
+    def __hash__(self):
+        try:
+            return hash(tuple(sorted(self.items())))
+        except:
+            return hash(tuple(sorted(str(x) for x in self.items())))
+
+    @classmethod
+    def of(cls, o):
+        if isinstance(o, (tuple, set, list)):
+            return tuple([cls.of(e) for e in o])
+        elif not isinstance(o, (dict, HashableDict)):
+            return o
+
+        new_o = HashableDict()
+        for k, v in o.items():
+            new_o[k] = cls.of(v)
+        return new_o
+
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py b/gremlin-python/src/main/python/radish/feature_steps.py
new file mode 100644
index 0000000..5b9808f
--- /dev/null
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -0,0 +1,295 @@
+#
+# 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.
+#
+
+import json
+import re
+from gremlin_python.statics import long
+from gremlin_python.structure.graph import Path
+from gremlin_python.process.anonymous_traversal import traversal
+from gremlin_python.process.graph_traversal import __
+from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO, WithOptions
+from radish import given, when, then
+from hamcrest import *
+
+regex_all = re.compile(r"Pop\.all")
+regex_and = re.compile(r"([(.,\s])and\(")
+regex_as = re.compile(r"([(.,\s])as\(")
+regex_from = re.compile(r"([(.,\s])from\(")
+regex_global = re.compile(r"([(.,\s])global")
+regex_cardlist = re.compile(r"Cardinality\.list")
+regex_in = re.compile(r"([(.,\s])in\(")
+regex_is = re.compile(r"([(.,\s])is\(")
+regex_not = re.compile(r"([(.,\s])not\(")
+regex_or = re.compile(r"([(.,\s])or\(")
+regex_with = re.compile(r"([(.,\s])with\(")
+regex_true = re.compile(r"(true)")
+regex_false = re.compile(r"(false)")
+regex_null = re.compile(r"(null)")
+
+outV = __.outV
+label = __.label
+inV = __.inV
+project = __.project
+tail = __.tail
+
+ignores = []
+
+
+@given("the {graph_name:w} graph")
+def choose_graph(step, graph_name):
+    step.context.graph_name = graph_name
+    step.context.g = traversal().withRemote(step.context.remote_conn[graph_name])
+
+
+@given("the graph initializer of")
+def initialize_graph(step):
+    t = _make_traversal(step.context.g, step.text, {})
+
+    # just be sure that the traversal returns something to prove that it worked to some degree. probably
+    # is overkill to try to assert the complete success of this init operation. presumably the test
+    # suite would fail elsewhere if this didn't work which would help identify a problem.
+    result = t.toList()
+    assert len(result) > 0
+
+    # add the first result - if a map - to the bindings. this is useful for cases when parameters for
+    # the test traversal need to come from the original graph initializer (i.e. a new graph is created
+    # and you need the id of a vertex from that graph)
+
+
+@given("an unsupported test")
+def unsupported_scenario(step):
+    # this is a do nothing step as the test can't be supported for whatever reason
+    return
+
+
+@given("using the parameter {param_name:w} defined as {param:QuotedString}")
+def add_parameter(step, param_name, param):
+    if not hasattr(step.context, "traversal_params"):
+        step.context.traversal_params = {}
+
+    step.context.traversal_params[param_name] = _convert(param.replace('\\"', '"'), step.context)
+
+
+@given("the traversal of")
+def translate_traversal(step):
+    step.context.ignore = ignores.__contains__(step.text)
+    step.context.traversal = _make_traversal(
+        step.context.g, step.text,
+        step.context.traversal_params if hasattr(step.context, "traversal_params") else {})
+
+
+@when("iterated to list")
+def iterate_the_traversal(step):
+    if step.context.ignore:
+        return
+    
+    step.context.result = list(map(lambda x: _convert_results(x), step.context.traversal.toList()))
+
+
+@when("iterated next")
+def next_the_traversal(step):
+    if step.context.ignore:
+        return
+
+    step.context.result = list(map(lambda x: _convert_results(x), step.context.traversal.next()))
+
+
+@then("the result should be {characterized_as:w}")
+def assert_result(step, characterized_as):
+    if step.context.ignore:
+        return
+
+    if characterized_as == "empty":        # no results
+        assert_that(len(step.context.result), equal_to(0))
+    elif characterized_as == "ordered":    # results asserted in the order of the data table
+        _table_assertion(step.table, step.context.result, step.context, True)
+    elif characterized_as == "unordered":  # results asserted in any order
+        _table_assertion(step.table, step.context.result, step.context, False)
+    elif characterized_as == "of":         # results may be of any of the specified items in the data table
+        _any_assertion(step.table, step.context.result, step.context)
+    else:
+        raise ValueError("unknown data characterization of " + characterized_as)
+
+
+@then("the graph should return {count:d} for count of {traversal_string:QuotedString}")
+def assert_side_effects(step, count, traversal_string):
+    if step.context.ignore:
+        return
+
+    t = _make_traversal(step.context.g, traversal_string.replace('\\"', '"'),
+                        step.context.traversal_params if hasattr(step.context, "traversal_params") else {})
+    assert_that(t.count().next(), equal_to(count))
+
+
+@then("the result should have a count of {count:d}")
+def assert_count(step, count):
+    assert_that(len(list(step.context.result)), equal_to(count))
+
+
+@then("nothing should happen because")
+def nothing_happening(step):
+    return
+
+
+def _convert(val, ctx):
+    graph_name = ctx.graph_name
+    if isinstance(val, dict):                                           # convert dictionary keys/values
+        n = {}
+        for key, value in val.items():
+            n[_convert(key, ctx)] = _convert(value, ctx)
+        return n
+    elif isinstance(val, str) and re.match(r"^l\[.*\]$", val):           # parse list
+        return [] if val == "l[]" else list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
+    elif isinstance(val, str) and re.match(r"^s\[.*\]$", val):           # parse set
+        return set() if val == "s[]" else set(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
+    elif isinstance(val, str) and re.match(r"^d\[.*\]\.[ilfdm]$", val):  # parse numeric
+        return float(val[2:-3]) if val[2:-3].__contains__(".") else long(val[2:-3])
+    elif isinstance(val, str) and re.match(r"^v\[.*\]\.id$", val):       # parse vertex id
+        return __find_cached_element(ctx, graph_name, val[2:-4], "v").id
+    elif isinstance(val, str) and re.match(r"^v\[.*\]\.sid$", val):      # parse vertex id as string
+        return str(__find_cached_element(ctx, graph_name, val[2:-5], "v").id)
+    elif isinstance(val, str) and re.match(r"^v\[.*\]$", val):           # parse vertex
+        return __find_cached_element(ctx, graph_name, val[2:-1], "v")
+    elif isinstance(val, str) and re.match(r"^e\[.*\]\.id$", val):       # parse edge id
+        return __find_cached_element(ctx, graph_name, val[2:-4], "e").id
+    elif isinstance(val, str) and re.match(r"^e\[.*\]\.sid$", val):      # parse edge id as string
+        return str(__find_cached_element(ctx, graph_name, val[2:-5], "e").id)
+    elif isinstance(val, str) and re.match(r"^e\[.*\]$", val):           # parse edge
+        return __find_cached_element(ctx, graph_name, val[2:-1], "e")
+    elif isinstance(val, str) and re.match(r"^m\[.*\]$", val):           # parse json as a map
+        return _convert(json.loads(val[2:-1]), ctx)
+    elif isinstance(val, str) and re.match(r"^p\[.*\]$", val):           # parse path
+        path_objects = list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
+        return Path([set([])], path_objects)
+    elif isinstance(val, str) and re.match(r"^c\[.*\]$", val):           # parse lambda/closure
+        return lambda: (val[2:-1], "gremlin-groovy")
+    elif isinstance(val, str) and re.match(r"^t\[.*\]$", val):           # parse instance of T enum
+        return T[val[2:-1]]
+    elif isinstance(val, str) and re.match(r"^D\[.*\]$", val):           # parse instance of Direction enum
+        return Direction[val[2:-1]]
+    elif isinstance(val, str) and re.match(r"^null$", val):              # parse null to None
+        return None
+    else:
+        return val
+
+
+def __find_cached_element(ctx, graph_name, identifier, element_type):
+    if graph_name == "empty":
+        cache = __create_lookup_v(ctx.remote_conn["empty"]) if element_type == "v" else __create_lookup_e(ctx.remote_conn["empty"])
+    else:
+        cache = ctx.lookup_v[graph_name] if element_type == "v" else ctx.lookup_e[graph_name]
+
+    return cache[identifier]
+
+
+def _convert_results(val):
+    if isinstance(val, Path):
+        # kill out labels as they aren't in the assertion logic
+        return Path([set([])], val.objects)
+    else:
+        return val
+
+
+def _any_assertion(data, result, ctx):
+    converted = [_convert(line['result'], ctx) for line in data]
+    for r in result:
+        assert_that(r, is_in(converted))
+
+
+def _table_assertion(data, result, ctx, ordered):
+    # results from traversal should have the same number of entries as the feature data table
+    assert_that(len(result), equal_to(len(data)), "result:" + str(result))
+
+    results_to_test = list(result)
+
+    # finds a match in the results for each line of data to assert and then removes that item
+    # from the list - in the end there should be no items left over and each will have been asserted
+    for ix, line in enumerate(data):
+        val = _convert(line['result'], ctx)
+
+        # clear the labels since we don't define them in .feature files
+        if isinstance(val, Path):
+            val.labels = [set([])]
+
+        if ordered:
+            assert_that(results_to_test[ix], equal_to(val))
+        else:
+            assert_that(val, is_in(results_to_test))
+            results_to_test.remove(val)
+
+    if not ordered:
+        assert_that(len(results_to_test), is_(0))
+
+
+def _translate(traversal_):
+    replaced = traversal_.replace("\n", "")
+    replaced = regex_all.sub(r"Pop.all_", replaced)
+    replaced = regex_cardlist.sub(r"Cardinality.list_", replaced)
+    replaced = regex_and.sub(r"\1and_(", replaced)
+    replaced = regex_from.sub(r"\1from_(", replaced)
+    replaced = regex_global.sub(r"\1global_", replaced)
+    replaced = regex_as.sub(r"\1as_(", replaced)
+    replaced = regex_is.sub(r"\1is_(", replaced)
+    replaced = regex_not.sub(r"\1not_(", replaced)
+    replaced = regex_or.sub(r"\1or_(", replaced)
+    replaced = regex_in.sub(r"\1in_(", replaced)
+    replaced = regex_with.sub(r"\1with_(", replaced)
+    replaced = regex_true.sub(r"True", replaced)
+    replaced = regex_false.sub(r"False", replaced)
+    return regex_null.sub(r"None", replaced)
+
+
+def _make_traversal(g, traversal_string, params):
+    b = {"g": g,
+         "__": __,
+         "Barrier": Barrier,
+         "Cardinality": Cardinality,
+         "Column": Column,
+         "Direction": Direction,
+         "Order": Order,
+         "P": P,
+         "TextP": TextP,
+         "IO": IO,
+         "Pick": Pick,
+         "Pop": Pop,
+         "Scope": Scope,
+         "Operator": Operator,
+         "T": T,
+         "WithOptions": WithOptions}
+
+    b.update(params)
+
+    return eval(_translate(traversal_string), b)
+
+
+def __create_lookup_v(remote):
+    g = traversal().withRemote(remote)
+
+    # hold a map of name/vertex for use in asserting results
+    return g.V().group().by('name').by(tail()).next()
+
+
+def __create_lookup_e(remote):
+    g = traversal().withRemote(remote)
+
+    # hold a map of the "name"/edge for use in asserting results - "name" in this context is in the form of
+    # outgoingV-label->incomingV
+    return g.E().group(). \
+        by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + it.inVertex().value('name')", "gremlin-groovy")). \
+        by(tail()).next()
diff --git a/gremlin-python/src/main/python/radish/terrain.py b/gremlin-python/src/main/python/radish/terrain.py
new file mode 100644
index 0000000..e08f864
--- /dev/null
+++ b/gremlin-python/src/main/python/radish/terrain.py
@@ -0,0 +1,114 @@
+#
+# 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.
+#
+
+from gremlin_python.process.anonymous_traversal import traversal
+from gremlin_python.process.graph_traversal import __
+from gremlin_python.driver import serializer
+from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
+from radish import before, after, world
+
+outV = __.outV
+label = __.label
+inV = __.inV
+project = __.project
+tail = __.tail
+
+
+@before.all
+def prepare_static_traversal_source(features, marker):
+    # as the various traversal sources for testing do not change their data, there is no need to re-create remotes
+    # and client side lookup data over and over. it can be created once for all tests and be reused.
+    cache = {}
+    for graph_name in (("modern", "gmodern"), ("classic", "gclassic"), ("crew", "gcrew"), ("grateful", "ggrateful"), ("sink", "gsink")):
+        cache[graph_name[0]] = {}
+        remote = __create_remote(graph_name[1])
+        cache[graph_name[0]]["remote_conn"] = __create_remote(graph_name[1])
+        cache[graph_name[0]]["lookup_v"] = __create_lookup_v(remote)
+        cache[graph_name[0]]["lookup_e"] = __create_lookup_e(remote)
+
+    # store the cache on the global context so that remotes can be shutdown cleanly at the end of the tests
+    world.cache = cache
+
+    # iterate each feature and apply the cached remotes/lookups to each scenario context so that they are
+    # accessible to the feature steps for test logic
+    for feature in features:
+        for scenario in feature.all_scenarios:
+            scenario.context.remote_conn = {}
+            scenario.context.lookup_v = {}
+            scenario.context.lookup_e = {}
+
+            for graph_name in ("modern", "classic", "crew", "grateful", "sink"):
+                scenario.context.remote_conn[graph_name] = cache[graph_name]["remote_conn"]
+                scenario.context.lookup_v[graph_name] = cache[graph_name]["lookup_v"]
+                scenario.context.lookup_e[graph_name] = cache[graph_name]["lookup_e"]
+
+            # setup the "empty" lookups as needed
+            scenario.context.lookup_v["empty"] = {}
+            scenario.context.lookup_e["empty"] = {}
+
+
+@before.each_scenario
+def prepare_traversal_source(scenario):
+    # some tests create data - create a fresh remote to the empty graph and clear that graph prior to each test
+    remote = __create_remote("ggraph")
+    scenario.context.remote_conn["empty"] = remote
+    g = traversal().withRemote(remote)
+    g.V().drop().iterate()
+
+
+@after.each_scenario
+def close_traversal_source(scenario):
+    scenario.context.remote_conn["empty"].close()
+
+
+@after.all
+def close_static_traversal_source(features, marker):
+    for key, value in world.cache.items():
+        value["remote_conn"].close()
+
+
+def __create_remote(server_graph_name):
+    if not("serializer" in world.config.user_data):
+        raise ValueError('test configuration requires setting of --user-data="serializer={mime-type}"')
+
+    if world.config.user_data["serializer"] == "application/vnd.gremlin-v3.0+json":
+        s = serializer.GraphSONSerializersV3d0()
+    elif world.config.user_data["serializer"] == "application/vnd.graphbinary-v1.0":
+        s = serializer.GraphBinarySerializersV1()
+    else:
+        raise ValueError('serializer not found - ' + world.config.user_data["serializer"])
+
+    return DriverRemoteConnection('ws://localhost:45940/gremlin', server_graph_name, message_serializer=s)
+
+
+def __create_lookup_v(remote):
+    g = traversal().withRemote(remote)
+
+    # hold a map of name/vertex for use in asserting results
+    return g.V().group().by('name').by(tail()).next()
+
+
+def __create_lookup_e(remote):
+    g = traversal().withRemote(remote)
+
+    # hold a map of the "name"/edge for use in asserting results - "name" in this context is in the form of
+    # outgoingV-label->incomingV
+    return g.E().group(). \
+        by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + it.inVertex().value('name')", "gremlin-groovy")). \
+        by(tail()).next()
diff --git a/gremlin-python/src/main/jython/setup.cfg b/gremlin-python/src/main/python/setup.cfg
similarity index 100%
rename from gremlin-python/src/main/jython/setup.cfg
rename to gremlin-python/src/main/python/setup.cfg
diff --git a/gremlin-python/src/main/python/setup.py b/gremlin-python/src/main/python/setup.py
new file mode 100644
index 0000000..b5a5911
--- /dev/null
+++ b/gremlin-python/src/main/python/setup.py
@@ -0,0 +1,94 @@
+"""
+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.
+"""
+import codecs
+import os
+import sys
+import time
+from setuptools import setup
+
+# Folder containing the setup.py
+root = os.path.dirname(os.path.abspath(__file__))
+
+# Path to __version__ module
+version_file = os.path.join(root, 'gremlin_python', '__version__.py')
+
+# Check if this is a source distribution.
+# If not create the __version__ module containing the version
+if not os.path.exists(os.path.join(root, 'PKG-INFO')):
+    timestamp = int(os.getenv('TIMESTAMP', time.time() * 1000)) / 1000
+    fd = codecs.open(version_file, 'w', 'utf-8')
+    fd.write("'''")
+    fd.write(__doc__)
+    fd.write("'''\n")
+    fd.write('version   = %r\n' % os.getenv('VERSION', '?').replace('-SNAPSHOT', '.dev-%d' % timestamp))
+    fd.write('timestamp = %d\n' % timestamp)
+    fd.close()
+# Load version
+from gremlin_python import __version__
+
+version = __version__.version
+
+install_requires = [
+    'aenum>=1.4.5,<3.0.0',
+    'tornado>=4.4.1,<6.0',
+    'six>=1.10.0,<2.0.0',
+    'isodate>=0.6.0,<1.0.0',
+    'pyparsing>=2.4.7,<3.0.0'
+]
+
+if sys.version_info < (3, 2):
+    install_requires += ['futures>=3.0.5,<4.0.0']
+
+if sys.version_info < (3, 5):
+    install_requires += ['pyparsing>=2.4.6,<3.0.0']
+
+setup(
+    name='gremlinpython',
+    version=version,
+    packages=['gremlin_python', 'gremlin_python.driver',
+              'gremlin_python.driver.tornado', 'gremlin_python.process',
+              'gremlin_python.structure', 'gremlin_python.structure.io'],
+    license='Apache 2',
+    url='http://tinkerpop.apache.org',
+    description='Gremlin-Python for Apache TinkerPop',
+    long_description=codecs.open("README.rst", "r", "UTF-8").read(),
+    long_description_content_type='text/x-rst',
+    test_suite="tests",
+    data_files=[("", ["LICENSE", "NOTICE"])],
+    setup_requires=[
+        'pytest-runner',
+    ],
+    tests_require=[
+        'pytest>=4.6.4,<5.0.0',
+        'mock>=3.0.5,<4.0.0',
+        'radish-bdd==0.8.6',
+        'PyHamcrest>=1.9.0,<2.0.0'
+    ],
+    install_requires=install_requires,
+    extra_require={
+        'kerberos': 'kerberos>=1.3.0,<2.0.0'    # Does not install in Microsoft Windows
+    },
+    classifiers=[
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: Apache Software License",
+        "Natural Language :: English",
+        "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
+    ]
+)
diff --git a/gremlin-python/src/main/jython/tests/__init__.py b/gremlin-python/src/main/python/tests/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/__init__.py
rename to gremlin-python/src/main/python/tests/__init__.py
diff --git a/gremlin-python/src/main/python/tests/conftest.py b/gremlin-python/src/main/python/tests/conftest.py
new file mode 100644
index 0000000..a5bbbcc
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/conftest.py
@@ -0,0 +1,166 @@
+#
+# 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.
+#
+
+import concurrent.futures
+import pytest
+import socket
+
+from six.moves import queue
+
+from gremlin_python.driver.client import Client
+from gremlin_python.driver.connection import Connection
+from gremlin_python.driver import serializer
+from gremlin_python.driver.driver_remote_connection import (
+    DriverRemoteConnection)
+from gremlin_python.driver.protocol import GremlinServerWSProtocol
+from gremlin_python.driver.serializer import (
+    GraphSONMessageSerializer, GraphSONSerializersV2d0, GraphSONSerializersV3d0,
+    GraphBinarySerializersV1)
+from gremlin_python.driver.tornado.transport import TornadoTransport
+
+gremlin_server_url = 'ws://localhost:{}/gremlin'
+anonymous_url = gremlin_server_url.format(45940)
+basic_url = gremlin_server_url.format(45941)
+kerberos_url = gremlin_server_url.format(45942)
+kerberized_service = 'test-service@{}'.format(socket.gethostname())
+
+
+@pytest.fixture
+def connection(request):
+    protocol = GremlinServerWSProtocol(
+        GraphSONMessageSerializer(),
+        username='stephen', password='password')
+    executor = concurrent.futures.ThreadPoolExecutor(5)
+    pool = queue.Queue()
+    try:
+        conn = Connection(anonymous_url, 'gmodern', protocol,
+                          lambda: TornadoTransport(), executor, pool)
+    except OSError:
+        executor.shutdown()
+        pytest.skip('Gremlin Server is not running')
+    else:
+        def fin():
+            executor.shutdown()
+            conn.close()
+        request.addfinalizer(fin)
+        return conn
+
+
+@pytest.fixture
+def client(request):
+    try:
+        client = Client(anonymous_url, 'gmodern')
+    except OSError:
+        pytest.skip('Gremlin Server is not running')
+    else:
+        def fin():
+            client.close()
+        request.addfinalizer(fin)
+        return client
+
+
+@pytest.fixture(params=['basic', 'kerberos'])
+def authenticated_client(request):
+    try:
+        if request.param == 'basic':
+            client = Client(basic_url, 'gmodern', username='stephen', password='password')
+        elif request.param == 'kerberos':
+            client = Client(kerberos_url, 'gmodern', kerberized_service=kerberized_service)
+        else:
+            raise ValueError("Invalid authentication option - " + request.param)
+    except OSError:
+        pytest.skip('Gremlin Server is not running')
+    else:
+        def fin():
+            client.close()
+        request.addfinalizer(fin)
+        return client
+
+
+@pytest.fixture(params=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
+def remote_connection(request):
+    try:
+        if request.param == 'graphbinaryv1':
+            remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern',
+                                                 message_serializer=serializer.GraphBinarySerializersV1())
+        elif request.param == 'graphsonv2':
+            remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern',
+                                                 message_serializer=serializer.GraphSONSerializersV2d0())
+        elif request.param == 'graphsonv3':
+            remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern',
+                                                 message_serializer=serializer.GraphSONSerializersV3d0())
+        else:
+            raise ValueError("Invalid serializer option - " + request.param)
+    except OSError:
+        pytest.skip('Gremlin Server is not running')
+    else:
+        def fin():
+            remote_conn.close()
+        request.addfinalizer(fin)
+        return remote_conn
+
+
+@pytest.fixture(params=['basic', 'kerberos'])
+def remote_connection_authenticated(request):
+    try:
+        if request.param == 'basic':
+            remote_conn = DriverRemoteConnection(basic_url, 'gmodern',
+                                                 username='stephen', password='password',
+                                                 message_serializer=serializer.GraphSONSerializersV2d0())
+        elif request.param == 'kerberos':
+            remote_conn = DriverRemoteConnection(kerberos_url, 'gmodern', kerberized_service=kerberized_service,
+                                                 message_serializer=serializer.GraphSONSerializersV2d0())
+        else:
+            raise ValueError("Invalid authentication option - " + request.param)
+    except OSError:
+        pytest.skip('Gremlin Server is not running')
+    else:
+        def fin():
+            remote_conn.close()
+        request.addfinalizer(fin)
+        return remote_conn
+
+
+@pytest.fixture
+def remote_connection_graphsonV2(request):
+    try:
+        remote_conn = DriverRemoteConnection(anonymous_url, 'g',
+                                             message_serializer=serializer.GraphSONSerializersV2d0())
+    except OSError:
+        pytest.skip('Gremlin Server is not running')
+    else:
+        def fin():
+            remote_conn.close()
+        request.addfinalizer(fin)
+        return remote_conn
+
+
+@pytest.fixture
+def graphson_serializer_v2(request):
+    return GraphSONSerializersV2d0()
+
+
+@pytest.fixture
+def graphson_serializer_v3(request):
+    return GraphSONSerializersV3d0()
+
+
+@pytest.fixture
+def graphbinary_serializer_v1(request):
+    return GraphBinarySerializersV1()
diff --git a/gremlin-python/src/main/jython/tests/driver/__init__.py b/gremlin-python/src/main/python/tests/driver/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/driver/__init__.py
rename to gremlin-python/src/main/python/tests/driver/__init__.py
diff --git a/gremlin-python/src/main/python/tests/driver/test_client.py b/gremlin-python/src/main/python/tests/driver/test_client.py
new file mode 100644
index 0000000..792e8c2
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/driver/test_client.py
@@ -0,0 +1,325 @@
+#
+# 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.
+#
+import threading
+import uuid
+
+from gremlin_python.driver.client import Client
+from gremlin_python.driver.protocol import GremlinServerError
+from gremlin_python.driver.request import RequestMessage
+from gremlin_python.process.graph_traversal import __
+from gremlin_python.process.strategies import OptionsStrategy
+from gremlin_python.structure.graph import Graph
+
+__author__ = 'David M. Brown (davebshow@gmail.com)'
+
+
+def test_connection(connection):
+    g = Graph().traversal()
+    t = g.V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    results_set = connection.write(message).result()
+    future = results_set.all()
+    results = future.result()
+    assert len(results) == 6
+    assert isinstance(results, list)
+    assert results_set.done.done()
+    assert 'host' in results_set.status_attributes
+
+
+def test_client_simple_eval(client):
+    assert client.submit('1 + 1').all().result()[0] == 2
+
+
+def test_client_simple_eval_bindings(client):
+    assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
+
+
+def test_client_eval_traversal(client):
+    assert len(client.submit('g.V()').all().result()) == 6
+
+
+def test_client_error(client):
+    try:
+        # should fire an exception
+        client.submit('1/0').all().result()
+        assert False
+    except GremlinServerError as ex:
+        assert 'exceptions' in ex.status_attributes
+        assert 'stackTrace' in ex.status_attributes
+
+
+def test_client_connection_pool_after_error(client):
+    # Overwrite fixture with pool_size=1 client
+    client = Client('ws://localhost:45940/gremlin', 'gmodern', pool_size=1)
+
+    try:
+        # should fire an exception
+        client.submit('1/0').all().result()
+        assert False
+    except GremlinServerError as gse:
+        # expecting the pool size to be 1 again after query returned
+        assert gse.status_code == 597
+        assert client.available_pool_size == 1
+
+
+def test_client_bytecode(client):
+    g = Graph().traversal()
+    t = g.V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    result_set = client.submit(message)
+    assert len(result_set.all().result()) == 6
+
+
+def test_client_bytecode_options(client):
+    # smoke test to validate serialization of OptionsStrategy. no way to really validate this from an integration
+    # test perspective because there's no way to access the internals of the strategy via bytecode
+    g = Graph().traversal()
+    t = g.withStrategies(OptionsStrategy(options={"x": "test", "y": True})).V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    result_set = client.submit(message)
+    assert len(result_set.all().result()) == 6
+    ##
+    t = g.with_("x", "test").with_("y", True).V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    result_set = client.submit(message)
+    assert len(result_set.all().result()) == 6
+
+
+def test_iterate_result_set(client):
+    g = Graph().traversal()
+    t = g.V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 6
+
+
+def test_client_async(client):
+    g = Graph().traversal()
+    t = g.V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    future = client.submitAsync(message)
+    result_set = future.result()
+    assert len(result_set.all().result()) == 6
+
+
+def test_connection_share(client):
+    # Overwrite fixture with pool_size=1 client
+    client = Client('ws://localhost:45940/gremlin', 'gmodern', pool_size=1)
+    g = Graph().traversal()
+    t = g.V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    message2 = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    future = client.submitAsync(message)
+    future2 = client.submitAsync(message2)
+
+    result_set2 = future2.result()
+    assert len(result_set2.all().result()) == 6
+
+    # This future has to finish for the second to yield result - pool_size=1
+    assert future.done()
+    result_set = future.result()
+    assert len(result_set.all().result()) == 6
+
+
+def test_multi_conn_pool(client):
+    g = Graph().traversal()
+    t = g.V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    message2 = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    client = Client('ws://localhost:45940/gremlin', 'g', pool_size=1)
+    future = client.submitAsync(message)
+    future2 = client.submitAsync(message2)
+
+    result_set2 = future2.result()
+    assert len(result_set2.all().result()) == 6
+
+    # with connection pool `future` may or may not be done here
+    result_set = future.result()
+    assert len(result_set.all().result()) == 6
+
+
+def test_multi_thread_pool(client):
+    g = Graph().traversal()
+    traversals = [g.V(),
+                  g.V().count(),
+                  g.E(),
+                  g.E().count()
+                  ]
+    results = [[] for _ in traversals]
+
+    # Use a condition variable to synchronise a group of threads, which should also inject some
+    # non-determinism into the run-time execution order
+    condition = threading.Condition()
+
+    def thread_run(tr, result_list):
+        message = RequestMessage('traversal', 'bytecode', {'gremlin': tr.bytecode, 'aliases': {'g': 'gmodern'}})
+        with condition:
+            condition.wait(5)
+        result_set = client.submit(message)
+        for result in result_set:
+            result_list.append(result)
+
+    threads = []
+    for i in range(len(results)):
+        thread = threading.Thread(target=thread_run,
+                                  args=(traversals[i], results[i]),
+                                  name="test_multi_thread_pool_%d" % i)
+        thread.daemon = True
+        threads.append(thread)
+        thread.start()
+    with condition:
+        condition.notify_all()
+
+    for t in threads:
+        t.join(5)
+
+    assert len(results[0][0]) == 6
+    assert results[1][0][0].object == 6
+    assert len(results[2][0]) == 6
+    assert results[3][0][0].object == 6
+
+
+def test_client_bytecode_with_int(client):
+    g = Graph().traversal()
+    t = g.V().has('age', 851401972585122).count()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 1
+
+
+def test_multi_request_in_session(client):
+    # Overwrite fixture with session client
+    session_id = str(uuid.uuid4())
+    client = Client('ws://localhost:45940/gremlin', 'g', session=session_id)
+
+    assert client.submit('x = 1').all().result()[0] == 1
+    assert client.submit('x + 2').all().result()[0] == 3
+
+    client.close()
+
+    # attempt reconnect to session and make sure "x" is no longer a thing
+    client = Client('ws://localhost:45940/gremlin', 'g', session=session_id)
+    try:
+        # should fire an exception
+        client.submit('x').all().result()
+        assert False
+    except Exception:
+        assert True
+
+
+def test_client_pool_in_session(client):
+    # Overwrite fixture with pool_size=2 client
+    try:
+        # should fire an exception
+        client = Client('ws://localhost:45940/gremlin', 'g', session=str(uuid.uuid4()), pool_size=2)
+        assert False
+    except Exception:
+        assert True
+
+
+def test_big_result_set(client):
+    g = Graph().traversal()
+    t = g.inject(1).repeat(__.addV('person').property('name', __.loops())).times(20000).count()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 1
+
+    t = g.V().limit(10)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 10
+
+    t = g.V().limit(100)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 100
+
+    t = g.V().limit(1000)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 1000
+
+    t = g.V().limit(10000)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 10000
+
+
+def test_big_result_set_secure(authenticated_client):
+    g = Graph().traversal()
+    t = g.inject(1).repeat(__.addV('person').property('name', __.loops())).times(20000).count()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = authenticated_client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 1
+
+    t = g.V().limit(10)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = authenticated_client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 10
+
+    t = g.V().limit(100)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = authenticated_client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 100
+
+    t = g.V().limit(1000)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = authenticated_client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 1000
+
+    t = g.V().limit(10000)
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'g'}})
+    result_set = authenticated_client.submit(message)
+    results = []
+    for result in result_set:
+        results += result
+    assert len(results) == 10000
diff --git a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
new file mode 100644
index 0000000..309dbf4
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
@@ -0,0 +1,219 @@
+#
+# 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.
+#
+
+import pytest
+
+from gremlin_python import statics
+from gremlin_python.driver.protocol import GremlinServerError
+from gremlin_python.statics import long
+from gremlin_python.process.traversal import Traverser
+from gremlin_python.process.traversal import TraversalStrategy
+from gremlin_python.process.traversal import Bindings
+from gremlin_python.process.traversal import P, Order, T
+from gremlin_python.process.graph_traversal import __
+from gremlin_python.process.anonymous_traversal import traversal
+from gremlin_python.structure.graph import Vertex
+from gremlin_python.process.strategies import SubgraphStrategy, ReservedKeysVerificationStrategy, SeedStrategy
+from gremlin_python.structure.io.util import HashableDict
+from gremlin_python.driver.serializer import GraphSONSerializersV2d0
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+
+class TestDriverRemoteConnection(object):
+    def test_traversals(self, remote_connection):
+        statics.load_statics(globals())
+        g = traversal().withRemote(remote_connection)
+
+        assert long(6) == g.V().count().toList()[0]
+        # #
+        assert Vertex(1) == g.V(1).next()
+        assert 1 == g.V(1).id().next()
+        assert Traverser(Vertex(1)) == g.V(1).nextTraverser()
+        assert 1 == len(g.V(1).toList())
+        assert isinstance(g.V(1).toList(), list)
+        results = g.V().repeat(out()).times(2).name
+        results = results.toList()
+        assert 2 == len(results)
+        assert "lop" in results
+        assert "ripple" in results
+        # #
+        assert 10 == g.V().repeat(both()).times(5)[0:10].count().next()
+        assert 1 == g.V().repeat(both()).times(5)[0:1].count().next()
+        assert 0 == g.V().repeat(both()).times(5)[0:0].count().next()
+        assert 4 == g.V()[2:].count().next()
+        assert 2 == g.V()[:2].count().next()
+        # #
+        results = g.withSideEffect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where(P.within('a')).toList()
+        assert 2 == len(results)
+        assert 'josh' in results
+        assert 'peter' in results
+        # #
+        results = g.V().out().profile().toList()
+        assert 1 == len(results)
+        assert 'metrics' in results[0]
+        assert 'dur' in results[0]
+        # #
+        results = g.V().has('name', 'peter').as_('a').out('created').as_('b').select('a', 'b').by(
+            __.valueMap()).toList()
+        assert 1 == len(results)
+        assert 'peter' == results[0]['a']['name'][0]
+        assert 35 == results[0]['a']['age'][0]
+        assert 'lop' == results[0]['b']['name'][0]
+        assert 'java' == results[0]['b']['lang'][0]
+        assert 2 == len(results[0]['a'])
+        assert 2 == len(results[0]['b'])
+        # #
+        results = g.V(1).inject(g.V(2).next()).values('name').toList()
+        assert 2 == len(results)
+        assert 'marko' in results
+        assert 'vadas' in results
+        # #
+        results = g.V().has('person', 'name', 'marko').map(lambda: ("it.get().value('name')", "gremlin-groovy")).toList()
+        assert 1 == len(results)
+        assert 'marko' in results
+        # #
+        # this test just validates that the underscored versions of steps conflicting with Gremlin work
+        # properly and can be removed when the old steps are removed - TINKERPOP-2272
+        results = g.V().filter_(__.values('age').sum_().and_(
+            __.max_().is_(gt(0)), __.min_().is_(gt(0)))).range_(0, 1).id_().next()
+        assert 1 == results
+        # #
+        # test binding in P
+        results = g.V().has('person', 'age', Bindings.of('x', lt(30))).count().next()
+        assert 2 == results
+        # #
+        # test dict keys which can only work on GraphBinary and GraphSON3 which include specific serialization
+        # types for dict
+        if not isinstance(remote_connection._client._message_serializer, GraphSONSerializersV2d0):
+            results = g.V().has('person', 'name', 'marko').elementMap("name").groupCount().next()
+            assert {HashableDict.of({T.id: 1, T.label: 'person', 'name': 'marko'}): 1} == results
+
+    def test_lambda_traversals(self, remote_connection):
+        statics.load_statics(globals())
+        assert "remoteconnection[ws://localhost:45940/gremlin,gmodern]" == str(remote_connection)
+        g = traversal().withRemote(remote_connection)
+
+        assert 24.0 == g.withSack(1.0, lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum().next()
+        assert 24.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum().next()
+
+        assert 48.0 == g.withSack(1.0, lambda: ("x, y ->  x + y + 1", "gremlin-groovy")).V().both().sack().sum().next()
+        assert 48.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x, y ->  x + y + 1", "gremlin-groovy")).V().both().sack().sum().next()
+
+    def test_iteration(self, remote_connection):
+        statics.load_statics(globals())
+        g = traversal().withRemote(remote_connection)
+
+        t = g.V().count()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert 6 == t.next()
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+
+        t = g.V().has('name', P.within('marko', 'peter')).values('name').order()
+        assert "marko" == t.next()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert t.hasNext()
+        assert "peter" == t.next()
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+        assert not(t.hasNext())
+
+        try:
+            t.next()
+            assert False
+        except StopIteration:
+            assert True
+
+    def test_strategies(self, remote_connection):
+        statics.load_statics(globals())
+        g = traversal().withRemote(remote_connection). \
+            withStrategies(TraversalStrategy("SubgraphStrategy",
+                                             {"vertices": __.hasLabel("person"),
+                                              "edges": __.hasLabel("created")},
+                                              "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy"))
+        assert 4 == g.V().count().next()
+        assert 0 == g.E().count().next()
+        assert 1 == g.V().label().dedup().count().next()
+        assert 4 == g.V().filter(lambda: ("x -> true", "gremlin-groovy")).count().next()
+        assert "person" == g.V().label().dedup().next()
+        #
+        g = traversal().withRemote(remote_connection). \
+            withStrategies(SubgraphStrategy(vertices=__.hasLabel("person"), edges=__.hasLabel("created")))
+        assert 4 == g.V().count().next()
+        assert 0 == g.E().count().next()
+        assert 1 == g.V().label().dedup().count().next()
+        assert "person" == g.V().label().dedup().next()
+        #
+        g = traversal().withRemote(remote_connection). \
+            withStrategies(SubgraphStrategy(edges=__.hasLabel("created")))
+        assert 6 == g.V().count().next()
+        assert 4 == g.E().count().next()
+        assert 1 == g.E().label().dedup().count().next()
+        assert "created" == g.E().label().dedup().next()
+        #
+        g = g.withoutStrategies(SubgraphStrategy). \
+            withComputer(vertices=__.has("name", "marko"), edges=__.limit(0))
+        assert 1 == g.V().count().next()
+        assert 0 == g.E().count().next()
+        assert "person" == g.V().label().next()
+        assert "marko" == g.V().name.next()
+        #
+        g = traversal().withRemote(remote_connection).withComputer()
+        assert 6 == g.V().count().next()
+        assert 6 == g.E().count().next()
+        #
+        g = traversal().withRemote(remote_connection).withStrategies(SeedStrategy(12345))
+        shuffledResult = g.V().values("name").order().by(Order.shuffle).toList()
+        assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
+        assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
+        assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
+        #
+        g = traversal().withRemote(remote_connection). \
+            withStrategies(ReservedKeysVerificationStrategy(throw_exception=True))
+        try:
+            g.addV("person").property("id", "please-don't-use-id").iterate()
+            assert False
+        except GremlinServerError as gse:
+            assert gse.status_code == 500
+
+    def test_clone(self, remote_connection):
+        g = traversal().withRemote(remote_connection)
+        t = g.V().count()
+        assert 6 == t.next()
+        assert 6 == t.clone().next()
+        assert 6 == t.clone().next()
+
+    def test_authenticated(self, remote_connection_authenticated):
+        statics.load_statics(globals())
+        g = traversal().withRemote(remote_connection_authenticated)
+
+        assert long(6) == g.V().count().toList()[0]
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection_threaded.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_threaded.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection_threaded.py
rename to gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_threaded.py
diff --git a/gremlin-python/src/main/jython/tests/driver/test_serializer.py b/gremlin-python/src/main/python/tests/driver/test_serializer.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/driver/test_serializer.py
rename to gremlin-python/src/main/python/tests/driver/test_serializer.py
diff --git a/gremlin-python/src/main/jython/tests/process/__init__.py b/gremlin-python/src/main/python/tests/process/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/process/__init__.py
rename to gremlin-python/src/main/python/tests/process/__init__.py
diff --git a/gremlin-python/src/main/jython/tests/process/test_dsl.py b/gremlin-python/src/main/python/tests/process/test_dsl.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/process/test_dsl.py
rename to gremlin-python/src/main/python/tests/process/test_dsl.py
diff --git a/gremlin-python/src/main/jython/tests/process/test_strategies.py b/gremlin-python/src/main/python/tests/process/test_strategies.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/process/test_strategies.py
rename to gremlin-python/src/main/python/tests/process/test_strategies.py
diff --git a/gremlin-python/src/main/python/tests/process/test_traversal.py b/gremlin-python/src/main/python/tests/process/test_traversal.py
new file mode 100644
index 0000000..653c56a
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/process/test_traversal.py
@@ -0,0 +1,117 @@
+#
+# 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.
+#
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+from gremlin_python.structure.graph import Graph
+from gremlin_python.process.anonymous_traversal import traversal
+from gremlin_python.process.traversal import P
+from gremlin_python.process.traversal import Binding, Bindings
+from gremlin_python.process.graph_traversal import __
+
+
+class TestTraversal(object):
+    def test_bytecode(self):
+        g = traversal().withGraph(Graph())
+        bytecode = g.V().out("created").bytecode
+        assert 0 == len(bytecode.bindings.keys())
+        assert 0 == len(bytecode.source_instructions)
+        assert 2 == len(bytecode.step_instructions)
+        assert "V" == bytecode.step_instructions[0][0]
+        assert "out" == bytecode.step_instructions[1][0]
+        assert "created" == bytecode.step_instructions[1][1]
+        assert 1 == len(bytecode.step_instructions[0])
+        assert 2 == len(bytecode.step_instructions[1])
+        ##
+        bytecode = g.withSack(1).E().groupCount().by("weight").bytecode
+        assert 0 == len(bytecode.bindings.keys())
+        assert 1 == len(bytecode.source_instructions)
+        assert "withSack" == bytecode.source_instructions[0][0]
+        assert 1 == bytecode.source_instructions[0][1]
+        assert 3 == len(bytecode.step_instructions)
+        assert "E" == bytecode.step_instructions[0][0]
+        assert "groupCount" == bytecode.step_instructions[1][0]
+        assert "by" == bytecode.step_instructions[2][0]
+        assert "weight" == bytecode.step_instructions[2][1]
+        assert 1 == len(bytecode.step_instructions[0])
+        assert 1 == len(bytecode.step_instructions[1])
+        assert 2 == len(bytecode.step_instructions[2])
+        ##
+        bytecode = g.V(Bindings.of('a', [1, 2, 3])) \
+            .out(Bindings.of('b', 'created')) \
+            .where(__.in_(Bindings.of('c', 'created'), Bindings.of('d', 'knows')) \
+            .count().is_(Bindings.of('e', P.gt(2)))).bytecode
+        assert 5 == len(bytecode.bindings.keys())
+        assert [1,2,3] == bytecode.bindings['a']
+        assert 'created' == bytecode.bindings['b']
+        assert 'created' == bytecode.bindings['c']
+        assert 'knows' == bytecode.bindings['d']
+        assert P.gt(2) == bytecode.bindings['e']
+        assert Binding('b', 'created') == bytecode.step_instructions[1][1]
+        assert 'binding[b=created]' == str(bytecode.step_instructions[1][1])
+        assert isinstance(hash(bytecode.step_instructions[1][1]), int)
+
+    def test_P(self):
+        # verify that the order of operations is respected
+        assert "and(eq(a),lt(b))" == str(P.eq("a").and_(P.lt("b")))
+        assert "and(or(lt(b),gt(c)),neq(d))" == str(P.lt("b").or_(P.gt("c")).and_(P.neq("d")))
+        assert "and(or(lt(b),gt(c)),or(neq(d),gte(e)))" == str(
+            P.lt("b").or_(P.gt("c")).and_(P.neq("d").or_(P.gte("e"))))
+
+    def test_anonymous_traversal(self):
+        bytecode = __.__(1).bytecode
+        assert 0 == len(bytecode.bindings.keys())
+        assert 0 == len(bytecode.source_instructions)
+        assert 1 == len(bytecode.step_instructions)
+        assert "inject" == bytecode.step_instructions[0][0]
+        assert 1 == bytecode.step_instructions[0][1]
+        ##
+        bytecode = __.start().bytecode
+        assert 0 == len(bytecode.bindings.keys())
+        assert 0 == len(bytecode.source_instructions)
+        assert 0 == len(bytecode.step_instructions)
+
+    def test_clone_traversal(self):
+        g = traversal().withGraph(Graph())
+        original = g.V().out("created")
+        clone = original.clone().out("knows")
+        cloneClone = clone.clone().out("created")
+
+        assert 2 == len(original.bytecode.step_instructions)
+        assert 3 == len(clone.bytecode.step_instructions)
+        assert 4 == len(cloneClone.bytecode.step_instructions)
+
+        original.has("person", "name", "marko")
+        clone.V().out()
+
+        assert 3 == len(original.bytecode.step_instructions)
+        assert 5 == len(clone.bytecode.step_instructions)
+        assert 4 == len(cloneClone.bytecode.step_instructions)
+
+    def test_enforce_anonymous_child_traversal(self):
+        g = traversal().withGraph(Graph())
+        g.V(0).addE("self").to(__.V(1))
+
+        try:
+            g.V(0).addE("self").to(g.V(1))
+            assert false
+        except TypeError:
+            pass
+
+
diff --git a/gremlin-python/src/main/jython/tests/structure/__init__.py b/gremlin-python/src/main/python/tests/structure/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/structure/__init__.py
rename to gremlin-python/src/main/python/tests/structure/__init__.py
diff --git a/gremlin-python/src/main/jython/tests/structure/io/__init__.py b/gremlin-python/src/main/python/tests/structure/io/__init__.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/structure/io/__init__.py
rename to gremlin-python/src/main/python/tests/structure/io/__init__.py
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py b/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
new file mode 100644
index 0000000..d221b18
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
@@ -0,0 +1,96 @@
+'''
+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.
+'''
+
+import datetime
+import uuid
+
+from gremlin_python.driver.serializer import GraphSONSerializersV2d0
+from gremlin_python.structure.graph import Graph
+from gremlin_python.statics import *
+
+
+def test_timestamp(remote_connection):
+    g = Graph().traversal().withRemote(remote_connection)
+    ts = timestamp(1481750076295 / 1000)
+    resp = g.addV('test_vertex').property('ts', ts)
+    resp = resp.toList()
+    vid = resp[0].id
+    try:
+        ts_prop = g.V(vid).properties('ts').toList()[0]
+        assert isinstance(ts_prop.value, timestamp)
+        assert ts_prop.value == ts
+    finally:
+        g.V(vid).drop().iterate()
+
+
+def test_datetime(remote_connection):
+    g = Graph().traversal().withRemote(remote_connection)
+    dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
+    resp = g.addV('test_vertex').property('dt', dt).toList()
+    vid = resp[0].id
+    try:
+        dt_prop = g.V(vid).properties('dt').toList()[0]
+        assert isinstance(dt_prop.value, datetime.datetime)
+        assert dt_prop.value == dt
+    finally:
+        g.V(vid).drop().iterate()
+
+
+def test_uuid(remote_connection):
+    g = Graph().traversal().withRemote(remote_connection)
+    uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
+    resp = g.addV('test_vertex').property('uuid', uid).toList()
+    vid = resp[0].id
+    try:
+        uid_prop = g.V(vid).properties('uuid').toList()[0]
+        assert isinstance(uid_prop.value, uuid.UUID)
+        assert uid_prop.value == uid
+    finally:
+        g.V(vid).drop().iterate()
+
+
+def test_odd_bits(remote_connection):
+    if not isinstance(remote_connection._client._message_serializer, GraphSONSerializersV2d0):
+        g = Graph().traversal().withRemote(remote_connection)
+        char_lower = str.__new__(SingleChar, chr(78))
+        resp = g.addV('test_vertex').property('char_lower', char_lower).toList()
+        vid = resp[0].id
+        try:
+            v = g.V(vid).values('char_lower').toList()[0]
+            assert v == char_lower
+        finally:
+            g.V(vid).drop().iterate()
+
+        char_upper = str.__new__(SingleChar, chr(57344))
+        resp = g.addV('test_vertex').property('char_upper', char_upper).toList()
+        vid = resp[0].id
+        try:
+            v = g.V(vid).values('char_upper').toList()[0]
+            assert v == char_upper
+        finally:
+            g.V(vid).drop().iterate()
+                
+        dur = datetime.timedelta(seconds=1000, microseconds=1000)
+        resp = g.addV('test_vertex').property('dur', dur).toList()
+        vid = resp[0].id
+        try:
+            v = g.V(vid).values('dur').toList()[0]
+            assert v == dur
+        finally:
+            g.V(vid).drop().iterate()
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
new file mode 100644
index 0000000..cee1bb2
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
@@ -0,0 +1,221 @@
+"""
+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.
+"""
+
+import datetime
+import calendar
+import time
+import uuid
+import math
+from decimal import *
+
+from mock import Mock
+
+from gremlin_python.statics import timestamp, long, SingleByte, SingleChar, ByteBufferType
+from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
+from gremlin_python.structure.io.graphbinaryV1 import GraphBinaryWriter, GraphBinaryReader, DataType
+from gremlin_python.process.traversal import P, Barrier, Binding, Bytecode
+from gremlin_python.process.strategies import SubgraphStrategy
+from gremlin_python.process.graph_traversal import __
+
+
+class TestGraphBinaryReader(object):
+    graphbinary_reader = GraphBinaryReader()
+
+
+class TestGraphSONWriter(object):
+    graphbinary_writer = GraphBinaryWriter()
+    graphbinary_reader = GraphBinaryReader()
+
+    def test_null(self):
+        c = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(None))
+        assert c is None
+
+    def test_int(self):
+        x = 100
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_long(self):
+        x = long(100)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_float(self):
+        x = float(100.001)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+        x = float('nan')
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert math.isnan(output)
+
+        x = float('-inf')
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert math.isinf(output) and output < 0
+
+        x = float('inf')
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert math.isinf(output) and output > 0
+
+    def test_double(self):
+        x = 100.001
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_date(self):
+        x = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_timestamp(self):
+        x = timestamp(1481750076295 / 1000)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_string(self):
+        x = "serialize this!"
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_homogeneous_list(self):
+        x = ["serialize this!", "serialize that!", "serialize that!","stop telling me what to serialize"]
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_heterogeneous_list(self):
+        x = ["serialize this!", 0, "serialize that!", "serialize that!", 1, "stop telling me what to serialize", 2]
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_heterogeneous_list_with_none(self):
+        x = ["serialize this!", 0, "serialize that!", "serialize that!", 1, "stop telling me what to serialize", 2, None]
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_homogeneous_set(self):
+        x = {"serialize this!", "serialize that!", "stop telling me what to serialize"}
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_heterogeneous_set(self):
+        x = {"serialize this!", 0, "serialize that!", 1, "stop telling me what to serialize", 2}
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_dict(self):
+        x = {"yo": "what?",
+             "go": "no!",
+             "number": 123,
+             321: "crazy with the number for a key",
+             987: ["go", "deep", {"here": "!"}]}
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+        x = {"marko": [666], "noone": ["blah"]}
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+        x = {"ripple": [], "peter": ["created"], "noone": ["blah"], "vadas": [],
+             "josh": ["created", "created"], "lop": [], "marko": [666, "created", "knows", "knows"]}
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_uuid(self):
+        x = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_edge(self):
+        x = Edge(123, Vertex(1, 'person'), "developed", Vertex(10, "software"))
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+        assert x.inV == output.inV
+        assert x.outV == output.outV
+
+    def test_path(self):
+        x = Path(["x", "y", "z"], [1, 2, 3])
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_property(self):
+        x = Property("name", "stephen", None)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_vertex(self):
+        x = Vertex(123, "person")
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_vertexproperty(self):
+        x = VertexProperty(123, "name", "stephen", None)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+        
+    def test_barrier(self):
+        x = Barrier.normSack
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_binding(self):
+        x = Binding("name", "marko")
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_bytecode(self):
+        x = Bytecode()
+        x.source_instructions.append(["withStrategies", "SubgraphStrategy"])
+        x.step_instructions.append(["V", 1, 2, 3])
+        x.step_instructions.append(["out"])
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_byte(self):
+        x = int.__new__(SingleByte, 1)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_bytebuffer(self):
+        x = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_boolean(self):
+        x = True
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+        x = False
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_char(self):
+        x = str.__new__(SingleChar, chr(76))
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+        x = str.__new__(SingleChar, chr(57344))
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+
+    def test_duration(self):
+        x = datetime.timedelta(seconds=1000, microseconds=1000)
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output
+        
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
new file mode 100644
index 0000000..8cc4fb5
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
@@ -0,0 +1,518 @@
+#
+# 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.
+#
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+import datetime
+import calendar
+import json
+import uuid
+import math
+from decimal import *
+
+from mock import Mock
+
+from gremlin_python.statics import *
+from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
+from gremlin_python.structure.io.graphsonV2d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
+import gremlin_python.structure.io.graphsonV2d0
+from gremlin_python.process.traversal import P
+from gremlin_python.process.strategies import SubgraphStrategy
+from gremlin_python.process.graph_traversal import __
+
+
+class TestGraphSONReader(object):
+    graphson_reader = GraphSONReader()
+
+    def test_number_input(self):
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:Byte",
+            "@value": 1
+        }))
+        assert isinstance(x, SingleByte)
+        assert 1 == x
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Int32",
+            "@value": 31
+        }))
+        assert isinstance(x, int)
+        assert 31 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Int64",
+            "@value": 31
+        }))
+        assert isinstance(x, long)
+        assert long(31) == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Float",
+            "@value": 31.3
+        }))
+        assert isinstance(x, float)
+        assert 31.3 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": 31.2
+        }))
+        assert isinstance(x, float)
+        assert 31.2 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": "NaN"
+        }))
+        assert isinstance(x, float)
+        assert math.isnan(x)
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": "Infinity"
+        }))
+        assert isinstance(x, float)
+        assert math.isinf(x) and x > 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": "-Infinity"
+        }))
+        assert isinstance(x, float)
+        assert math.isinf(x) and x < 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": 31.2
+        }))
+        assert isinstance(x, Decimal)
+        assert Decimal(31.2) == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": 123456789987654321123456789987654321
+        }))
+        assert isinstance(x, Decimal)
+        assert Decimal('123456789987654321123456789987654321') == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": "NaN"
+        }))
+        assert isinstance(x, Decimal)
+        assert math.isnan(x)
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": "Infinity"
+        }))
+        assert isinstance(x, Decimal)
+        assert math.isinf(x) and x > 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": "-Infinity"
+        }))
+        assert isinstance(x, Decimal)
+        assert math.isinf(x) and x < 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigInteger",
+            "@value": 31
+        }))
+        assert isinstance(x, long)
+        assert 31 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigInteger",
+            "@value": 123456789987654321123456789987654321
+        }))
+        assert isinstance(x, long)
+        assert 123456789987654321123456789987654321 == x
+
+    def test_graph(self):
+        vertex = self.graphson_reader.readObject("""
+        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type":"g:Double","@value":1.0}}}]},"properties":{"name":[{"id":{"@type":"g:Int64","@value":0},"value":"marko"}],"age":[{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29}}]}}}""")
+        assert isinstance(vertex, Vertex)
+        assert "person" == vertex.label
+        assert 1 == vertex.id
+        assert isinstance(vertex.id, int)
+        assert vertex == Vertex(1)
+        ##
+        vertex = self.graphson_reader.readObject("""
+        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
+        assert isinstance(vertex, Vertex)
+        assert 45.23 == vertex.id
+        assert isinstance(vertex.id, FloatType)
+        assert "vertex" == vertex.label
+        assert vertex == Vertex(45.23)
+        ##
+        vertex_property = self.graphson_reader.readObject("""
+        {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
+        assert isinstance(vertex_property, VertexProperty)
+        assert "anId" == vertex_property.id
+        assert "aKey" == vertex_property.label
+        assert vertex_property.value
+        assert vertex_property.vertex == Vertex(9)
+        ##
+        vertex_property = self.graphson_reader.readObject("""
+        {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
+        assert isinstance(vertex_property, VertexProperty)
+        assert 1 == vertex_property.id
+        assert "name" == vertex_property.label
+        assert "marko" == vertex_property.value
+        assert vertex_property.vertex is None
+        ##
+        edge = self.graphson_reader.readObject("""
+        {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
+        # print edge
+        assert isinstance(edge, Edge)
+        assert 17 == edge.id
+        assert "knows" == edge.label
+        assert edge.inV == Vertex("x", "xLabel")
+        assert edge.outV == Vertex("y", "vertex")
+        ##
+        property = self.graphson_reader.readObject("""
+        {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
+        # print property
+        assert isinstance(property, Property)
+        assert "aKey" == property.key
+        assert 17 == property.value
+        assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
+
+    def test_path(self):
+        path = self.graphson_reader.readObject(
+            """{"@type":"g:Path","@value":{"labels":[["a"],["b","c"],[]],"objects":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}"""
+        )
+        assert isinstance(path, Path)
+        assert "path[v[1], v[3], lop]" == str(path)
+        assert Vertex(1) == path[0]
+        assert Vertex(1) == path["a"]
+        assert "lop" == path[2]
+        assert 3 == len(path)
+
+    def test_custom_mapping(self):
+
+        # extended mapping
+        class X(object):
+            pass
+
+        type_string = "test:Xtype"
+        override_string = "g:Int64"
+        serdes = Mock()
+
+        reader = GraphSONReader(deserializer_map={type_string: serdes})
+        assert type_string in reader.deserializers
+
+        # base dicts are not modified
+        assert type_string not in gremlin_python.structure.io.graphsonV2d0._deserializers
+
+        x = X()
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
+        serdes.objectify.assert_called_once_with(x, reader)
+        assert o is serdes.objectify()
+
+        # overridden mapping
+        type_string = "g:Int64"
+        serdes = Mock()
+        reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
+        assert gremlin_python.structure.io.graphsonV2d0._deserializers[type_string] is not reader.deserializers[type_string]
+
+        value = 3
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
+        serdes.objectify.assert_called_once_with(value, reader)
+        assert o is serdes.objectify()
+
+    def test_datetime(self):
+        expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
+        pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
+        ts = int(round(pts * 1000))
+        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Date", "@value": ts}))
+        assert isinstance(dt, datetime.datetime)
+        # TINKERPOP-1848
+        assert dt == expected
+
+    def test_timestamp(self):
+        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
+        assert isinstance(dt, timestamp)
+        assert float(dt) == 1481750076.295
+
+    def test_duration(self):
+        d = self.graphson_reader.readObject(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
+        assert isinstance(d, datetime.timedelta)
+        assert d == datetime.timedelta(hours=120)
+
+    def test_uuid(self):
+        prop = self.graphson_reader.readObject(
+            json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
+        assert isinstance(prop, uuid.UUID)
+        assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
+
+    def test_metrics(self):
+        prop = self.graphson_reader.readObject(
+            json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
+                {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
+                {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
+            ]}}]))
+        assert isinstance(prop, list)
+        assert prop == [{'dur': 1.468594, 'metrics': [
+                {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
+                {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
+                ]}]
+
+    def test_bytebuffer(self):
+        bb = self.graphson_reader.readObject(
+            json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
+        assert isinstance(bb, ByteBufferType)
+        assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
+
+    def test_char(self):
+        c = self.graphson_reader.readObject(json.dumps({"@type": "gx:Char", "@value": "L"}))
+        assert isinstance(c, SingleChar)
+        assert chr(76) == c
+
+    def test_null(self):
+        c = self.graphson_reader.readObject(json.dumps(None))
+        assert c is None
+
+
+class TestGraphSONWriter(object):
+    graphson_writer = GraphSONWriter()
+    graphson_reader = GraphSONReader()
+
+    def test_numbers(self):
+        assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.writeObject(int.__new__(SingleByte, 1)))
+        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
+        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(long(851401972585122)))
+        assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.writeObject(long(-2)))
+        assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.writeObject(long(-851401972585122)))
+        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
+        assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.writeObject(-1))
+        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(851401972585122))
+        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
+        assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(float('nan')))
+        assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(float('inf')))
+        assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(float('-inf')))
+        assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(Decimal('123456789987654321123456789987654321')))
+        assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(Decimal('nan')))
+        assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('inf')))
+        assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('-inf')))
+        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(long(123456789987654321123456789987654321)))
+        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(123456789987654321123456789987654321))
+        assert """true""" == self.graphson_writer.writeObject(True)
+
+    def test_P(self):
+        result = {'@type': 'g:P',
+                  '@value': {
+                      'predicate': 'and',
+                      'value': [{
+                          '@type': 'g:P',
+                          '@value': {
+                              'predicate': 'or',
+                              'value': [{
+                                  '@type': 'g:P',
+                                  '@value': {'predicate': 'lt', 'value': 'b'}
+                              },
+                                  {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
+                              ]
+                          }
+                      },
+                          {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
+
+        assert result == json.loads(
+            self.graphson_writer.writeObject(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
+
+        result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1},{"@type": "g:Int32", "@value": 2}]}}
+        assert result == json.loads(self.graphson_writer.writeObject(P.within([1, 2])))
+        assert result == json.loads(self.graphson_writer.writeObject(P.within(1, 2)))
+
+        result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1}]}}
+        assert result == json.loads(self.graphson_writer.writeObject(P.within([1])))
+        assert result == json.loads(self.graphson_writer.writeObject(P.within(1)))
+
+    def test_strategies(self):
+        # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the Gremlin traversal machine (yet)
+        assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
+            self.graphson_writer.writeObject(SubgraphStrategy))
+        assert {"@type": "g:SubgraphStrategy", "@value": {
+            "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
+            self.graphson_writer.writeObject(SubgraphStrategy(vertices=__.has("name", "marko"))))
+
+    def test_graph(self):
+        # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
+        assert {"@type": "g:Vertex", "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(self.graphson_writer.writeObject(Vertex(long(12), "person")))
+
+        assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
+                                              "outV": {"@type": "g:Int32", "@value": 0},
+                                              "outVLabel": "person",
+                                              "label": "knows",
+                                              "inV": {"@type": "g:Int32", "@value": 1},
+                                              "inVLabel": "dog"}} == json.loads(
+            self.graphson_writer.writeObject(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
+        assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
+                                                        "vertex": "stephen"}} == json.loads(
+            self.graphson_writer.writeObject(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
+
+        assert {"@type": "g:Property",
+                "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
+                                                                        "@value": {
+                                                                            "vertex": "vertexId",
+                                                                            "id": {"@type": "g:Int32", "@value": 1234},
+                                                                            "label": "aKey"}}}} == json.loads(
+            self.graphson_writer.writeObject(
+                Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
+
+        vertex = self.graphson_reader.readObject(self.graphson_writer.writeObject(Vertex(1, "person")))
+        assert 1 == vertex.id
+        assert "person" == vertex.label
+
+        edge = self.graphson_reader.readObject(
+            self.graphson_writer.writeObject(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
+        assert "knows" == edge.label
+        assert 3 == edge.id
+        assert 1 == edge.outV.id
+        assert 2 == edge.inV.id
+
+        vertex_property = self.graphson_reader.readObject(
+            self.graphson_writer.writeObject(VertexProperty(1, "age", 32, Vertex(1))))
+        assert 1 == vertex_property.id
+        assert "age" == vertex_property.key
+        assert 32 == vertex_property.value
+
+        property = self.graphson_reader.readObject(self.graphson_writer.writeObject(Property("age", 32.2, Edge(1,Vertex(2),"knows",Vertex(3)))))
+        assert "age" == property.key
+        assert 32.2 == property.value
+
+    def test_custom_mapping(self):
+        # extended mapping
+        class X(object):
+            pass
+
+        serdes = Mock()
+        writer = GraphSONWriter(serializer_map={X: serdes})
+        assert X in writer.serializers
+
+        # base dicts are not modified
+        assert X not in gremlin_python.structure.io.graphsonV2d0._serializers
+
+        obj = X()
+        d = writer.toDict(obj)
+        serdes.dictify.assert_called_once_with(obj, writer)
+        assert d is serdes.dictify()
+
+        # overridden mapping
+        serdes = Mock()
+        writer = GraphSONWriter(serializer_map={int: serdes})
+        assert gremlin_python.structure.io.graphsonV2d0._serializers[int] is not writer.serializers[int]
+
+        value = 3
+        d = writer.toDict(value)
+        serdes.dictify.assert_called_once_with(value, writer)
+        assert d is serdes.dictify()
+
+    def test_write_long(self):
+        mapping = self.graphson_writer.toDict(1)
+        assert mapping['@type'] == 'g:Int32'
+        assert mapping['@value'] == 1
+
+        mapping = self.graphson_writer.toDict(long(1))
+        assert mapping['@type'] == 'g:Int64'
+        assert mapping['@value'] == 1
+
+    def test_datetime(self):
+        expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
+        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
+        output = self.graphson_writer.writeObject(dt)
+        assert expected == output
+
+    def test_timestamp(self):
+        expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
+        ts = timestamp(1481750076295 / 1000.0)
+        output = self.graphson_writer.writeObject(ts)
+        assert expected == output
+
+    def test_duration(self):
+        expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
+        d = datetime.timedelta(hours=120)
+        output = self.graphson_writer.writeObject(d)
+        assert expected == output
+
+    def test_uuid(self):
+        expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
+        prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
+        output = self.graphson_writer.writeObject(prop)
+        assert expected == output
+
+    def test_bytebuffer(self):
+        expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
+        bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
+        output = self.graphson_writer.writeObject(bb)
+        assert expected == output
+
+    def test_char(self):
+        expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
+        c = str.__new__(SingleChar, chr(76))
+        output = self.graphson_writer.writeObject(c)
+        assert expected == output
+
+
+class TestFunctionalGraphSONIO(object):
+    """Functional IO tests"""
+
+    def test_timestamp(self, remote_connection_graphsonV2):
+        g = Graph().traversal().withRemote(remote_connection_graphsonV2)
+        ts = timestamp(1481750076295 / 1000)
+        resp = g.addV('test_vertex').property('ts', ts)
+        resp = resp.toList()
+        vid = resp[0].id
+        try:
+            ts_prop = g.V(vid).properties('ts').toList()[0]
+            assert isinstance(ts_prop.value, timestamp)
+            assert ts_prop.value == ts
+        except OSError:
+            assert False, "Error making request"
+        finally:
+            g.V(vid).drop().iterate()
+
+    def test_datetime(self, remote_connection_graphsonV2):
+        g = Graph().traversal().withRemote(remote_connection_graphsonV2)
+        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
+        resp = g.addV('test_vertex').property('dt', dt).toList()
+        vid = resp[0].id
+        try:
+            dt_prop = g.V(vid).properties('dt').toList()[0]
+            assert isinstance(dt_prop.value, datetime.datetime)
+            assert dt_prop.value == dt
+        except OSError:
+            assert False, "Error making request"
+        finally:
+            g.V(vid).drop().iterate()
+
+    def test_uuid(self, remote_connection_graphsonV2):
+        g = Graph().traversal().withRemote(remote_connection_graphsonV2)
+        uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
+        resp = g.addV('test_vertex').property('uuid', uid).toList()
+        vid = resp[0].id
+        try:
+            uid_prop = g.V(vid).properties('uuid').toList()[0]
+            assert isinstance(uid_prop.value, uuid.UUID)
+            assert uid_prop.value == uid
+        except OSError:
+            assert False, "Error making request"
+        finally:
+            g.V(vid).drop().iterate()
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
new file mode 100644
index 0000000..83aa55f
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
@@ -0,0 +1,536 @@
+#
+# 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.
+#
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+import datetime
+import calendar
+import json
+import uuid
+import math
+from decimal import *
+
+from mock import Mock
+
+from gremlin_python.statics import *
+from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
+from gremlin_python.structure.io.graphsonV3d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
+import gremlin_python.structure.io.graphsonV3d0
+from gremlin_python.process.traversal import P
+from gremlin_python.process.strategies import SubgraphStrategy
+from gremlin_python.process.graph_traversal import __
+
+
+class TestGraphSONReader(object):
+    graphson_reader = GraphSONReader()
+
+    def test_collections(self):
+        x = self.graphson_reader.readObject(
+            json.dumps({"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
+                                                      {"@type": "g:Int32", "@value": 2},
+                                                      "3"]}))
+        assert isinstance(x, list)
+        assert x[0] == 1
+        assert x[1] == 2
+        assert x[2] == "3"
+        ##
+
+        x = self.graphson_reader.readObject(
+            json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
+                                                     {"@type": "g:Int32", "@value": 2},
+                                                     "3"]}))
+        # return a set as normal
+        assert isinstance(x, set)
+        assert x == set([1, 2, "3"])
+
+        x = self.graphson_reader.readObject(
+            json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
+                                                    {"@type": "g:Int32", "@value": 2},
+                                                    {"@type": "g:Float", "@value": 2.0},
+                                                    "3"]}))
+        # coerce to list here because Java might return numerics of different types which python won't recognize
+        # see comments of TINKERPOP-1844 for more details
+        assert isinstance(x, list)
+        assert x == list([1, 2, 2.0, "3"])
+        ##
+        x = self.graphson_reader.readObject(
+            json.dumps({"@type": "g:Map",
+                        "@value": ['a', {"@type": "g:Int32", "@value": 1}, 'b', "marko"]}))
+        assert isinstance(x, dict)
+        assert x['a'] == 1
+        assert x['b'] == "marko"
+        assert len(x) == 2
+
+        # BulkSet gets coerced to a List - both have the same behavior
+        x = self.graphson_reader.readObject(
+            json.dumps({"@type": "g:BulkSet",
+                        "@value": ["marko", {"@type": "g:Int64", "@value": 1}, "josh", {"@type": "g:Int64", "@value": 3}]}))
+        assert isinstance(x, list)
+        assert len(x) == 4
+        assert x.count("marko") == 1
+        assert x.count("josh") == 3
+
+    def test_number_input(self):
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:Byte",
+            "@value": 1
+        }))
+        assert isinstance(x, SingleByte)
+        assert 1 == x
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Int32",
+            "@value": 31
+        }))
+        assert isinstance(x, int)
+        assert 31 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Int64",
+            "@value": 31
+        }))
+        assert isinstance(x, long)
+        assert long(31) == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Float",
+            "@value": 31.3
+        }))
+        assert isinstance(x, float)
+        assert 31.3 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": 31.2
+        }))
+        assert isinstance(x, float)
+        assert 31.2 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": "NaN"
+        }))
+        assert isinstance(x, float)
+        assert math.isnan(x)
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": "Infinity"
+        }))
+        assert isinstance(x, float)
+        assert math.isinf(x) and x > 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": "-Infinity"
+        }))
+        assert isinstance(x, float)
+        assert math.isinf(x) and x < 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": 31.2
+        }))
+        assert isinstance(x, Decimal)
+        assert Decimal(31.2) == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": 123456789987654321123456789987654321
+        }))
+        assert isinstance(x, Decimal)
+        assert Decimal('123456789987654321123456789987654321') == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": "NaN"
+        }))
+        assert isinstance(x, Decimal)
+        assert math.isnan(x)
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": "Infinity"
+        }))
+        assert isinstance(x, Decimal)
+        assert math.isinf(x) and x > 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigDecimal",
+            "@value": "-Infinity"
+        }))
+        assert isinstance(x, Decimal)
+        assert math.isinf(x) and x < 0
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigInteger",
+            "@value": 31
+        }))
+        assert isinstance(x, long)
+        assert 31 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "gx:BigInteger",
+            "@value": 123456789987654321123456789987654321
+        }))
+        assert isinstance(x, long)
+        assert 123456789987654321123456789987654321 == x
+
+    def test_graph(self):
+        vertex = self.graphson_reader.readObject("""
+        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type":"g:Double","@value":1.0}}}]},"properties":{"name":[{"id":{"@type":"g:Int64","@value":0},"value":"marko"}],"age":[{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29}}]}}}""")
+        assert isinstance(vertex, Vertex)
+        assert "person" == vertex.label
+        assert 1 == vertex.id
+        assert isinstance(vertex.id, int)
+        assert vertex == Vertex(1)
+        ##
+        vertex = self.graphson_reader.readObject("""
+        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
+        assert isinstance(vertex, Vertex)
+        assert 45.23 == vertex.id
+        assert isinstance(vertex.id, FloatType)
+        assert "vertex" == vertex.label
+        assert vertex == Vertex(45.23)
+        ##
+        vertex_property = self.graphson_reader.readObject("""
+        {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
+        assert isinstance(vertex_property, VertexProperty)
+        assert "anId" == vertex_property.id
+        assert "aKey" == vertex_property.label
+        assert vertex_property.value
+        assert vertex_property.vertex == Vertex(9)
+        ##
+        vertex_property = self.graphson_reader.readObject("""
+        {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
+        assert isinstance(vertex_property, VertexProperty)
+        assert 1 == vertex_property.id
+        assert "name" == vertex_property.label
+        assert "marko" == vertex_property.value
+        assert vertex_property.vertex is None
+        ##
+        edge = self.graphson_reader.readObject("""
+        {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
+        # print edge
+        assert isinstance(edge, Edge)
+        assert 17 == edge.id
+        assert "knows" == edge.label
+        assert edge.inV == Vertex("x", "xLabel")
+        assert edge.outV == Vertex("y", "vertex")
+        ##
+        property = self.graphson_reader.readObject("""
+        {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
+        # print property
+        assert isinstance(property, Property)
+        assert "aKey" == property.key
+        assert 17 == property.value
+        assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
+
+    def test_path(self):
+        path = self.graphson_reader.readObject(
+            """{"@type":"g:Path","@value":{"labels":{"@type":"g:List","@value":[{"@type":"g:Set","@value":["a"]},{"@type":"g:Set","@value":["b","c"]},{"@type":"g:Set","@value":[]}]},"objects":{"@type":"g:List","@value":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}}"""
+        )
+        assert isinstance(path, Path)
+        assert "path[v[1], v[3], lop]" == str(path)
+        assert Vertex(1) == path[0]
+        assert Vertex(1) == path["a"]
+        assert "lop" == path[2]
+        assert 3 == len(path)
+
+    def test_custom_mapping(self):
+
+        # extended mapping
+        class X(object):
+            pass
+
+        type_string = "test:Xtype"
+        override_string = "g:Int64"
+        serdes = Mock()
+
+        reader = GraphSONReader(deserializer_map={type_string: serdes})
+        assert type_string in reader.deserializers
+
+        # base dicts are not modified
+        assert type_string not in gremlin_python.structure.io.graphsonV3d0._deserializers
+
+        x = X()
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
+        serdes.objectify.assert_called_once_with(x, reader)
+        assert o is serdes.objectify()
+
+        # overridden mapping
+        type_string = "g:Int64"
+        serdes = Mock()
+        reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
+        assert gremlin_python.structure.io.graphsonV3d0._deserializers[type_string] is not reader.deserializers[
+            type_string]
+
+        value = 3
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
+        serdes.objectify.assert_called_once_with(value, reader)
+        assert o is serdes.objectify()
+
+    def test_datetime(self):
+        expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
+        pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
+        ts = int(round(pts * 1000))
+        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Date", "@value": ts}))
+        assert isinstance(dt, datetime.datetime)
+        # TINKERPOP-1848
+        assert dt == expected
+
+    def test_timestamp(self):
+        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
+        assert isinstance(dt, timestamp)
+        assert float(dt) == 1481750076.295
+
+    def test_duration(self):
+        d = self.graphson_reader.readObject(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
+        assert isinstance(d, datetime.timedelta)
+        assert d == datetime.timedelta(hours=120)
+
+    def test_uuid(self):
+        prop = self.graphson_reader.readObject(
+            json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
+        assert isinstance(prop, uuid.UUID)
+        assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
+
+    def test_metrics(self):
+        prop = self.graphson_reader.readObject(
+            json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
+                {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
+                {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
+            ]}}]))
+        assert isinstance(prop, list)
+        assert prop == [{'dur': 1.468594, 'metrics': [
+                {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
+                {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
+                ]}]
+
+    def test_bytebuffer(self):
+        bb = self.graphson_reader.readObject(
+            json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
+        assert isinstance(bb, ByteBufferType)
+        assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
+
+    def test_char(self):
+        c = self.graphson_reader.readObject(json.dumps({"@type": "gx:Char", "@value": "L"}))
+        assert isinstance(c, SingleChar)
+        assert chr(76) == c
+
+    def test_null(self):
+        c = self.graphson_reader.readObject(json.dumps(None))
+        assert c is None
+
+
+class TestGraphSONWriter(object):
+    graphson_writer = GraphSONWriter()
+    graphson_reader = GraphSONReader()
+
+    def test_collections(self):
+        assert {"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
+                                              {"@type": "g:Int32", "@value": 2},
+                                              {"@type": "g:Int32", "@value": 3}]} == json.loads(
+            self.graphson_writer.writeObject([1, 2, 3]))
+        assert {"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
+                                             {"@type": "g:Int32", "@value": 2},
+                                             {"@type": "g:Int32", "@value": 3}]} == json.loads(
+            self.graphson_writer.writeObject(set([1, 2, 3, 3])))
+        assert {"@type": "g:Map",
+                "@value": ['a', {"@type": "g:Int32", "@value": 1}]} == json.loads(
+            self.graphson_writer.writeObject({'a': 1}))
+
+    def test_numbers(self):
+        assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.writeObject(int.__new__(SingleByte, 1)))
+        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
+        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(long(851401972585122)))
+        assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.writeObject(long(-2)))
+        assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.writeObject(long(-851401972585122)))
+        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
+        assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.writeObject(-1))
+        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(851401972585122))
+        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
+        assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(float('nan')))
+        assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(float('inf')))
+        assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(float('-inf')))
+        assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(Decimal('123456789987654321123456789987654321')))
+        assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(Decimal('nan')))
+        assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('inf')))
+        assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('-inf')))
+        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(long(123456789987654321123456789987654321)))
+        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(123456789987654321123456789987654321))
+        assert """true""" == self.graphson_writer.writeObject(True)
+
+    def test_P(self):
+        result = {'@type': 'g:P',
+                  '@value': {
+                      'predicate': 'and',
+                      'value': [{
+                          '@type': 'g:P',
+                          '@value': {
+                              'predicate': 'or',
+                              'value': [{
+                                  '@type': 'g:P',
+                                  '@value': {'predicate': 'lt', 'value': 'b'}
+                              },
+                                  {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
+                              ]
+                          }
+                      },
+                          {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
+
+        assert result == json.loads(
+            self.graphson_writer.writeObject(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
+
+        result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
+            {"@type": "g:Int32", "@value": 1}, {"@type": "g:Int32", "@value": 2}]}}}
+        assert result == json.loads(self.graphson_writer.writeObject(P.within([1, 2])))
+        assert result == json.loads(self.graphson_writer.writeObject(P.within(1, 2)))
+
+        result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
+            {"@type": "g:Int32", "@value": 1}]}}}
+        assert result == json.loads(self.graphson_writer.writeObject(P.within([1])))
+        assert result == json.loads(self.graphson_writer.writeObject(P.within(1)))
+
+    def test_strategies(self):
+        # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the 
+        # Gremlin traversal machine (yet)
+        assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
+            self.graphson_writer.writeObject(SubgraphStrategy))
+        assert {"@type": "g:SubgraphStrategy", "@value": {
+            "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
+            self.graphson_writer.writeObject(SubgraphStrategy(vertices=__.has("name", "marko"))))
+
+    def test_graph(self):
+        # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
+        assert {"@type": "g:Vertex",
+                "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(
+            self.graphson_writer.writeObject(Vertex(long(12), "person")))
+
+        assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
+                                              "outV": {"@type": "g:Int32", "@value": 0},
+                                              "outVLabel": "person",
+                                              "label": "knows",
+                                              "inV": {"@type": "g:Int32", "@value": 1},
+                                              "inVLabel": "dog"}} == json.loads(
+            self.graphson_writer.writeObject(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
+        assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
+                                                        "vertex": "stephen"}} == json.loads(
+            self.graphson_writer.writeObject(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
+
+        assert {"@type": "g:Property",
+                "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
+                                                                        "@value": {
+                                                                            "vertex": "vertexId",
+                                                                            "id": {"@type": "g:Int32", "@value": 1234},
+                                                                            "label": "aKey"}}}} == json.loads(
+            self.graphson_writer.writeObject(
+                Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
+
+        vertex = self.graphson_reader.readObject(self.graphson_writer.writeObject(Vertex(1, "person")))
+        assert 1 == vertex.id
+        assert "person" == vertex.label
+
+        edge = self.graphson_reader.readObject(
+            self.graphson_writer.writeObject(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
+        assert "knows" == edge.label
+        assert 3 == edge.id
+        assert 1 == edge.outV.id
+        assert 2 == edge.inV.id
+
+        vertex_property = self.graphson_reader.readObject(
+            self.graphson_writer.writeObject(VertexProperty(1, "age", 32, Vertex(1))))
+        assert 1 == vertex_property.id
+        assert "age" == vertex_property.key
+        assert 32 == vertex_property.value
+
+        property = self.graphson_reader.readObject(self.graphson_writer.writeObject(Property("age", 32.2, Edge(1,Vertex(2),"knows",Vertex(3)))))
+        assert "age" == property.key
+        assert 32.2 == property.value
+
+    def test_custom_mapping(self):
+        # extended mapping
+        class X(object):
+            pass
+
+        serdes = Mock()
+        writer = GraphSONWriter(serializer_map={X: serdes})
+        assert X in writer.serializers
+
+        # base dicts are not modified
+        assert X not in gremlin_python.structure.io.graphsonV3d0._serializers
+
+        obj = X()
+        d = writer.toDict(obj)
+        serdes.dictify.assert_called_once_with(obj, writer)
+        assert d is serdes.dictify()
+
+        # overridden mapping
+        serdes = Mock()
+        writer = GraphSONWriter(serializer_map={int: serdes})
+        assert gremlin_python.structure.io.graphsonV3d0._serializers[int] is not writer.serializers[int]
+
+        value = 3
+        d = writer.toDict(value)
+        serdes.dictify.assert_called_once_with(value, writer)
+        assert d is serdes.dictify()
+
+    def test_write_long(self):
+        mapping = self.graphson_writer.toDict(1)
+        assert mapping['@type'] == 'g:Int32'
+        assert mapping['@value'] == 1
+
+        mapping = self.graphson_writer.toDict(long(1))
+        assert mapping['@type'] == 'g:Int64'
+        assert mapping['@value'] == 1
+
+    def test_datetime(self):
+        expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
+        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
+        output = self.graphson_writer.writeObject(dt)
+        assert expected == output
+
+    def test_timestamp(self):
+        expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
+        ts = timestamp(1481750076295 / 1000.0)
+        output = self.graphson_writer.writeObject(ts)
+        assert expected == output
+
+    def test_duration(self):
+        expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
+        d = datetime.timedelta(hours=120)
+        output = self.graphson_writer.writeObject(d)
+        assert expected == output
+
+    def test_uuid(self):
+        expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
+        prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
+        output = self.graphson_writer.writeObject(prop)
+        assert expected == output
+
+    def test_bytebuffer(self):
+        expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
+        bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
+        output = self.graphson_writer.writeObject(bb)
+        assert expected == output
+
+    def test_char(self):
+        expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
+        c = str.__new__(SingleChar, chr(76))
+        output = self.graphson_writer.writeObject(c)
+        assert expected == output
diff --git a/gremlin-python/src/main/python/tests/structure/test_graph.py b/gremlin-python/src/main/python/tests/structure/test_graph.py
new file mode 100644
index 0000000..0937e39
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/structure/test_graph.py
@@ -0,0 +1,111 @@
+#
+# 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.
+#
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+from gremlin_python.statics import long
+from gremlin_python.structure.graph import Edge
+from gremlin_python.structure.graph import Property
+from gremlin_python.structure.graph import Vertex
+from gremlin_python.structure.graph import VertexProperty
+from gremlin_python.structure.graph import Path
+
+
+class TestGraph(object):
+    def test_graph_objects(self):
+        vertex = Vertex(1)
+        assert "v[1]" == str(vertex)
+        assert "vertex" == vertex.label
+        assert "person" == Vertex(1, "person").label
+        assert vertex == Vertex(1)
+        #
+        edge = Edge(2, Vertex(1), "said", Vertex("hello", "phrase"))
+        assert "e[2][1-said->hello]" == str(edge)
+        assert Vertex(1) == edge.outV
+        assert Vertex("hello") == edge.inV
+        assert "said" == edge.label
+        assert "phrase" == edge.inV.label
+        assert edge.inV != edge.outV
+        #
+        vertex_property = VertexProperty(long(24), "name", "marko", Vertex(1))
+        assert "vp[name->marko]" == str(vertex_property)
+        assert "name" == vertex_property.label
+        assert "name" == vertex_property.key
+        assert "marko" == vertex_property.value
+        assert long(24) == vertex_property.id
+        assert Vertex(1) == vertex_property.vertex
+        assert isinstance(vertex_property.id, long)
+        assert vertex_property == VertexProperty(long(24), "name", "marko", Vertex(1))
+        #
+        property = Property("age", 29, Vertex(1))
+        assert "p[age->29]" == str(property)
+        assert "age" == property.key
+        assert 29 == property.value
+        assert Vertex(1) == property.element
+        assert isinstance(property.value, int)
+        assert property == Property("age", 29, Vertex(1))
+        #
+        for i in [vertex, edge, vertex_property, property]:
+            for j in [vertex, edge, vertex_property, property]:
+                if type(i) != type(j):
+                    assert i != j
+                else:
+                    assert i == j
+                    assert i.__hash__() == hash(i)
+
+    def test_path(self):
+        path = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
+        assert "path[1, v[1], hello]" == str(path)
+        assert 1 == path["a"]
+        assert Vertex(1) == path["c"]
+        assert [1, Vertex(1)] == path["b"]
+        assert path[0] == 1
+        assert path[1] == Vertex(1)
+        assert path[2] == "hello"
+        assert 3 == len(path)
+        assert "hello" in path
+        assert "goodbye" not in path
+        assert Vertex(1) in path
+        assert Vertex(123) not in path
+        #
+        try:
+            temp = path[3]
+            raise Exception("Accessing beyond the list index should throw an index error")
+        except IndexError:
+            pass
+        #
+        try:
+            temp = path["zz"]
+            raise Exception("Accessing nothing should throw a key error")
+        except KeyError:
+            pass
+        #
+        try:
+            temp = path[1:2]
+            raise Exception("Accessing using slices should throw a type error")
+        except TypeError:
+            pass
+        #
+        assert path == path
+        assert hash(path) == hash(path)
+        path2 = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
+        assert path == path2
+        assert hash(path) == hash(path2)
+        assert path != Path([set(["a"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
+        assert path != Path([set(["a", "b"]), set(["c", "b"]), set([])], [3, Vertex(1), "hello"])
diff --git a/gremlin-python/src/main/jython/tests/test_statics.py b/gremlin-python/src/main/python/tests/test_statics.py
similarity index 100%
rename from gremlin-python/src/main/jython/tests/test_statics.py
rename to gremlin-python/src/main/python/tests/test_statics.py
diff --git a/gremlin-python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/gremlin-python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
deleted file mode 100644
index 3dda102..0000000
--- a/gremlin-python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-#  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.
-#
-
-org.apache.tinkerpop.gremlin.python.jsr223.GremlinJythonScriptEngineFactory
\ No newline at end of file
diff --git a/gremlin-python/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory b/gremlin-python/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
deleted file mode 100644
index 92f4825..0000000
--- a/gremlin-python/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.tinkerpop.gremlin.python.jsr223.GremlinJythonScriptEngineFactory
\ No newline at end of file
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java
deleted file mode 100644
index 2c4e5bc..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.jsr223.DefaultGremlinScriptEngineManager;
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineManager;
-import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.HashSet;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Ignore
-public class GremlinJythonScriptEngineTest {
-
-    @Test
-    public void shouldGetEngineByName() throws Exception {
-        final ScriptEngine engine = new DefaultGremlinScriptEngineManager().getEngineByName("gremlin-jython");
-        assertNotNull(engine);
-        assertTrue(engine instanceof GremlinJythonScriptEngine);
-        assertEquals(3, engine.eval("1+2"));
-    }
-
-    @Test
-    public void shouldHaveCoreImports() throws Exception {
-        final ScriptEngine engine = new DefaultGremlinScriptEngineManager().getEngineByName("gremlin-jython");
-        assertThat(engine.eval("Graph"), instanceOf(Class.class));
-        assertThat(engine.eval("__"), instanceOf(Class.class));
-        assertThat(engine.eval("T"), instanceOf(Class.class));
-        assertThat(engine.eval("label"), instanceOf(T.class));
-        assertThat(engine.eval("T.label"), instanceOf(T.class));
-        assertEquals(SackFunctions.Barrier.class, engine.eval("Barrier"));
-        assertEquals(SackFunctions.Barrier.normSack, engine.eval("Barrier.normSack"));
-        assertEquals(Column.class, engine.eval("Column"));
-        assertEquals(Column.values, engine.eval("Column.valueOf(\'values\')"));
-        assertEquals(VertexProperty.Cardinality.class, engine.eval("Cardinality"));
-        assertEquals(VertexProperty.Cardinality.single, engine.eval("Cardinality.valueOf(\'single\')"));
-        assertTrue(engine.eval("out()") instanceof GraphTraversal);
-        assertTrue(engine.eval("__.out()") instanceof GraphTraversal);
-        assertTrue(engine.eval("__.property(VertexProperty.Cardinality.single, 'name','marko')") instanceof GraphTraversal);
-        assertTrue(engine.eval("__.property(Cardinality.single, 'name','marko')") instanceof GraphTraversal);
-    }
-
-
-    @Test
-    public void shouldSupportJavaBasedGraphTraversal() throws Exception {
-        final ScriptEngine engine = new DefaultGremlinScriptEngineManager().getEngineByName("gremlin-jython");
-        engine.getBindings(ScriptContext.ENGINE_SCOPE).put("graph", TinkerFactory.createModern());
-        engine.eval("g = graph.traversal()");
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(out()).times(2).values('name').toSet()"));
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).values('name').toSet()"));
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(out()).times(2).name.toSet()"));
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).name.toSet()"));
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2)[0:2].name.toSet()"));
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).name[0:3].toSet()"));
-    }
-
-    @Test
-    public void shouldSupportSugarMethods() throws Exception {
-        final ScriptEngine engine = new DefaultGremlinScriptEngineManager().getEngineByName("gremlin-jython");
-        engine.getBindings(ScriptContext.ENGINE_SCOPE).put("graph", TinkerFactory.createModern());
-        engine.eval("g = graph.traversal()");
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2)[0:2].name.toSet()"));
-        assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).name[0:3].toSet()"));
-        assertEquals(BigInteger.valueOf(1), engine.eval("g.V().repeat(__.out()).times(2).name[0:1].count().next()"));
-        assertEquals(BigInteger.valueOf(1), engine.eval("g.V().repeat(__.out()).times(2).name[0].count().next()"));
-        assertEquals(BigInteger.valueOf(0), engine.eval("g.V().repeat(__.out()).times(2).name[3].count().next()"));
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
deleted file mode 100644
index bfbd8c4..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.jsr223.ScriptEngineCache;
-import org.python.jsr223.PyScriptEngine;
-
-import javax.script.ScriptException;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class JythonScriptEngineSetup {
-
-    private JythonScriptEngineSetup() {
-    }
-
-    public static void setup() {
-        setup((PyScriptEngine) ScriptEngineCache.get("jython"));
-    }
-
-    public static PyScriptEngine setup(final PyScriptEngine jythonEngine) {
-        try {
-            jythonEngine.eval("import gremlin_python.statics");
-            jythonEngine.eval("from gremlin_python.process.traversal import *");
-            jythonEngine.eval("from gremlin_python.process.graph_traversal import *");
-            jythonEngine.eval("from gremlin_python.process.graph_traversal import __");
-            // jythonEngine.eval("from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection");
-            jythonEngine.eval("from gremlin_python.process.traversal import Bytecode");
-            jythonEngine.eval("from gremlin_python.structure.graph import Graph");
-            jythonEngine.eval("from gremlin_python.structure.graph import Vertex");
-            jythonEngine.eval("from gremlin_python.structure.graph import Edge");
-            jythonEngine.eval("from gremlin_python.structure.graph import VertexProperty");
-            jythonEngine.eval("from gremlin_python.structure.graph import Property");
-            jythonEngine.eval("import gremlin_python.structure.io.graphsonV2d0");
-            jythonEngine.eval("import gremlin_python.structure.io.graphsonV3d0");
-            jythonEngine.eval("graphsonV2d0_reader = gremlin_python.structure.io.graphsonV2d0.GraphSONReader()");
-            jythonEngine.eval("graphsonV2d0_writer = gremlin_python.structure.io.graphsonV2d0.GraphSONWriter()");
-            jythonEngine.eval("graphsonV3d0_reader = gremlin_python.structure.io.graphsonV3d0.GraphSONReader()");
-            jythonEngine.eval("graphsonV3d0_writer = gremlin_python.structure.io.graphsonV3d0.GraphSONWriter()");
-            return jythonEngine;
-        } catch (final ScriptException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java
deleted file mode 100644
index 5e9b31a..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class JythonTranslatorTest {
-
-    @Test
-    public void shouldSupportStringSupplierLambdas() throws Exception {
-        GraphTraversalSource g = TinkerFactory.createModern().traversal();
-        g = g.withStrategies(new TranslationStrategy(g, JythonTranslator.of("g"), false));
-        final GraphTraversal.Admin<Vertex, Integer> t = g.withSideEffect("lengthSum", 0).withSack(1)
-                .V()
-                .filter(Lambda.predicate("x : x.get().label() == 'person'"))
-                .flatMap(Lambda.function("lambda x : x.get().vertices(Direction.OUT)"))
-                .map(Lambda.<Traverser<Object>, Integer>function("lambda x : len(x.get().value('name'))"))
-                .sideEffect(Lambda.consumer(" x : x.sideEffects(\"lengthSum\", x.sideEffects('lengthSum') + x.get())    "))
-                .order().by(Lambda.comparator("  lambda a,b : 0 if a == b else 1 if a > b else -1"))
-                .sack(Lambda.biFunction("lambda a,b : a + b"))
-                .asAdmin();
-        final List<Integer> sacks = new ArrayList<>();
-        final List<Integer> lengths = new ArrayList<>();
-        while (t.hasNext()) {
-            final Traverser.Admin<Integer> traverser = t.nextTraverser();
-            sacks.add(traverser.sack());
-            lengths.add(traverser.get());
-        }
-        assertFalse(t.hasNext());
-        //
-        assertEquals(6, lengths.size());
-        assertEquals(3, lengths.get(0).intValue());
-        assertEquals(3, lengths.get(1).intValue());
-        assertEquals(3, lengths.get(2).intValue());
-        assertEquals(4, lengths.get(3).intValue());
-        assertEquals(5, lengths.get(4).intValue());
-        assertEquals(6, lengths.get(5).intValue());
-        ///
-        assertEquals(6, sacks.size());
-        assertEquals(4, sacks.get(0).intValue());
-        assertEquals(4, sacks.get(1).intValue());
-        assertEquals(4, sacks.get(2).intValue());
-        assertEquals(5, sacks.get(3).intValue());
-        assertEquals(6, sacks.get(4).intValue());
-        assertEquals(7, sacks.get(5).intValue());
-        //
-        assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
-    }
-
-    @Test
-    public void shouldHaveValidToString() {
-        assertEquals("translator[h:gremlin-jython]", JythonTranslator.of("h").toString());
-    }
-
-    @Test
-    public void shouldTranslateToJythonAndNotPython() throws Exception {
-        // the jython translation bind "g" to java classes and thus does not require the strict python syntax which
-        // converts steps like as() to as_(). if those steps are converted then the traversal does not evaluate
-        // properly in the python engine. not much of an assertion here to worry about - just need to ensure that
-        // the traversal with such steps evaluates to success
-        GraphTraversalSource g = TinkerFactory.createModern().traversal();
-        g = g.withStrategies(new TranslationStrategy(g, JythonTranslator.of("g"), false));
-        final List<Object> o = g.V().has("name").
-                match(__.as("x").label().as("lbl"),
-                        __.as("x").id().as("id")).
-                select("lbl", "id").
-                                 map(Lambda.function("lambda x: type(x.get())")).toList();
-
-        assertEquals(6, o.size());
-    }
-
-    @Test
-    @Ignore("TINKERPOP-1898 - ultimately seems to be a problem with jython and varargs - doesn't act consistently")
-    public void shouldTranslateToJythonWhenUsingLambdasAndStrategies() throws Exception {
-        // the jython translation kicks in when you add a lambda so ensure that it translates when strategies are
-        // present
-        GraphTraversalSource g = TinkerFactory.createModern().traversal();
-        g = g.withStrategies(new TranslationStrategy(g, JythonTranslator.of("g"), false));
-        final List<Object> o = g.withStrategies(ReadOnlyStrategy.instance(),
-                                                SubgraphStrategy.build().checkAdjacentVertices(false).vertices(hasLabel("person")).create()).
-                                 V().has("name").map(Lambda.function("lambda x: type(x.get())")).toList();
-
-        assertEquals(4, o.size());
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonComputerProvider.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonComputerProvider.java
deleted file mode 100644
index 7ccc4c6..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonComputerProvider.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.GraphProvider;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@GraphProvider.Descriptor(computer = TinkerGraphComputer.class)
-public class PythonComputerProvider extends PythonProvider {
-
-    public GraphTraversalSource traversal(final Graph graph) {
-        return super.traversal(graph).withComputer();
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java
deleted file mode 100644
index 6c77867..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator;
-import org.apache.tinkerpop.gremlin.jsr223.ScriptEngineCache;
-import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.Translator;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.util.BytecodeHelper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONReader;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV3d0;
-import org.apache.tinkerpop.shaded.jackson.core.JsonFactory;
-import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-final class PythonGraphSONJavaTranslator<S extends TraversalSource, T extends Traversal.Admin<?, ?>> implements Translator.StepTranslator<S, T> {
-
-    private final boolean IS_TESTING = Boolean.valueOf(System.getProperty("is.testing", "false"));
-    private final PythonTranslator pythonTranslator;
-    private final JavaTranslator<S, T> javaTranslator;
-    private final GraphSONReader reader;
-    private final GraphSONWriter writer;
-    private final GraphSONVersion version;
-
-    public PythonGraphSONJavaTranslator(final PythonTranslator pythonTranslator, final JavaTranslator<S, T> javaTranslator, final GraphSONVersion version) {
-        this.pythonTranslator = pythonTranslator;
-        this.javaTranslator = javaTranslator;
-        this.version = version;
-        this.reader = GraphSONReader.build().mapper(
-                GraphSONMapper.build().addCustomModule(version.equals(GraphSONVersion.V2_0) ?
-                        GraphSONXModuleV2d0.build().create(false) :
-                        GraphSONXModuleV3d0.build().create(false))
-                        .version(version).create()).create();
-        this.writer = GraphSONWriter.build().mapper(
-                GraphSONMapper.build().addCustomModule(version.equals(GraphSONVersion.V2_0) ?
-                        GraphSONXModuleV2d0.build().create(false) :
-                        GraphSONXModuleV3d0.build().create(false))
-                        .version(version).create()).create();
-    }
-
-    @Override
-    public S getTraversalSource() {
-        return this.javaTranslator.getTraversalSource();
-    }
-
-    @Override
-    public String getTargetLanguage() {
-        return this.javaTranslator.getTargetLanguage();
-    }
-
-    @Override
-    public T translate(final Bytecode bytecode) {
-        try {
-            final ScriptEngine jythonEngine = ScriptEngineCache.get("jython");
-            final Bindings bindings = jythonEngine.createBindings();
-            bindings.putAll(jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE));
-            bindings.put(this.pythonTranslator.getTraversalSource(), jythonEngine.eval("Graph().traversal()"));
-            bindings.putAll(bytecode.getBindings());
-            final String translatedGraphSONBytecode = jythonEngine.eval((this.version.equals(GraphSONVersion.V2_0) ?
-                    "graphsonV2d0_writer" :
-                    "graphsonV3d0_writer") +
-                    ".writeObject(" + this.pythonTranslator.translate(bytecode) + ")", bindings).toString();
-            if (IS_TESTING) {
-                // verify that the GraphSON sent to Python is the same as the GraphSON returned by Python
-                final ByteArrayOutputStream output = new ByteArrayOutputStream();
-                BytecodeHelper.removeBindings(bytecode); // this is because bindings are variables that get converted to values at translation
-                BytecodeHelper.detachElements(bytecode); // this is to get the minimal necessary representation
-                this.writer.writeObject(output, bytecode);
-                final String originalGraphSONBytecode = new String(output.toByteArray());
-                final ObjectMapper mapper = new ObjectMapper(new JsonFactory());
-                // System.out.println(originalGraphSONBytecode + "\n" + translatedGraphSONBytecode + "\n\n");
-                final Map<String, Object> original = mapper.readValue(originalGraphSONBytecode, Map.class);
-                final Map<String, Object> translated = mapper.readValue(translatedGraphSONBytecode, Map.class);
-                assertEquals(originalGraphSONBytecode.length(), translatedGraphSONBytecode.length());
-                assertEquals(original, translated);
-            }
-            return this.javaTranslator.translate(this.reader.readObject(new ByteArrayInputStream(translatedGraphSONBytecode.getBytes()), Bytecode.class));
-
-        } catch (final Exception e) {
-            throw new IllegalArgumentException(e.getMessage(), e);
-        }
-
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGremlinScriptEngineTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGremlinScriptEngineTest.java
deleted file mode 100644
index 9313717..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGremlinScriptEngineTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineSuite;
-import org.apache.tinkerpop.gremlin.jsr223.ScriptEngineToTest;
-import org.junit.Ignore;
-import org.junit.runner.RunWith;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@Ignore
-@RunWith(GremlinScriptEngineSuite.class)
-@ScriptEngineToTest(scriptEngineName = "gremlin-jython")
-public class PythonGremlinScriptEngineTest {
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProcessComputerTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProcessComputerTest.java
deleted file mode 100644
index fc53bbd..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProcessComputerTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.process.ProcessComputerSuite;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import org.junit.Ignore;
-import org.junit.runner.RunWith;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Ignore
-@RunWith(ProcessComputerSuite.class)
-@GraphProviderClass(provider = PythonComputerProvider.class, graph = TinkerGraph.class)
-public class PythonProcessComputerTest {
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProcessStandardTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProcessStandardTest.java
deleted file mode 100644
index 21bfb78..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProcessStandardTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import org.junit.Ignore;
-import org.junit.runner.RunWith;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Ignore
-@RunWith(ProcessStandardSuite.class)
-@GraphProviderClass(provider = PythonProvider.class, graph = TinkerGraph.class)
-public class PythonProcessStandardTest {
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java
deleted file mode 100644
index 345aa65..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- *  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.python.jsr223;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.AbstractGraphProvider;
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
-import org.apache.tinkerpop.gremlin.TestHelper;
-import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator;
-import org.apache.tinkerpop.gremlin.jsr223.ScriptEngineCache;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerEdge;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerElement;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphVariables;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerProperty;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty;
-
-import javax.script.ScriptException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ProgramTest",
-        method = "*",
-        reason = "Reason requires investigation")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionTest",
-        method = "*",
-        reason = "Reason requires investigation")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionComputerTest",
-        method = "*",
-        reason = "Reason requires investigation")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategyProcessTest",
-        method = "*",
-        reason = "Strategy not properly supported by Bytecode based traversals")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategyProcessTest",
-        method = "*",
-        reason = "Strategy not properly supported by Bytecode based traversals")
-public class PythonProvider extends AbstractGraphProvider {
-
-    protected static final boolean IMPORT_STATICS = new Random().nextBoolean();
-
-
-    static {
-        JythonScriptEngineSetup.setup();
-    }
-
-    private static final Set<Class> IMPLEMENTATION = new HashSet<Class>() {{
-        add(TinkerEdge.class);
-        add(TinkerElement.class);
-        add(TinkerGraph.class);
-        add(TinkerGraphVariables.class);
-        add(TinkerProperty.class);
-        add(TinkerVertex.class);
-        add(TinkerVertexProperty.class);
-    }};
-
-    @Override
-    public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName,
-                                                    final LoadGraphWith.GraphData loadGraphWith) {
-        final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith);
-        final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromGraphData(loadGraphWith) : idManager).name();
-        return new HashMap<String, Object>() {{
-            put(Graph.GRAPH, TinkerGraph.class.getName());
-            put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_ID_MANAGER, idMaker);
-            put(TinkerGraph.GREMLIN_TINKERGRAPH_EDGE_ID_MANAGER, idMaker);
-            put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, idMaker);
-            if (loadGraphWith == LoadGraphWith.GraphData.CREW)
-                put(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name());
-        }};
-    }
-
-    @Override
-    public void clear(final Graph graph, final Configuration configuration) throws Exception {
-        if (graph != null) graph.close();
-    }
-
-    @Override
-    public Set<Class> getImplementations() {
-        return IMPLEMENTATION;
-    }
-
-    /**
-     * Test that load with specific graph data can be configured with a specific id manager as the data type to
-     * be used in the test for that graph is known.
-     */
-    protected TinkerGraph.DefaultIdManager selectIdMakerFromGraphData(final LoadGraphWith.GraphData loadGraphWith) {
-        if (null == loadGraphWith) return TinkerGraph.DefaultIdManager.ANY;
-        if (loadGraphWith.equals(LoadGraphWith.GraphData.CLASSIC))
-            return TinkerGraph.DefaultIdManager.INTEGER;
-        else if (loadGraphWith.equals(LoadGraphWith.GraphData.MODERN))
-            return TinkerGraph.DefaultIdManager.INTEGER;
-        else if (loadGraphWith.equals(LoadGraphWith.GraphData.CREW))
-            return TinkerGraph.DefaultIdManager.INTEGER;
-        else if (loadGraphWith.equals(LoadGraphWith.GraphData.GRATEFUL))
-            return TinkerGraph.DefaultIdManager.INTEGER;
-        else
-            throw new IllegalStateException(String.format("Need to define a new %s for %s", TinkerGraph.IdManager.class.getName(), loadGraphWith.name()));
-    }
-
-    /////////////////////////////
-    /////////////////////////////
-    /////////////////////////////
-
-    @Override
-    public GraphTraversalSource traversal(final Graph graph) {
-        if ((Boolean) graph.configuration().getProperty("skipTest"))
-            return graph.traversal();
-            //throw new VerificationException("This test current does not work with Gremlin-Python", EmptyTraversal.instance());
-        else {
-            try {
-                ScriptEngineCache.get("jython").eval(IMPORT_STATICS ?
-                        "statics.load_statics(globals())" :
-                        "statics.unload_statics(globals())");
-            } catch (final ScriptException e) {
-                throw new IllegalStateException(e.getMessage(), e);
-            }
-            final GraphTraversalSource g = graph.traversal();
-            return g.withStrategies(new TranslationStrategy(g,
-                    new PythonGraphSONJavaTranslator<>(
-                            PythonTranslator.of("g", IMPORT_STATICS),
-                            JavaTranslator.of(g),
-                            TestHelper.RANDOM.nextBoolean() ? GraphSONVersion.V2_0 : GraphSONVersion.V3_0), true));
-        }
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java
deleted file mode 100644
index d1e37b6..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *  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.python.structure.io.graphson;
-
-import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.python.jsr223.JythonScriptEngineSetup;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.python.jsr223.PyScriptEngine;
-
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Ignore
-public class GraphSONReaderTest {
-
-    private static final Set<GraphSONVersion> VERSIONS = new HashSet<>(Arrays.asList(GraphSONVersion.V2_0, GraphSONVersion.V3_0));
-    private static final GraphTraversalSource g = TinkerFactory.createModern().traversal();
-
-    @Test
-    public void shouldDeserializeGraphObjects() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_reader = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_reader" : "graphsonV3d0_reader"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            final Vertex vertex = g.V(1).next();
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(vertex));
-            assertEquals(vertex.toString(), jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),Vertex)"));
-            assertEquals("person", jythonEngine.eval("graphson_reader.readObject(x).label"));
-            assertEquals(1, jythonEngine.eval("graphson_reader.readObject(x).id"));
-            //
-            final Edge edge = g.V(1).outE("created").next();
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(edge));
-            assertEquals(edge.toString(), jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),Edge)"));
-            assertEquals("created", jythonEngine.eval("graphson_reader.readObject(x).label"));
-            //
-            final VertexProperty vertexProperty = (VertexProperty) g.V(1).properties("name").next();
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(vertexProperty));
-            assertEquals(vertexProperty.toString(), jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),VertexProperty)"));
-            //
-            final Property property = g.V(1).outE("created").properties("weight").next();
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(property));
-            assertEquals(property.toString(), jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),Property)"));
-            //
-            final Traverser<Vertex> traverser = new DefaultRemoteTraverser<>(vertex, 3L);
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(traverser));
-            assertEquals(traverser.toString(), jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertEquals(BigInteger.valueOf(3L), jythonEngine.eval("graphson_reader.readObject(x).bulk")); // jython uses big integer in Java
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x).object,Vertex)"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),Traverser)"));
-        }
-    }
-
-    @Test
-    public void shouldDeserializeNumbers() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_reader = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_reader" : "graphsonV3d0_reader"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1));
-            assertEquals("1", jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),int)"));
-            //
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1L));
-            assertEquals("1", jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),long)"));
-            //
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1.2f));
-            assertEquals("1.2", jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),float)"));
-            //
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1.3d));
-            assertEquals("1.3", jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x),float)"));
-        }
-    }
-
-    @Test
-    public void shouldDeserializeCollections() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_reader = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_reader" : "graphsonV3d0_reader"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            final Map<String, Number> map = new LinkedHashMap<>();
-            map.put("a", 2);
-            map.put("b", 2.3d);
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(map));
-            assertEquals("{u'a': 2, u'b': 2.3}", jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertEquals(2, jythonEngine.eval("graphson_reader.readObject(x)['a']"));
-            assertEquals(2.3d, jythonEngine.eval("graphson_reader.readObject(x)['b']")); // jython is smart about double
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x)['a'],int)"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x)['b'],float)"));
-            //
-            final List<Object> list = Arrays.asList(g.V(1).next(), "hello", map, true);
-            jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(list));
-            assertEquals("[v[1], u'hello', {u'a': 2, u'b': 2.3}, True]", jythonEngine.eval("str(graphson_reader.readObject(x))"));
-            assertEquals(g.V(1).next().toString(), jythonEngine.eval("str(graphson_reader.readObject(x)[0])"));
-            assertEquals("hello", jythonEngine.eval("graphson_reader.readObject(x)[1]"));
-            assertEquals("{u'a': 2, u'b': 2.3}", jythonEngine.eval("str(graphson_reader.readObject(x)[2])"));
-            assertTrue((Boolean) jythonEngine.eval("graphson_reader.readObject(x)[3]"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x)[0],Vertex)"));
-            // assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x)[1],str)")); // its python unicode jython object
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x)[2],dict)"));
-            assertTrue((Boolean) jythonEngine.eval("isinstance(graphson_reader.readObject(x)[3],bool)"));
-        }
-    }
-}
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
deleted file mode 100644
index 905d9c7..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- *  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.python.structure.io.graphson;
-
-import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Pop;
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
-import org.apache.tinkerpop.gremlin.python.jsr223.JythonScriptEngineSetup;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
-import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.python.jsr223.PyScriptEngine;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Ignore
-public class GraphSONWriterTest {
-
-    private static final Set<GraphSONVersion> VERSIONS = new HashSet<>(Arrays.asList(GraphSONVersion.V2_0, GraphSONVersion.V3_0));
-
-    @Test
-    public void shouldSerializeNumbers() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_writer = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_writer" : "graphsonV3d0_writer"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            assertEquals(1, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(1)").toString(), Object.class));
-            assertEquals(mapper.writeValueAsString(1), jythonEngine.eval("graphson_writer.writeObject(1)").toString().replace(" ", ""));
-            //
-            assertEquals(2L, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(2L)").toString(), Object.class));
-            assertEquals(mapper.writeValueAsString(2L), jythonEngine.eval("graphson_writer.writeObject(2L)").toString().replace(" ", ""));
-            //
-            assertEquals(3.4, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(3.4)").toString(), Object.class));
-            assertEquals(mapper.writeValueAsString(3.4), jythonEngine.eval("graphson_writer.writeObject(3.4)").toString().replace(" ", ""));
-        }
-    }
-
-    @Test
-    public void shouldSerializeCollections() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_writer = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_writer" : "graphsonV3d0_writer"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            final Map<String, Number> map = new LinkedHashMap<>();
-            map.put("a", 2);
-            map.put("b", 2.3);
-            assertEquals(map, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject({'a':2,'b':2.3})").toString(), Object.class));
-            //
-            final List<Object> list = Arrays.asList(new DefaultRemoteTraverser<>("hello", 3L), "hello", map, true);
-            assertTrue((Boolean) jythonEngine.eval("isinstance([Traverser('hello',3L),'hello',{'a':2,'b':2.3},True],list)"));
-            assertEquals(list, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject([Traverser('hello',3L),'hello',{'a':2,'b':2.3},True])").toString(), Object.class));
-        }
-    }
-
-    @Test
-    public void shouldSerializeTraverser() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_writer = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_writer" : "graphsonV3d0_writer"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            assertEquals(
-                    new DefaultRemoteTraverser<>("hello", 3L),
-                    mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Traverser('hello',3L))").toString(), Object.class));
-            assertEquals(3L, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Traverser('hello',3L))").toString(), Traverser.class).bulk());
-            assertEquals("hello", mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Traverser('hello',3L))").toString(), Traverser.class).get());
-        }
-    }
-
-    @Test
-    public void shouldSerializeBytecode() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_writer = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_writer" : "graphsonV3d0_writer"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            assertEquals(P.eq(7L), mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(P.eq(7L))").toString(), Object.class));
-            // TODO: assertEquals(mapper.writeValueAsString(P.between(1, 2).and(P.eq(7L))), jythonEngine.eval("graphson_writer.writeObject(P.eq(7L)._and(P.between(1,2)))").toString().replace(" ",""));
-            assertEquals(AndP.class, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(P.eq(7L).and_(P.between(1,2)))").toString(), Object.class).getClass());
-            //
-            assertEquals(new Bytecode.Binding<>("a", 5L), mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Binding('a',5L))").toString(), Object.class));
-            //
-            for (final Column t : Column.values()) {
-                assertEquals(t, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Column." + t.name() + ")").toString(), Object.class));
-            }
-            for (final T t : T.values()) {
-                assertEquals(t, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(T." + t.name() + ")").toString(), Object.class));
-            }
-            assertEquals(Pop.first, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Pop.first)").toString(), Object.class));
-            assertEquals(Pop.last, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Pop.last)").toString(), Object.class));
-            assertEquals(Pop.all, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Pop.all_)").toString(), Object.class));
-            assertEquals(Pop.mixed, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Pop.mixed)").toString(), Object.class));
-            assertEquals(Scope.global, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Scope.global_)").toString(), Object.class));
-            assertEquals(Scope.local, mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(Scope.local)").toString(), Object.class));
-        }
-    }
-
-    @Test
-    public void shouldSerializeLambda() throws Exception {
-        for (final GraphSONVersion version : VERSIONS) {
-            final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
-            jythonEngine.eval("graphson_writer = " + (version.equals(GraphSONVersion.V2_0) ? "graphsonV2d0_writer" : "graphsonV3d0_writer"));
-            final ObjectMapper mapper = GraphSONMapper.build().version(version).create().createMapper();
-            //
-            assertEquals(
-                    Lambda.function("lambda z : 1+2", "gremlin-python"),
-                    mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(lambda : 'z : 1+2')").toString(), Object.class));
-            assertEquals(
-                    Lambda.function("lambda z : z+ 7", "gremlin-python"),
-                    mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(lambda : 'lambda z : z+ 7')").toString(), Object.class));
-            assertEquals(
-                    Lambda.supplier("lambda : 23", "gremlin-python"),
-                    mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(lambda : 'lambda : 23')").toString(), Object.class));
-            assertEquals(
-                    Lambda.consumer("lambda z : z + 23", "gremlin-python"),
-                    mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(lambda : 'lambda z : z + 23')").toString(), Object.class));
-            assertEquals(
-                    Lambda.biFunction("lambda z,y : z - y + 2", "gremlin-python"),
-                    mapper.readValue(jythonEngine.eval("graphson_writer.writeObject(lambda : 'lambda z,y : z - y + 2')").toString(), Object.class));
-        }
-    }
-}
diff --git a/gremlin-python/src/test/resources/log4j-silent.properties b/gremlin-python/src/test/resources/log4j-silent.properties
deleted file mode 100644
index 1825bb0..0000000
--- a/gremlin-python/src/test/resources/log4j-silent.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-# 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.
-
-# this file should always have logging set to OFF.  it seems, however, that an appender of some sort is
-# required or else some logs throw error and use other log4j.properties files on the path.
-log4j.rootLogger=OFF, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=[%p] %C - %m%n
\ No newline at end of file
diff --git a/gremlin-python/src/test/resources/log4j-test.properties b/gremlin-python/src/test/resources/log4j-test.properties
deleted file mode 100644
index 79038b1..0000000
--- a/gremlin-python/src/test/resources/log4j-test.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# 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.
-#
-
-log4j.rootLogger=WARN, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=[%p] %C - %m%n
\ No newline at end of file
diff --git a/gremlin-server/Dockerfile b/gremlin-server/Dockerfile
index 3b1e849..fe8126a 100644
--- a/gremlin-server/Dockerfile
+++ b/gremlin-server/Dockerfile
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-FROM openjdk:8-jre-alpine
+FROM adoptopenjdk/openjdk11:alpine-slim
 
 LABEL maintainer="dev@tinkerpop.apache.org"
 
diff --git a/gremlin-server/conf/gremlin-server-classic.yaml b/gremlin-server/conf/gremlin-server-classic.yaml
index 248a6bf..15b2397 100644
--- a/gremlin-server/conf/gremlin-server-classic.yaml
+++ b/gremlin-server/conf/gremlin-server-classic.yaml
@@ -27,8 +27,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-classic.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/conf/gremlin-server-modern-py.yaml b/gremlin-server/conf/gremlin-server-modern-py.yaml
deleted file mode 100644
index 3193d5f..0000000
--- a/gremlin-server/conf/gremlin-server-modern-py.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-# 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.
-
-# Note that TinkerPop does not include gremlin-python dependencies in
-# its distributions. This file cannot be used as a configuration file
-# to Gremlin Server unless those dependencies are installed on the
-# Gremlin Server path with:
-#
-# bin/gremlin-server.sh -i org.apache.tinkerpop gremlin-python x.y.z
-#
-# The primary change in this file to enable the GremlinJythonScriptEngine
-# is the addition of "gremlin-jython" to the "scriptEngines" field.
-
-host: localhost
-port: 8182
-threadPoolWorker: 1
-gremlinPool: 8
-evaluationTimeout: 30000
-graphs: {
-  graph: conf/tinkergraph-empty.properties}
-scriptEngines: {
-  gremlin-groovy: {
-    plugins: { org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
-               org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
-               org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
-               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-modern.groovy]}}},
-  gremlin-jython: {},
-  gremlin-python: {}
-}
-serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
-metrics: {
-  slf4jReporter: {enabled: true, interval: 180000}}
-strictTransactionManagement: false
-idleConnectionTimeout: 0
-keepAliveInterval: 0
-threadPoolBoss: 1
-maxInitialLineLength: 4096
-maxHeaderSize: 8192
-maxChunkSize: 8192
-maxContentLength: 65536
-maxAccumulationBufferComponents: 1024
-resultIterationBatchSize: 64
diff --git a/gremlin-server/conf/gremlin-server-modern-readonly.yaml b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
index 7388f73..705163f 100644
--- a/gremlin-server/conf/gremlin-server-modern-readonly.yaml
+++ b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
@@ -27,8 +27,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-modern-readonly.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/conf/gremlin-server-modern.yaml b/gremlin-server/conf/gremlin-server-modern.yaml
index 5f83508..e9ace56 100644
--- a/gremlin-server/conf/gremlin-server-modern.yaml
+++ b/gremlin-server/conf/gremlin-server-modern.yaml
@@ -28,8 +28,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-modern.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/conf/gremlin-server-neo4j.yaml b/gremlin-server/conf/gremlin-server-neo4j.yaml
index 08e42a8..6f838af 100644
--- a/gremlin-server/conf/gremlin-server-neo4j.yaml
+++ b/gremlin-server/conf/gremlin-server-neo4j.yaml
@@ -38,8 +38,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/empty-sample.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/conf/gremlin-server-secure.yaml b/gremlin-server/conf/gremlin-server-secure.yaml
index dec2bb3..93c4323 100644
--- a/gremlin-server/conf/gremlin-server-secure.yaml
+++ b/gremlin-server/conf/gremlin-server-secure.yaml
@@ -37,8 +37,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/empty-sample-secure.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/conf/gremlin-server-spark.yaml b/gremlin-server/conf/gremlin-server-spark.yaml
index 4d974bf..8634eab 100644
--- a/gremlin-server/conf/gremlin-server-spark.yaml
+++ b/gremlin-server/conf/gremlin-server-spark.yaml
@@ -51,8 +51,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/spark.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/conf/gremlin-server.yaml b/gremlin-server/conf/gremlin-server.yaml
index 86f4e92..4f210c8 100644
--- a/gremlin-server/conf/gremlin-server.yaml
+++ b/gremlin-server/conf/gremlin-server.yaml
@@ -28,8 +28,6 @@
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/empty-sample.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}            # application/vnd.gremlin-v3.0+gryo
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}                                                                      # application/vnd.gremlin-v3.0+gryo-stringd
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
diff --git a/gremlin-server/pom.xml b/gremlin-server/pom.xml
index f3367f0..194c09d 100644
--- a/gremlin-server/pom.xml
+++ b/gremlin-server/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-server</artifactId>
     <name>Apache TinkerPop :: Gremlin Server</name>
@@ -100,12 +100,6 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.kerby</groupId>
-            <artifactId>kerb-simplekdc</artifactId>
-            <version>2.0.0</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
     <build>
         <directory>${basedir}/target</directory>
@@ -156,7 +150,6 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
             </plugin>
-
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-failsafe-plugin</artifactId>
@@ -206,28 +199,52 @@
                 <dependency>
                     <groupId>org.neo4j</groupId>
                     <artifactId>neo4j-tinkerpop-api-impl</artifactId>
-                    <version>0.3-2.3.3</version>
+                    <version>0.9-3.4.0</version>
                     <scope>test</scope>
                     <exclusions>
                         <exclusion>
+                            <groupId>org.neo4j</groupId>
+                            <artifactId>neo4j-kernel</artifactId>
+                        </exclusion>
+                        <exclusion>
                             <groupId>org.apache.commons</groupId>
                             <artifactId>commons-lang3</artifactId>
                         </exclusion>
                         <exclusion>
-                            <groupId>com.googlecode.concurrentlinkedhashmap</groupId>
-                            <artifactId>concurrentlinkedhashmap-lru</artifactId>
+                            <groupId>org.apache.commons</groupId>
+                            <artifactId>commons-text</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>com.github.ben-manes.caffeine</groupId>
+                            <artifactId>caffeine</artifactId>
                         </exclusion>
                         <exclusion>
                             <groupId>org.scala-lang</groupId>
                             <artifactId>scala-library</artifactId>
                         </exclusion>
                         <exclusion>
+                            <groupId>org.scala-lang</groupId>
+                            <artifactId>scala-reflect</artifactId>
+                        </exclusion>
+                        <exclusion>
                             <groupId>org.slf4j</groupId>
                             <artifactId>slf4j-api</artifactId>
                         </exclusion>
                         <exclusion>
-                            <groupId>info.ganglia.gmetric4j</groupId>
-                            <artifactId>gmetric4j</artifactId>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-nop</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>org.apache.lucene</groupId>
+                            <artifactId>lucene-core</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>io.dropwizard.metrics</groupId>
+                            <artifactId>metrics-core</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>io.netty</groupId>
+                            <artifactId>netty-all</artifactId>
                         </exclusion>
                         <exclusion>
                             <groupId>org.ow2.asm</groupId>
@@ -235,6 +252,42 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
+                <dependency>
+                    <groupId>org.scala-lang</groupId>
+                    <artifactId>scala-library</artifactId>
+                    <version>2.11.8</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.scala-lang</groupId>
+                    <artifactId>scala-reflect</artifactId>
+                    <version>2.11.8</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.lucene</groupId>
+                    <artifactId>lucene-core</artifactId>
+                    <version>5.5.0</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>io.dropwizard.metrics</groupId>
+                    <artifactId>metrics-core</artifactId>
+                    <version>4.0.2</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.neo4j</groupId>
+                    <artifactId>neo4j-kernel</artifactId>
+                    <version>3.4.11</version>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>io.netty</groupId>
+                            <artifactId>netty-all</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
                 <!-- *** WARNING *** -->
             </dependencies>
             <build>
@@ -344,7 +397,7 @@
                             <repository>tinkerpop/gremlin-server</repository>
                         </configuration>
                     </plugin>
-                </plugins>                
+                </plugins>
             </build>
         </profile>
     </profiles>
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
index 77cd465..e6987c1 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
@@ -26,10 +26,8 @@
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.AbstractGryoMessageSerializerV1d0;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.auth.Authenticator;
 import org.apache.tinkerpop.gremlin.server.handler.AbstractAuthenticationHandler;
@@ -48,7 +46,6 @@
 import javax.net.ssl.SSLException;
 import javax.net.ssl.TrustManagerFactory;
 
-import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -81,10 +78,6 @@
 public abstract class AbstractChannelizer extends ChannelInitializer<SocketChannel> implements Channelizer {
     private static final Logger logger = LoggerFactory.getLogger(AbstractChannelizer.class);
     protected static final List<Settings.SerializerSettings> DEFAULT_SERIALIZERS = Arrays.asList(
-            new Settings.SerializerSettings(GryoMessageSerializerV3d0.class.getName(), Collections.emptyMap()),
-            new Settings.SerializerSettings(GryoMessageSerializerV3d0.class.getName(), new HashMap<String,Object>(){{
-                put(AbstractGryoMessageSerializerV1d0.TOKEN_SERIALIZE_RESULT_TO_STRING, true);
-            }}),
             new Settings.SerializerSettings(GraphSONMessageSerializerV2d0.class.getName(), Collections.emptyMap()),
             new Settings.SerializerSettings(GraphBinaryMessageSerializerV1.class.getName(), Collections.emptyMap()),
             new Settings.SerializerSettings(GraphBinaryMessageSerializerV1.class.getName(), new HashMap<String,Object>(){{
@@ -119,7 +112,7 @@
     protected Authenticator authenticator;
 
     /**
-     * This method is called from within {@code SocketChannel} just after the SSL handler is put in the pipeline.
+     * This method is called from within {@link #initChannel(SocketChannel)} just after the SSL handler is put in the pipeline.
      * Modify the pipeline as needed here.
      */
     public abstract void configure(final ChannelPipeline pipeline);
@@ -272,58 +265,43 @@
 
         final SslContextBuilder builder;
 
-        // DEPRECATED: If the config has the required, deprecated settings, then use it
-        if (null != sslSettings.keyCertChainFile && null != sslSettings.keyFile) {
-            logger.warn("Using deprecated SSL keyFile support");
-            final File keyCertChainFile = new File(sslSettings.keyCertChainFile);
-            final File keyFile = new File(sslSettings.keyFile);
-            final File trustCertChainFile = null == sslSettings.trustCertChainFile ? null : new File(sslSettings.trustCertChainFile);
+        // Build JSSE SSLContext
+        try {
+            final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
 
-            // note that keyPassword may be null here if the keyFile is not
-            // password-protected. passing null to
-            // trustManager is also ok (default will be used)
-            builder = SslContextBuilder.forServer(keyCertChainFile, keyFile, sslSettings.keyPassword).trustManager(trustCertChainFile);
-        } else {
-
-            // Build JSSE SSLContext
-            try {
-                final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-
-                // Load private key and signed cert
-                if (null != sslSettings.keyStore) {
-                    final String keyStoreType = null == sslSettings.keyStoreType ? KeyStore.getDefaultType() : sslSettings.keyStoreType;
-                    final KeyStore keystore = KeyStore.getInstance(keyStoreType);
-                    final char[] password = null == sslSettings.keyStorePassword ? null : sslSettings.keyStorePassword.toCharArray();
-                    try (final InputStream in = new FileInputStream(sslSettings.keyStore)) {
-                        keystore.load(in, password);
-                    }
-                    kmf.init(keystore, password);
-                } else {
-                    throw new IllegalStateException("keyStore must be configured when SSL is enabled.");
+            // Load private key and signed cert
+            if (null != sslSettings.keyStore) {
+                final String keyStoreType = null == sslSettings.keyStoreType ? KeyStore.getDefaultType() : sslSettings.keyStoreType;
+                final KeyStore keystore = KeyStore.getInstance(keyStoreType);
+                final char[] password = null == sslSettings.keyStorePassword ? null : sslSettings.keyStorePassword.toCharArray();
+                try (final InputStream in = new FileInputStream(sslSettings.keyStore)) {
+                    keystore.load(in, password);
                 }
-
-                builder = SslContextBuilder.forServer(kmf);
-
-                // Load custom truststore for client auth certs
-                if (null != sslSettings.trustStore) {
-                    final String trustStoreType = null != sslSettings.trustStoreType ? sslSettings.trustStoreType
-                            : sslSettings.keyStoreType != null ? sslSettings.keyStoreType : KeyStore.getDefaultType();
-
-                    final KeyStore truststore = KeyStore.getInstance(trustStoreType);
-                    final char[] password = null == sslSettings.trustStorePassword ? null : sslSettings.trustStorePassword.toCharArray();
-                    try (final InputStream in = new FileInputStream(sslSettings.trustStore)) {
-                        truststore.load(in, password);
-                    }
-                    final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-                    tmf.init(truststore);
-                    builder.trustManager(tmf);
-                }
-
-            } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) {
-                logger.error(e.getMessage());
-                throw new RuntimeException("There was an error enabling SSL.", e);
+                kmf.init(keystore, password);
+            } else {
+                throw new IllegalStateException("keyStore must be configured when SSL is enabled.");
             }
 
+            builder = SslContextBuilder.forServer(kmf);
+
+            // Load custom truststore for client auth certs
+            if (null != sslSettings.trustStore) {
+                final String trustStoreType = null != sslSettings.trustStoreType ? sslSettings.trustStoreType
+                            : sslSettings.keyStoreType != null ? sslSettings.keyStoreType : KeyStore.getDefaultType();
+
+                final KeyStore truststore = KeyStore.getInstance(trustStoreType);
+                final char[] password = null == sslSettings.trustStorePassword ? null : sslSettings.trustStorePassword.toCharArray();
+                try (final InputStream in = new FileInputStream(sslSettings.trustStore)) {
+                    truststore.load(in, password);
+                }
+                final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+                tmf.init(truststore);
+                builder.trustManager(tmf);
+            }
+
+        } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) {
+            logger.error(e.getMessage());
+            throw new RuntimeException("There was an error enabling SSL.", e);
         }
 
         if (null != sslSettings.sslCipherSuites && !sslSettings.sslCipherSuites.isEmpty()) {
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/ResponseHandlerContext.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/ResponseHandlerContext.java
deleted file mode 100644
index d927fd8..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/ResponseHandlerContext.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.server;
-
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.server.handler.Frame;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * A context for asynchronously writing response messages related to a particular request.
- * <p>The "write" methods of this class ensure that at most one {@link ResponseStatusCode#isFinalResponse() final}
- * response message is written to the underlying channel. Attempts to write more than one final response message will
- * be ignored with a warning log message.</p>
- * <p>Note: an object of this class should be used instead of writing to the channel directly when multiple threads
- * are expected to produce final response messages concurrently. Callers must ensure that the same
- * {@link ResponseHandlerContext} is used by all threads writing response messages for the same request.</p>
- *
- * @author Dmitri Bourlatchkov
- * @deprecated As of release 3.3.8, replaced by {@link Context}.
- */
-@Deprecated
-public class ResponseHandlerContext {
-    private static final Logger logger = LoggerFactory.getLogger(ResponseHandlerContext.class);
-
-    private final Context context;
-    private final AtomicBoolean finalResponseWritten = new AtomicBoolean();
-
-    public ResponseHandlerContext(final Context context) {
-        this.context = context;
-    }
-
-    public Context getContext() {
-        return context;
-    }
-
-    /**
-     * Writes a response message to the underlying channel while ensuring that at most one
-     * {@link ResponseStatusCode#isFinalResponse() final} response is written.
-     * <p>Note: this method should be used instead of writing to the channel directly when multiple threads
-     * are expected to produce response messages concurrently.</p>
-     * <p>Attempts to write more than one final response message will be ignored.</p>
-     * @see #writeAndFlush(ResponseStatusCode, Object)
-     */
-    public void writeAndFlush(final ResponseMessage message) {
-        writeAndFlush(message.getStatus().getCode(), message);
-    }
-
-    /**
-     * Writes a response message to the underlying channel while ensuring that at most one
-     * {@link ResponseStatusCode#isFinalResponse() final} response is written.
-     * <p>The caller must make sure that the provided response status code matches the content of the message.</p>
-     * <p>Note: this method should be used instead of writing to the channel directly when multiple threads
-     * are expected to produce response messages concurrently.</p>
-     * <p>Attempts to write more than one final response message will be ignored.</p>
-     * @see #writeAndFlush(ResponseMessage)
-     */
-    public void writeAndFlush(final ResponseStatusCode code, final Object responseMessage) {
-        final boolean messageIsFinal = code.isFinalResponse();
-        if(finalResponseWritten.compareAndSet(false, messageIsFinal)) {
-            context.getChannelHandlerContext().writeAndFlush(responseMessage);
-        } else {
-            if (responseMessage instanceof Frame) {
-                ((Frame) responseMessage).tryRelease();
-            }
-
-            final String logMessage = String.format("Another final response message was already written for request %s, ignoring response code: %s",
-                    context.getRequestMessage().getRequestId(), code);
-            logger.warn(logMessage);
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
index 059163e..ae35d0f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
@@ -101,16 +101,6 @@
     public int threadPoolBoss = 1;
 
     /**
-     * Time in milliseconds to wait for a request (script or bytecode) to complete execution.  Defaults to -1 and
-     * thus defers to {@link #evaluationTimeout} for this configuration. When set to something greater than -1 then
-     * this configuration is used.
-     *
-     * @deprecated As of release 3.3.9, replaced by {@link #evaluationTimeout}.
-     */
-    @Deprecated
-    public long scriptEvaluationTimeout = -1L;
-
-    /**
      * Time in milliseconds to wait for a request (script or bytecode) to complete execution. Defaults to 30000.
      */
     public long evaluationTimeout = 30000L;
@@ -255,7 +245,7 @@
     }
 
     public long getEvaluationTimeout() {
-        return -1 == scriptEvaluationTimeout ? evaluationTimeout : scriptEvaluationTimeout;
+        return evaluationTimeout;
     }
 
     /**
@@ -448,41 +438,6 @@
         public boolean enabled = false;
 
         /**
-         * The X.509 certificate chain file in PEM format.
-         *
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStore}
-         */
-        @Deprecated
-        public String keyCertChainFile = null;
-
-        /**
-         * The PKCS#8 private key file in PEM format.
-         *
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStore}
-         */
-        @Deprecated
-        public String keyFile = null;
-
-        /**
-         * The password of the {@link #keyFile}, or {@code null} if it's not
-         * password-protected.
-         *
-         * @deprecated As of release 3.2.10, replaced by {@link #keyStorePassword}
-         */
-        @Deprecated
-        public String keyPassword = null;
-
-        /**
-         * Trusted certificates for verifying the remote endpoint's certificate. The
-         * file should contain an X.509 certificate chain in PEM format. {@code null}
-         * uses the system default.
-         *
-         * @deprecated As of release 3.2.10, replaced by {@link #trustStore}
-         */
-        @Deprecated
-        public String trustCertChainFile = null;
-
-        /**
          * The file location of the private key in JKS or PKCS#12 format.
          */
         public String keyStore;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Krb5Authenticator.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Krb5Authenticator.java
index 6a339c4..7abf9ac 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Krb5Authenticator.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Krb5Authenticator.java
@@ -72,7 +72,7 @@
             principalName = (String) config.get(PRINCIPAL_KEY);
             subject = JaasKrbUtil.loginUsingKeytab(principalName, keytabFile);
         } catch (Exception e) {
-            logger.warn("Failed to login to kdc");
+            logger.warn("Failed to login to kdc:" + e.getMessage());
         }
         
         logger.debug("Done logging in to kdc");
@@ -110,7 +110,7 @@
                 //   https://docs.oracle.com/javase/8/docs/technotes/guides/security/sasl/sasl-refguide.html#SERVER
                 // Rely on GSSAPI defaults for Sasl.MAX_BUFFER and Sasl.QOP. Note, however, that gremlin-driver has
                 // Sasl.SERVER_AUTH fixed to true (mutual authentication) and one can configure SSL for enhanced confidentiality,
-                // Sasl policy properties for negotiating the authenticatin mechanism are not relevant here, because
+                // Sasl policy properties for negotiating the authentication mechanism are not relevant here, because
                 // GSSAPI is the only available mechanism for this authenticator
                 final Map<String, Object> props = new HashMap<>();
                 if (principalName == null) {
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
deleted file mode 100644
index 8043580..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.server.channel;
-
-import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient;
-import org.apache.tinkerpop.gremlin.server.AbstractChannelizer;
-import org.apache.tinkerpop.gremlin.server.Channelizer;
-import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
-import org.apache.tinkerpop.gremlin.server.handler.GremlinResponseFrameEncoder;
-import org.apache.tinkerpop.gremlin.server.handler.NioGremlinBinaryRequestDecoder;
-import io.netty.channel.ChannelPipeline;
-import io.netty.handler.logging.LogLevel;
-import io.netty.handler.logging.LoggingHandler;
-import org.apache.tinkerpop.gremlin.server.handler.NioGremlinResponseFrameEncoder;
-import org.apache.tinkerpop.gremlin.server.handler.SaslAuthenticationHandler;
-import org.apache.tinkerpop.gremlin.server.util.ServerGremlinExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A {@link Channelizer} that exposes an NIO-based Gremlin endpoint with a custom protocol.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
- */
-@Deprecated
-public class NioChannelizer extends AbstractChannelizer {
-    private static final Logger logger = LoggerFactory.getLogger(NioChannelizer.class);
-
-    private SaslAuthenticationHandler authenticationHandler;
-    private GremlinResponseFrameEncoder gremlinResponseFrameEncoder;
-    private NioGremlinResponseFrameEncoder nioGremlinResponseFrameEncoder;
-
-    @Override
-    public void init(final ServerGremlinExecutor serverGremlinExecutor) {
-        super.init(serverGremlinExecutor);
-
-        // configure authentication - null means don't bother to add authentication to the pipeline
-        if (authenticator != null)
-            authenticationHandler = authenticator.getClass() == AllowAllAuthenticator.class ?
-                    null : new SaslAuthenticationHandler(authenticator, settings.authentication);
-
-        gremlinResponseFrameEncoder = new GremlinResponseFrameEncoder();
-        nioGremlinResponseFrameEncoder = new NioGremlinResponseFrameEncoder();
-    }
-
-    @Override
-    public void configure(final ChannelPipeline pipeline) {
-        if (logger.isDebugEnabled())
-            pipeline.addLast(new LoggingHandler("log-io", LogLevel.DEBUG));
-
-        pipeline.addLast("nio-frame-encoder", nioGremlinResponseFrameEncoder);
-        pipeline.addLast("response-frame-encoder", gremlinResponseFrameEncoder);
-        pipeline.addLast("request-binary-decoder", new NioGremlinBinaryRequestDecoder(serializers));
-
-        if (logger.isDebugEnabled())
-            pipeline.addLast(new LoggingHandler("log-codec", LogLevel.DEBUG));
-
-        if (authenticationHandler != null)
-            pipeline.addLast(PIPELINE_AUTHENTICATOR, authenticationHandler);
-    }
-}
\ No newline at end of file
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinBinaryRequestDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinBinaryRequestDecoder.java
deleted file mode 100644
index 5709143..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinBinaryRequestDecoder.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.server.handler;
-
-import io.netty.handler.codec.ReplayingDecoder;
-import io.netty.util.CharsetUtil;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- *
- * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
- */
-@Deprecated
-public class NioGremlinBinaryRequestDecoder extends ReplayingDecoder<NioGremlinBinaryRequestDecoder.DecoderState> {
-    private static final Logger logger = LoggerFactory.getLogger(NioGremlinBinaryRequestDecoder.class);
-    private final Map<String, MessageSerializer> serializers;
-    private int messageLength;
-
-    public NioGremlinBinaryRequestDecoder(final Map<String, MessageSerializer> serializers) {
-        super(DecoderState.MESSAGE_LENGTH);
-        this.serializers = serializers;
-    }
-
-    @Override
-    protected void decode(final ChannelHandlerContext channelHandlerContext, final ByteBuf byteBuf, final List<Object> objects) throws Exception {
-        switch (state()) {
-            case MESSAGE_LENGTH:
-                messageLength = byteBuf.readInt();
-                checkpoint(DecoderState.MESSAGE);
-            case MESSAGE:
-                try {
-                    final ByteBuf messageFrame = byteBuf.readBytes(messageLength);
-                    final int contentTypeLength = messageFrame.readByte();
-                    final ByteBuf contentTypeFrame = messageFrame.readBytes(contentTypeLength);
-                    final String contentType = contentTypeFrame.toString(CharsetUtil.UTF_8);
-
-                    // the default serializer to use has been GraphSON 1.0 to this point (which was probably bad),
-                    // so maintain that for 3.3.x
-                    final MessageSerializer serializer = select(contentType, ServerSerializers.DEFAULT_SERIALIZER);
-
-                    // it's important to re-initialize these channel attributes as they apply globally to the channel. in
-                    // other words, the next request to this channel might not come with the same configuration and mixed
-                    // state can carry through from one request to the next
-                    channelHandlerContext.channel().attr(StateKey.SESSION).set(null);
-                    channelHandlerContext.channel().attr(StateKey.SERIALIZER).set(serializer);
-                    channelHandlerContext.channel().attr(StateKey.USE_BINARY).set(true);
-
-                    // subtract the contentTypeLength and the byte that held it from the full message length to
-                    // figure out how long the rest of the message is
-                    final int payloadLength = messageLength - 1 - contentTypeLength;
-                    objects.add(serializer.deserializeRequest(messageFrame.readBytes(payloadLength)));
-                } catch (SerializationException se) {
-                    objects.add(RequestMessage.INVALID);
-                }
-
-                checkpoint(DecoderState.MESSAGE_LENGTH);
-                break;
-            default:
-                throw new Error("Invalid message sent to Gremlin Server");
-        }
-    }
-
-    public MessageSerializer select(final String mimeType, final MessageSerializer defaultSerializer) {
-        if (logger.isWarnEnabled() && !serializers.containsKey(mimeType))
-            logger.warn("Gremlin Server is not configured with a serializer for the requested mime type [{}] - using {} by default",
-                    mimeType, defaultSerializer.getClass().getName());
-
-        return serializers.getOrDefault(mimeType, defaultSerializer);
-    }
-
-    public enum DecoderState {
-        MESSAGE_LENGTH,
-        MESSAGE
-    }
-}
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
deleted file mode 100644
index 7bfc98e..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.server.handler;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.MessageToByteEncoder;
-import io.netty.util.CharsetUtil;
-import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient;
-
-/**
- * Encodes {@code ByteBuf} and {@code String} values to bytes to be written over NIO.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.3.10, not replaced, use {@link WebSocketClient}.
- */
-@Deprecated
-@ChannelHandler.Sharable
-public class NioGremlinResponseFrameEncoder extends MessageToByteEncoder<Frame> {
-    @Override
-    protected void encode(final ChannelHandlerContext ctx, final Frame frame, final ByteBuf byteBuf) throws Exception {
-        if (frame.getMsg() instanceof ByteBuf) {
-            final ByteBuf bytes = (ByteBuf) frame.getMsg();
-            byteBuf.writeInt(bytes.capacity());
-            byteBuf.writeBytes(bytes);
-            bytes.release();
-        } else if (frame.getMsg() instanceof String) {
-            final byte [] bytes = ((String) frame.getMsg()).getBytes(CharsetUtil.UTF_8);
-            byteBuf.writeInt(bytes.length);
-            byteBuf.writeBytes(bytes);
-        }
-    }
-}
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
index 3e11ae8..6b2d248 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
@@ -21,8 +21,6 @@
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.handler.codec.base64.Base64Decoder;
 import io.netty.util.Attribute;
 
 import java.net.InetAddress;
@@ -37,13 +35,11 @@
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
 import org.apache.tinkerpop.gremlin.server.auth.Authenticator;
-import org.apache.tinkerpop.gremlin.server.channel.NioChannelizer;
 import org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,7 +47,6 @@
 /**
  * A SASL authentication handler that allows the {@link Authenticator} to be plugged into it. This handler is meant
  * to be used with protocols that process a {@link RequestMessage} such as the {@link WebSocketChannelizer}
- * or the {@link NioChannelizer}
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/ServerSerializers.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/ServerSerializers.java
index d59e1ed..09b7599 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/ServerSerializers.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/ServerSerializers.java
@@ -19,8 +19,8 @@
 package org.apache.tinkerpop.gremlin.server.handler;
 
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -30,10 +30,15 @@
     private ServerSerializers() {}
 
     /**
-     * Default serializer used by the server when the serializer requested does not match what is on the server.
-     * Using GraphSON 1.0 on 3.3.5 because that's what it has long been set to in previous versions on
-     * {@link Serializers#DEFAULT_RESULT_SERIALIZER} which is now deprecated.
+     * Default binary serializer used by the server when the serializer requested does not match what is on the server.
+     * This defaults to GraphBinary 1.0.
      */
-    static final MessageSerializer DEFAULT_SERIALIZER = new GraphSONMessageSerializerV1d0();
+    static final MessageSerializer DEFAULT_BINARY_SERIALIZER = new GraphBinaryMessageSerializerV1();
+
+    /**
+     * Default binary serializer used by the server when the serializer requested does not match what is on the server.
+     * This defaults to GraphSON 3.0.
+     */
+    static final MessageSerializer DEFAULT_TEXT_SERIALIZER = new GraphSONMessageSerializerV3d0();
 
 }
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java
index a56d017..e3b61bc 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java
@@ -64,7 +64,7 @@
         try {
             messageBytes.readBytes(contentTypeBytes);
             final String contentType = contentTypeBytes.toString(UTF8);
-            final MessageSerializer serializer = select(contentType, ServerSerializers.DEFAULT_SERIALIZER);
+            final MessageSerializer serializer = select(contentType, ServerSerializers.DEFAULT_BINARY_SERIALIZER);
 
             // it's important to re-initialize these channel attributes as they apply globally to the channel. in
             // other words, the next request to this channel might not come with the same configuration and mixed
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinCloseRequestDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinCloseRequestDecoder.java
index 8567ff0..6281851 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinCloseRequestDecoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinCloseRequestDecoder.java
@@ -26,7 +26,6 @@
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,7 +63,7 @@
         try {
             messageBytes.readBytes(contentTypeBytes);
             final String contentType = contentTypeBytes.toString(UTF8);
-            final MessageSerializer serializer = select(contentType, ServerSerializers.DEFAULT_SERIALIZER);
+            final MessageSerializer serializer = select(contentType, ServerSerializers.DEFAULT_BINARY_SERIALIZER);
 
             // it's important to re-initialize these channel attributes as they apply globally to the channel. in
             // other words, the next request to this channel might not come with the same configuration and mixed
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java
index 0f614ca..77472ac 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java
@@ -52,7 +52,7 @@
     protected void decode(final ChannelHandlerContext channelHandlerContext, final TextWebSocketFrame frame, final List<Object> objects) throws Exception {
         try {
             // the default serializer must be a MessageTextSerializer instance to be compatible with this decoder
-            final MessageTextSerializer serializer = (MessageTextSerializer) select("application/json", ServerSerializers.DEFAULT_SERIALIZER);
+            final MessageTextSerializer serializer = (MessageTextSerializer) select("application/json", ServerSerializers.DEFAULT_TEXT_SERIALIZER);
 
             // it's important to re-initialize these channel attributes as they apply globally to the channel. in
             // other words, the next request to this channel might not come with the same configuration and mixed
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index 2620e47..fd4491c 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -30,7 +30,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
 import org.apache.tinkerpop.gremlin.server.OpProcessor;
-import org.apache.tinkerpop.gremlin.server.ResponseHandlerContext;
 import org.apache.tinkerpop.gremlin.structure.Column;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.server.Context;
@@ -190,15 +189,6 @@
     }
 
     /**
-     * @deprecated As of release 3.3.8, replaced by {@link #evalOpInternal(Context, Supplier, BindingSupplier)}.
-     */
-    @Deprecated
-    protected void evalOpInternal(final ResponseHandlerContext ctx, final Supplier<GremlinExecutor> gremlinExecutorSupplier,
-                                  final BindingSupplier bindingsSupplier) throws OpProcessorException {
-        evalOpInternal(ctx.getContext(), gremlinExecutorSupplier, bindingsSupplier);
-    }
-
-    /**
      * A generalized implementation of the "eval" operation.  It handles script evaluation and iteration of results
      * so as to write {@link ResponseMessage} objects down the Netty pipeline.  It also handles script timeouts,
      * iteration timeouts, metrics and building bindings.  Note that result iteration is delegated to the
@@ -230,11 +220,8 @@
 
         // timeout override - handle both deprecated and newly named configuration. earlier logic should prevent
         // both configurations from being submitted at the same time
-        final long seto = args.containsKey(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT) || args.containsKey(Tokens.ARGS_EVAL_TIMEOUT)
-            // could be sent as an integer or long
-            ? (args.containsKey(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT) ?
-                ((Number) args.get(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT)).longValue() : ((Number) args.get(Tokens.ARGS_EVAL_TIMEOUT)).longValue())
-            : settings.getEvaluationTimeout();
+        final long seto = args.containsKey(Tokens.ARGS_EVAL_TIMEOUT) ?
+                ((Number) args.get(Tokens.ARGS_EVAL_TIMEOUT)).longValue() : settings.getEvaluationTimeout();
 
         final GremlinExecutor.LifeCycle lifeCycle = GremlinExecutor.LifeCycle.build()
                 .evaluationTimeoutOverride(seto)
@@ -303,13 +290,13 @@
                             ((MultipleCompilationErrorsException) t).getErrorCollector().getErrorCount() == 1) {
                         final String errorMessage = String.format("The Gremlin statement that was submitted exceeds the maximum compilation size allowed by the JVM, please split it into multiple smaller statements - %s", trimMessage(msg));
                         logger.warn(errorMessage);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION)
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_EVALUATION)
                                                          .statusMessage(errorMessage)
                                                          .statusAttributeException(t).create());
                     } else {
                         final String errorMessage =  (t.getMessage() == null) ? t.toString() : t.getMessage();
                         logger.warn(String.format("Exception processing a script on request [%s].", msg), t);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION)
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_EVALUATION)
                                                          .statusMessage(errorMessage)
                                                          .statusAttributeException(t).create());
                     }
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
index 6254b1d..0b72ed6 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
@@ -28,7 +28,6 @@
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
 import org.apache.tinkerpop.gremlin.server.OpProcessor;
-import org.apache.tinkerpop.gremlin.server.ResponseHandlerContext;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.handler.Frame;
 import org.apache.tinkerpop.gremlin.server.handler.StateKey;
@@ -64,14 +63,6 @@
     }
 
     /**
-     * @deprecated As of release 3.3.8, not replaced.
-     */
-    @Deprecated
-    protected void handleIterator(final ResponseHandlerContext rhc, final Iterator itty) throws InterruptedException {
-        handleIterator(rhc.getContext(), itty);
-    }
-
-    /**
      * Provides a generic way of iterating a result set back to the client.
      *
      * @param context The Gremlin Server {@link Context} object containing settings, request message, etc.
@@ -242,24 +233,11 @@
      *
      * @param itty a reference to the current {@link Iterator} of results - it is not meant to be forwarded in
      *             this method
-     * @deprecated As of release 3.4.0, replaced by {@link #generateResultMetaData(ChannelHandlerContext, RequestMessage, ResponseStatusCode, Iterator, Settings)}
-     */
-    @Deprecated
-    protected Map<String, Object> generateMetaData(final ChannelHandlerContext ctx, final RequestMessage msg,
-                                                   final ResponseStatusCode code, final Iterator itty) {
-        return Collections.emptyMap();
-    }
-
-    /**
-     * Generates response result meta-data to put on a {@link ResponseMessage}.
-     *
-     * @param itty a reference to the current {@link Iterator} of results - it is not meant to be forwarded in
-     *             this method
      */
     protected Map<String, Object> generateResultMetaData(final ChannelHandlerContext ctx, final RequestMessage msg,
                                                          final ResponseStatusCode code, final Iterator itty,
                                                          final Settings settings) {
-        return generateMetaData(ctx, msg, code, itty);
+        return Collections.emptyMap();
     }
 
     /**
@@ -280,50 +258,6 @@
         return metaData;
     }
 
-    /**
-     * @deprecated As of release 3.3.8, replaced by {@link #makeFrame(Context, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)}.
-     */
-    @Deprecated
-    protected static Frame makeFrame(final ChannelHandlerContext ctx, final RequestMessage msg,
-                                     final MessageSerializer serializer, final boolean useBinary, final List<Object> aggregate,
-                                     final ResponseStatusCode code, final Map<String,Object> responseMetaData,
-                                     final Map<String,Object> statusAttributes) throws Exception {
-        final Context context = new Context(msg, ctx, null, null, null, null); // dummy context, good only for writing response messages to the channel
-        final ResponseHandlerContext rhc = new ResponseHandlerContext(context);
-        return makeFrame(rhc, msg, serializer, useBinary, aggregate, code, responseMetaData, statusAttributes);
-    }
-
-    /**
-     * @deprecated As of release 3.3.8, replaced by {@link #makeFrame(Context, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)}.
-     */
-    @Deprecated
-    protected static Frame makeFrame(final ResponseHandlerContext rhc, final RequestMessage msg,
-                                     final MessageSerializer serializer, final boolean useBinary, final List<Object> aggregate,
-                                     final ResponseStatusCode code, final Map<String,Object> responseMetaData) throws Exception {
-        return makeFrame(rhc.getContext(), msg, serializer, useBinary,aggregate, code, responseMetaData);
-    }
-
-    /**
-     * @deprecated As of release 3.3.8, replaced by {@link #makeFrame(Context, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)}.
-     */
-    @Deprecated
-    protected static Frame makeFrame(final ResponseHandlerContext rhc, final RequestMessage msg,
-                                     final MessageSerializer serializer, final boolean useBinary, final List<Object> aggregate,
-                                     final ResponseStatusCode code, final Map<String,Object> responseMetaData,
-                                     final Map<String,Object> statusAttributes) throws Exception {
-        return makeFrame(rhc.getContext(), msg, serializer, useBinary,aggregate, code, responseMetaData, statusAttributes);
-    }
-
-    /**
-     * @deprecated As of release 3.4.3, replaced by {@link #makeFrame(Context, RequestMessage, MessageSerializer, boolean, List, ResponseStatusCode, Map)}.
-     */
-    @Deprecated
-    protected static Frame makeFrame(final Context ctx, final RequestMessage msg,
-                                     final MessageSerializer serializer, final boolean useBinary, final List<Object> aggregate,
-                                     final ResponseStatusCode code, final Map<String,Object> responseMetaData) throws Exception {
-        return makeFrame(ctx, msg, serializer, useBinary,aggregate, code, responseMetaData, Collections.emptyMap());
-    }
-
     protected static Frame makeFrame(final Context ctx, final RequestMessage msg,
                                      final MessageSerializer serializer, final boolean useBinary, final List<Object> aggregate,
                                      final ResponseStatusCode code, final Map<String,Object> responseMetaData,
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
index 2bcb430..b4d6d4e 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
@@ -122,13 +122,14 @@
     }
 
     /**
-     * Session based requests accept a "close" operator in addition to "eval". A close will trigger the session to be
-     * killed and any uncommitted transaction to be rolled-back.
+     * Older versions of session-based requests accepted a "close" operator in addition to "eval". This feature
+     * effectively acts as a do-nothing for 3.5.0 to allow older versions of the drivers to connect. At some point
+     * this may be removed completely. Note that closing the channel kills the session now.
      */
     @Override
     public Optional<ThrowingConsumer<Context>> selectOther(final RequestMessage requestMessage) throws OpProcessorException {
-        // deprecated the "close" message at 3.3.11 - should probably leave this check for the "close" token so that
-        // if older versions of the driver connect they won't get an error. can basically just write back a NO_CONTENT
+        // deprecated the "close" message at 3.3.11 - left this check for the "close" token so that if older versions
+        // of the driver connect they won't get an error. basically just writes back a NO_CONTENT
         // for the immediate term in 3.5.0 and then for some future version remove support for the message completely
         // and thus disallow older driver versions from connecting at all.
         if (requestMessage.getOp().equals(Tokens.OPS_CLOSE)) {
@@ -138,14 +139,7 @@
                 throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
             }
 
-            final boolean force = requestMessage.<Boolean>optionalArgs(Tokens.ARGS_FORCE).orElse(false);
-
             return Optional.of(rhc -> {
-                final Session sessionToClose = sessions.get(requestMessage.getArgs().get(Tokens.ARGS_SESSION).toString());
-                if (null != sessionToClose) {
-                    sessionToClose.manualKill(force);
-                }
-
                 // send back a confirmation of the close
                 rhc.writeAndFlush(ResponseMessage.build(requestMessage)
                         .code(ResponseStatusCode.NO_CONTENT)
@@ -191,6 +185,15 @@
             throw new OpProcessorException(sessionClosedMessage, response);
         }
 
+        // check if the session is bound to this channel, thus one client per session
+        if (!session.isBoundTo(context.getChannelHandlerContext().channel())) {
+            final String sessionClosedMessage = String.format("Session %s is not bound to the connecting client",
+                    session.getSessionId());
+            final ResponseMessage response = ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                    .statusMessage(sessionClosedMessage).create();
+            throw new OpProcessorException(sessionClosedMessage, response);
+        }
+
         // place the session on the channel context so that it can be used during serialization.  in this way
         // the serialization can occur on the same thread used to execute the gremlin within the session.  this
         // is important given the threadlocal nature of Graph implementation transactions.
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
index 418c66c..0d4b797 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
@@ -19,8 +19,6 @@
 package org.apache.tinkerpop.gremlin.server.op.traversal;
 
 import com.codahale.metrics.Timer;
-import com.github.benmanes.caffeine.cache.Cache;
-import com.github.benmanes.caffeine.cache.Caffeine;
 import io.netty.channel.ChannelHandlerContext;
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.Tokens;
@@ -30,7 +28,6 @@
 import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.util.BytecodeHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
@@ -44,7 +41,6 @@
 import org.apache.tinkerpop.gremlin.server.op.AbstractOpProcessor;
 import org.apache.tinkerpop.gremlin.server.op.OpProcessorException;
 import org.apache.tinkerpop.gremlin.server.util.MetricManager;
-import org.apache.tinkerpop.gremlin.server.util.SideEffectIterator;
 import org.apache.tinkerpop.gremlin.server.util.TraverserIterator;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
@@ -59,13 +55,10 @@
 import javax.script.SimpleBindings;
 import java.lang.reflect.UndeclaredThrowableException;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.UUID;
 import java.util.concurrent.Future;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
@@ -79,62 +72,11 @@
  */
 public class TraversalOpProcessor extends AbstractOpProcessor {
     private static final Logger logger = LoggerFactory.getLogger(TraversalOpProcessor.class);
+    private static final Logger auditLogger = LoggerFactory.getLogger(GremlinServer.AUDIT_LOGGER_NAME);
     private static final ObjectMapper mapper = GraphSONMapper.build().version(GraphSONVersion.V2_0).create().createMapper();
     public static final String OP_PROCESSOR_NAME = "traversal";
     public static final Timer traversalOpTimer = MetricManager.INSTANCE.getTimer(name(GremlinServer.class, "op", "traversal"));
 
-    public static final Settings.ProcessorSettings DEFAULT_SETTINGS = new Settings.ProcessorSettings();
-
-    /**
-     * Configuration setting for how long a cached side-effect will be available before it is evicted from the cache.
-     *
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String CONFIG_CACHE_EXPIRATION_TIME = "cacheExpirationTime";
-
-    /**
-     * Default timeout for a cached side-effect is ten minutes.
-     *
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final long DEFAULT_CACHE_EXPIRATION_TIME = 600000;
-
-    /**
-     * Configuration setting for the maximum number of entries the cache will have.
-     *
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final String CONFIG_CACHE_MAX_SIZE = "cacheMaxSize";
-
-    /**
-     * Default size of the max size of the cache.
-     *
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    @Deprecated
-    public static final long DEFAULT_CACHE_MAX_SIZE = 1000;
-
-    static {
-        DEFAULT_SETTINGS.className = TraversalOpProcessor.class.getCanonicalName();
-        DEFAULT_SETTINGS.config = new HashMap<String, Object>() {{
-            put(CONFIG_CACHE_EXPIRATION_TIME, DEFAULT_CACHE_EXPIRATION_TIME);
-            put(CONFIG_CACHE_MAX_SIZE, DEFAULT_CACHE_MAX_SIZE);
-        }};
-    }
-
-    /**
-     * @deprecated As of release 3.3.8, not directly replaced in the protocol as side-effect retrieval after
-     * traversal iteration is not being promoted anymore as a feature.
-     */
-    protected static Cache<UUID, TraversalSideEffects> cache = null;
-
     private static final Bindings EMPTY_BINDINGS = new SimpleBindings();
 
     public TraversalOpProcessor() {
@@ -152,23 +94,6 @@
     }
 
     @Override
-    public void init(final Settings settings) {
-        final Settings.ProcessorSettings processorSettings = settings.processors.stream()
-                .filter(p -> p.className.equals(TraversalOpProcessor.class.getCanonicalName()))
-                .findAny().orElse(TraversalOpProcessor.DEFAULT_SETTINGS);
-        final long maxSize = Long.parseLong(processorSettings.config.get(TraversalOpProcessor.CONFIG_CACHE_MAX_SIZE).toString());
-        final long expirationTime = Long.parseLong(processorSettings.config.get(TraversalOpProcessor.CONFIG_CACHE_EXPIRATION_TIME).toString());
-
-        cache = Caffeine.newBuilder()
-                .expireAfterWrite(expirationTime, TimeUnit.MILLISECONDS)
-                .maximumSize(maxSize)
-                .build();
-
-        logger.info("Initialized cache for {} with size {} and expiration time of {} ms",
-                TraversalOpProcessor.class.getSimpleName(), maxSize, expirationTime);
-    }
-
-    @Override
     public ThrowingConsumer<Context> select(final Context context) throws OpProcessorException {
         final RequestMessage message = context.getRequestMessage();
         logger.debug("Selecting processor for RequestMessage {}", message);
@@ -179,62 +104,6 @@
                 validateTraversalSourceAlias(context, message, validateTraversalRequest(message));
                 op = this::iterateBytecodeTraversal;
                 break;
-            case Tokens.OPS_GATHER:
-                final Optional<String> sideEffectForGather = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
-                if (!sideEffectForGather.isPresent()) {
-                    final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_GATHER, Tokens.ARGS_SIDE_EFFECT);
-                    throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
-                }
-
-                final Optional<String> sideEffectKey = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT_KEY);
-                if (!sideEffectKey.isPresent()) {
-                    final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_GATHER, Tokens.ARGS_SIDE_EFFECT_KEY);
-                    throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
-                }
-
-                validateTraversalSourceAlias(context, message, validatedAliases(message).get());
-
-                op = this::gatherSideEffect;
-
-                break;
-            case Tokens.OPS_KEYS:
-                final Optional<String> sideEffectForKeys = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
-                if (!sideEffectForKeys.isPresent()) {
-                    final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_GATHER, Tokens.ARGS_SIDE_EFFECT);
-                    throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
-                }
-
-                op = varRhc -> {
-                    final RequestMessage msg = context.getRequestMessage();
-                    final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
-                    final TraversalSideEffects sideEffects = cache.getIfPresent(sideEffect.get());
-
-                    if (null == sideEffects)
-                        logger.warn("Request for side-effect keys on {} returned no side-effects in the cache", sideEffect.get());
-
-                    handleIterator(varRhc, null == sideEffects ? Collections.emptyIterator() : sideEffects.keys().iterator());
-                };
-
-                break;
-            case Tokens.OPS_CLOSE:
-                final Optional<String> sideEffectForClose = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
-                if (!sideEffectForClose.isPresent()) {
-                    final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_CLOSE, Tokens.ARGS_SIDE_EFFECT);
-                    throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
-                }
-
-                op = varRhc -> {
-                    final RequestMessage msg = context.getRequestMessage();
-                    logger.debug("Close request {} for in thread {}", msg.getRequestId(), Thread.currentThread().getName());
-
-                    final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
-                    cache.invalidate(sideEffect.get());
-
-                    final String successMessage = String.format("Successfully cleared side effect cache for [%s].", Tokens.ARGS_SIDE_EFFECT);
-                    varRhc.writeAndFlush(ResponseMessage.build(message).code(ResponseStatusCode.NO_CONTENT).statusMessage(successMessage).create());
-                };
-
-                break;
             case Tokens.OPS_INVALID:
                 final String msgInvalid = String.format("Message could not be parsed.  Check the format of the request. [%s]", message);
                 throw new OpProcessorException(msgInvalid, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgInvalid).create());
@@ -279,80 +148,9 @@
         return aliases;
     }
 
-    private void gatherSideEffect(final Context context) throws OpProcessorException {
-        final RequestMessage msg = context.getRequestMessage();
-        logger.debug("Side-effect request {} for in thread {}", msg.getRequestId(), Thread.currentThread().getName());
-
-        // earlier validation in selection of this op method should free us to cast this without worry
-        final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
-        final Optional<String> sideEffectKey = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT_KEY);
-        final Map<String, String> aliases = (Map<String, String>) msg.optionalArgs(Tokens.ARGS_ALIASES).get();
-
-        final GraphManager graphManager = context.getGraphManager();
-        final String traversalSourceName = aliases.entrySet().iterator().next().getValue();
-        final TraversalSource g = graphManager.getTraversalSource(traversalSourceName);
-
-        final Timer.Context timerContext = traversalOpTimer.time();
-        try {
-            final ChannelHandlerContext ctx = context.getChannelHandlerContext();
-            final Graph graph = g.getGraph();
-
-            context.getGremlinExecutor().getExecutorService().submit(() -> {
-                try {
-                    beforeProcessing(graph, context);
-
-                    try {
-                        final TraversalSideEffects sideEffects = cache.getIfPresent(sideEffect.get());
-
-                        if (null == sideEffects) {
-                            final String errorMessage = String.format("Could not find side-effects for %s.", sideEffect.get());
-                            logger.warn(errorMessage);
-                            context.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(errorMessage).create());
-                            onError(graph, context);
-                            return;
-                        }
-
-                        if (!sideEffects.exists(sideEffectKey.get())) {
-                            final String errorMessage = String.format("Could not find side-effect key for %s in %s.", sideEffectKey.get(), sideEffect.get());
-                            logger.warn(errorMessage);
-                            context.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(errorMessage).create());
-                            onError(graph, context);
-                            return;
-                        }
-
-                        handleIterator(context, new SideEffectIterator(sideEffects.get(sideEffectKey.get()), sideEffectKey.get()));
-                    } catch (Exception ex) {
-                        logger.warn(String.format("Exception processing a side-effect on iteration for request [%s].", msg.getRequestId()), ex);
-                        context.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
-                                                             .statusMessage(ex.getMessage())
-                                                             .statusAttributeException(ex).create());
-                        onError(graph, context);
-                        return;
-                    }
-
-                    onSideEffectSuccess(graph, context);
-                } catch (Exception ex) {
-                    logger.warn(String.format("Exception processing a side-effect on request [%s].", msg.getRequestId()), ex);
-                    context.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
-                                                         .statusMessage(ex.getMessage())
-                                                         .statusAttributeException(ex).create());
-                    onError(graph, context);
-                } finally {
-                    timerContext.stop();
-                }
-            });
-
-        } catch (Exception ex) {
-            timerContext.stop();
-            throw new OpProcessorException("Could not iterate the side-effect instance",
-                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
-                            .statusMessage(ex.getMessage())
-                            .statusAttributeException(ex).create());
-        }
-    }
-
     private void iterateBytecodeTraversal(final Context context) throws Exception {
         final RequestMessage msg = context.getRequestMessage();
+        final Settings settings = context.getSettings();
         logger.debug("Traversal request {} for in thread {}", msg.getRequestId(), Thread.currentThread().getName());
 
         // right now the TraversalOpProcessor can take a direct GraphSON representation of Bytecode or directly take
@@ -367,11 +165,8 @@
         // timeout override - handle both deprecated and newly named configuration. earlier logic should prevent
         // both configurations from being submitted at the same time
         final Map<String, Object> args = msg.getArgs();
-        final long seto = args.containsKey(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT) || args.containsKey(Tokens.ARGS_EVAL_TIMEOUT)
-                // could be sent as an integer or long
-                ? (args.containsKey(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT) ?
-                ((Number) args.get(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT)).longValue() : ((Number) args.get(Tokens.ARGS_EVAL_TIMEOUT)).longValue())
-                : context.getSettings().getEvaluationTimeout();
+        final long seto = args.containsKey(Tokens.ARGS_EVAL_TIMEOUT) ?
+                ((Number) args.get(Tokens.ARGS_EVAL_TIMEOUT)).longValue() : context.getSettings().getEvaluationTimeout();
 
         final GraphManager graphManager = context.getGraphManager();
         final String traversalSourceName = aliases.entrySet().iterator().next().getValue();
@@ -387,7 +182,7 @@
         } catch (ScriptException ex) {
             logger.error("Traversal contains a lambda that cannot be compiled", ex);
             throw new OpProcessorException("Traversal contains a lambda that cannot be compiled",
-                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION)
+                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_EVALUATION)
                             .statusMessage(ex.getMessage())
                             .statusAttributeException(ex).create());
         } catch (Exception ex) {
@@ -397,6 +192,11 @@
                             .statusMessage(ex.getMessage())
                             .statusAttributeException(ex).create());
         }
+        if (settings.authentication.enableAuditLog) {
+            String address = context.getChannelHandlerContext().channel().remoteAddress().toString();
+            if (address.startsWith("/") && address.length() > 1) address = address.substring(1);
+            auditLogger.info("User with address {} requested: {}", address, bytecode);
+        }
 
         final Timer.Context timerContext = traversalOpTimer.time();
         final FutureTask<Void> evalFuture = new FutureTask<>(() -> {
@@ -449,16 +249,6 @@
         }
     }
 
-    @Override
-    protected void iterateComplete(final ChannelHandlerContext ctx, final RequestMessage msg, final Iterator itty) {
-        if (itty instanceof TraverserIterator) {
-            final Traversal.Admin traversal = ((TraverserIterator) itty).getTraversal();
-            if (!traversal.getSideEffects().isEmpty()) {
-                cache.put(msg.getRequestId(), traversal.getSideEffects());
-            }
-        }
-    }
-
     protected void beforeProcessing(final Graph graph, final Context ctx) {
         if (graph.features().graph().supportsTransactions() && graph.tx().isOpen()) graph.tx().rollback();
     }
@@ -471,35 +261,6 @@
         if (graph.features().graph().supportsTransactions() && graph.tx().isOpen()) graph.tx().commit();
     }
 
-    protected void onSideEffectSuccess(final Graph graph, final Context ctx) {
-        // there was no "writing" here, just side-effect retrieval, so if a transaction was opened then
-        // just close with rollback
-        if (graph.features().graph().supportsTransactions() && graph.tx().isOpen()) graph.tx().rollback();
-    }
-
-    @Override
-    protected Map<String, Object> generateMetaData(final ChannelHandlerContext ctx, final RequestMessage msg,
-                                                   final ResponseStatusCode code, final Iterator itty) {
-        // leaving this overriding the deprecated version of this method because it provides a decent test to those
-        // who might have their own OpProcessor implementations that apply meta-data. leaving this alone helps validate
-        // that the upgrade path is clean.  it can be removed at the next breaking change 3.5.0
-        Map<String, Object> metaData = Collections.emptyMap();
-        if (itty instanceof SideEffectIterator) {
-            final SideEffectIterator traversalIterator = (SideEffectIterator) itty;
-            final String key = traversalIterator.getSideEffectKey();
-            if (key != null) {
-                metaData = new HashMap<>();
-                metaData.put(Tokens.ARGS_SIDE_EFFECT_KEY, key);
-                metaData.put(Tokens.ARGS_AGGREGATE_TO, traversalIterator.getSideEffectAggregator());
-            }
-        } else {
-            // this is a standard traversal iterator
-            metaData = super.generateMetaData(ctx, msg, code, itty);
-        }
-
-        return metaData;
-    }
-
     protected void handleIterator(final Context context, final Iterator itty, final Graph graph) throws InterruptedException {
         final ChannelHandlerContext nettyContext = context.getChannelHandlerContext();
         final RequestMessage msg = context.getRequestMessage();
@@ -511,11 +272,7 @@
         // we have an empty iterator - happens on stuff like: g.V().iterate()
         if (!itty.hasNext()) {
             final Map<String, Object> attributes = generateStatusAttributes(nettyContext, msg, ResponseStatusCode.NO_CONTENT, itty, settings);
-            // if it was a g.V().iterate(), then be sure to add the side-effects to the cache
-            if (itty instanceof TraverserIterator &&
-                    !((TraverserIterator)itty).getTraversal().getSideEffects().isEmpty()) {
-                cache.put(msg.getRequestId(), ((TraverserIterator)itty).getTraversal().getSideEffects());
-            }
+
             // as there is nothing left to iterate if we are transaction managed then we should execute a
             // commit here before we send back a NO_CONTENT which implies success
             onTraversalSuccess(graph, context);
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/SideEffectIterator.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/SideEffectIterator.java
deleted file mode 100644
index 2544634..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/SideEffectIterator.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.server.util;
-
-import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class SideEffectIterator implements Iterator<Object> {
-
-    private final Iterator<Object> sideEffectIterator;
-    private final String sideEffectKey;
-    private final String sideEffectAggregator;
-
-    public SideEffectIterator(final Object sideEffect, final String sideEffectKey) {
-        this.sideEffectKey = sideEffectKey;
-        sideEffectAggregator = getAggregatorType(sideEffect);
-        sideEffectIterator = sideEffect instanceof BulkSet ?
-                new BulkSetIterator((BulkSet) sideEffect) :
-                IteratorUtils.asIterator(sideEffect);
-    }
-
-    public String getSideEffectKey() {
-        return sideEffectKey;
-    }
-
-    public String getSideEffectAggregator() {
-        return sideEffectAggregator;
-    }
-
-    @Override
-    public boolean hasNext() {
-        return sideEffectIterator.hasNext();
-    }
-
-    @Override
-    public Object next() {
-        return sideEffectIterator.next();
-    }
-
-    private String getAggregatorType(final Object o) {
-        if (o instanceof BulkSet)
-            return Tokens.VAL_AGGREGATE_TO_BULKSET;
-        else if (o instanceof Set)
-            return Tokens.VAL_AGGREGATE_TO_SET;
-        else if (o instanceof Iterable || o instanceof Iterator)
-            return Tokens.VAL_AGGREGATE_TO_LIST;
-        else if (o instanceof Map)
-            return Tokens.VAL_AGGREGATE_TO_MAP;
-        else
-            return Tokens.VAL_AGGREGATE_TO_NONE;
-    }
-
-    static class BulkSetIterator implements Iterator {
-
-        private final Iterator<Map.Entry<Object,Long>> itty;
-
-        public BulkSetIterator(final BulkSet<Object> bulkSet) {
-            itty = bulkSet.asBulk().entrySet().iterator();
-        }
-
-        @Override
-        public boolean hasNext() {
-            return itty.hasNext();
-        }
-
-        @Override
-        public Object next() {
-            final Map.Entry<Object, Long> entry = itty.next();
-            return new DefaultRemoteTraverser<>(entry.getKey(), entry.getValue());
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientConnectionIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientConnectionIntegrateTest.java
index 87042dc..bd50750 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientConnectionIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientConnectionIntegrateTest.java
@@ -21,6 +21,7 @@
 import io.netty.handler.codec.CorruptedFrameException;
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
+import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import org.apache.tinkerpop.gremlin.server.AbstractGremlinServerIntegrationTest;
 import org.apache.tinkerpop.gremlin.server.TestClientFactory;
 import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
@@ -70,6 +71,7 @@
     public void shouldCloseConnectionDeadDueToUnRecoverableError() throws Exception {
         // Set a low value of maxContentLength to intentionally trigger CorruptedFrameException
         final Cluster cluster = TestClientFactory.build()
+                                                 .serializer(Serializers.GRYO_V3D0)
                                                  .maxContentLength(64)
                                                  .minConnectionPoolSize(1)
                                                  .maxConnectionPoolSize(2)
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractRemoteGraphProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractRemoteGraphProvider.java
index e86a546..7bf2423 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractRemoteGraphProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractRemoteGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver.remote;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGraphProvider;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.TestHelper;
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java
index fa07ca3..d6e753d 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java
@@ -57,11 +57,7 @@
         reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_injectXg_VX4XX_out_name",
-        reason = "The inject() step is not supported by GraphComputer")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_out_injectXv2X_name",
+        method = "*",
         reason = "The inject() step is not supported by GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MathTest",
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java
index 648de5c..30ecf85 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java
@@ -57,11 +57,7 @@
         reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_injectXg_VX4XX_out_name",
-        reason = "The inject() step is not supported by GraphComputer")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_out_injectXv2X_name",
+        method = "*",
         reason = "The inject() step is not supported by GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MathTest",
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java
index e5c1a4d..6e65989 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java
@@ -58,11 +58,7 @@
         reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_injectXg_VX4XX_out_name",
-        reason = "The inject() step is not supported by GraphComputer")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_out_injectXv2X_name",
+        method = "*",
         reason = "The inject() step is not supported by GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MathTest",
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java
index b594127..2e08aa8 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java
@@ -60,11 +60,7 @@
         reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_injectXg_VX4XX_out_name",
-        reason = "The inject() step is not supported by GraphComputer")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
-        method = "g_VX1X_out_injectXv2X_name",
+        method = "*",
         reason = "The inject() step is not supported by GraphComputer")
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MathTest",
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
index 667c69f..9fa8504 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
@@ -161,7 +161,7 @@
         try {
             Class.forName("org.neo4j.tinkerpop.api.impl.Neo4jGraphAPIImpl");
             neo4jIncludedForTesting = true;
-        } catch (Exception ex) {
+        } catch (Throwable ex) {
             neo4jIncludedForTesting = false;
         }
         assumeThat("Neo4j implementation was not included for testing - run with -DincludeNeo4j", neo4jIncludedForTesting, is(true));
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index d747913..ae766be 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@ -21,7 +21,6 @@
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.log4j.Level;
 import org.apache.tinkerpop.gremlin.TestHelper;
-import org.apache.tinkerpop.gremlin.driver.Channelizer;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.RequestOptions;
@@ -33,6 +32,7 @@
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0;
 import org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer;
 import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0;
@@ -41,7 +41,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.server.channel.NioChannelizer;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.Storage;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
@@ -159,9 +158,6 @@
                     throw new RuntimeException(ex);
                 }
                 break;
-            case "shouldWorkOverNioTransport":
-                settings.channelizer = NioChannelizer.class.getName();
-                break;
             case "shouldFailWithBadClientSideSerialization":
                 final List<String> custom = Arrays.asList(
                         JsonBuilder.class.getName() + ";" + JsonBuilderGryoSerializer.class.getName(),
@@ -193,9 +189,6 @@
             case "shouldProcessEvalInterruption":
                 settings.evaluationTimeout = 1500;
                 break;
-            case "shouldProcessEvalTimeoutOverride":
-                settings.scriptEvaluationTimeout = 15000;
-                break;
         }
 
         return settings;
@@ -228,25 +221,6 @@
     }
 
     @Test
-    public void shouldProcessEvalTimeoutOverride() throws Exception {
-        final Cluster cluster = TestClientFactory.open();
-        final Client client = cluster.connect();
-        try {
-            final RequestOptions options = RequestOptions.build().timeout(500).create();
-
-            try {
-                client.submit("Thread.sleep(5000);'done'", options).all().get();
-                fail("Should have timed out");
-            } catch (Exception ex) {
-                final ResponseException re = (ResponseException) ex.getCause();
-                assertEquals(ResponseStatusCode.SERVER_ERROR_TIMEOUT, re.getResponseStatusCode());
-            }
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
     public void shouldProcessTraversalInterruption() throws Exception {
         final Cluster cluster = TestClientFactory.open();
         final Client client = cluster.connect();
@@ -520,9 +494,8 @@
         final Cluster cluster = TestClientFactory.open();
         final Client client = cluster.connect();
         try {
-            final ResultSet results = client.submit("1/0");
-
             try {
+                final ResultSet results = client.submit("1/0");
                 results.all().join();
                 fail("Should have thrown exception over bad serialization");
             } catch (Exception ex) {
@@ -533,7 +506,7 @@
                 final ResponseException rex = (ResponseException) inner;
                 assertEquals("java.lang.ArithmeticException", rex.getRemoteExceptionHierarchy().get().get(0));
                 assertEquals(1, rex.getRemoteExceptionHierarchy().get().size());
-                assertThat(rex.getRemoteStackTrace().get(), startsWith("java.lang.ArithmeticException: Division by zero\n\tat java.math.BigDecimal.divide(BigDecimal.java"));
+                assertThat(rex.getRemoteStackTrace().get(), containsString("Division by zero"));
             }
 
             // should not die completely just because we had a bad serialization error.  that kind of stuff happens
@@ -632,27 +605,6 @@
     }
 
     @Test
-    public void shouldWorkOverNioTransport() throws Exception {
-        final Cluster cluster = TestClientFactory.build().channelizer(Channelizer.NioChannelizer.class.getName()).create();
-        final Client client = cluster.connect();
-
-        try {
-            final AtomicInteger checked = new AtomicInteger(0);
-            final ResultSet results = client.submit("[1,2,3,4,5,6,7,8,9]");
-            while (!results.allItemsAvailable()) {
-                assertTrue(results.getAvailableItemCount() < 10);
-                checked.incrementAndGet();
-                Thread.sleep(100);
-            }
-
-            assertTrue(checked.get() > 0);
-            assertEquals(9, results.getAvailableItemCount());
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
     public void shouldStream() throws Exception {
         final Cluster cluster = TestClientFactory.open();
         final Client client = cluster.connect();
@@ -858,6 +810,24 @@
     }
 
     @Test
+    public void shouldSerializeToStringWhenRequestedGraphBinaryV1() throws Exception {
+        final Map<String, Object> m = new HashMap<>();
+        m.put("serializeResultToString", true);
+        final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
+        serializer.configure(m, null);
+
+        final Cluster cluster = TestClientFactory.build().serializer(serializer).create();
+        final Client client = cluster.connect();
+
+        final ResultSet resultSet = client.submit("TinkerFactory.createClassic()");
+        final List<Result> results = resultSet.all().join();
+        assertEquals(1, results.size());
+        assertEquals("tinkergraph[vertices:6 edges:6]", results.get(0).getString());
+
+        cluster.close();
+    }
+
+    @Test
     public void shouldSerializeToStringWhenRequestedGryoV1() throws Exception {
         final Map<String, Object> m = new HashMap<>();
         m.put("serializeResultToString", true);
@@ -999,12 +969,11 @@
         final Client client = cluster.connect();
 
         try {
-            final Instant now = Instant.now();
-            final List<Result> r = client.submit("java.time.Instant.ofEpochMilli(" + now.toEpochMilli() + ")").all().join();
+            final List<Result> r = client.submit("java.time.Instant.EPOCH").all().join();
             assertEquals(1, r.size());
 
             final Instant then = r.get(0).get(Instant.class);
-            assertEquals(now, then);
+            assertEquals(Instant.EPOCH, then);
         } finally {
             cluster.close();
         }
@@ -1037,12 +1006,11 @@
         final Client client = cluster.connect();
 
         try {
-            final Instant now = Instant.now();
-            final List<Result> r = client.submit("java.time.Instant.ofEpochMilli(" + now.toEpochMilli() + ")").all().join();
+            final List<Result> r = client.submit("java.time.Instant.EPOCH").all().join();
             assertEquals(1, r.size());
 
             final Instant then = r.get(0).get(Instant.class);
-            assertEquals(now, then);
+            assertEquals(Instant.EPOCH, then);
         } finally {
             cluster.close();
         }
@@ -1171,18 +1139,18 @@
         final Cluster cluster = TestClientFactory.open();
         final Client client = cluster.connect(name.getMethodName());
 
-        final Vertex vertexBeforeTx = client.submit("v=graph.addVertex(\"name\",\"stephen\")").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexBeforeTx.values("name").next());
+        final Vertex vertexBeforeTx = client.submit("v=g.addV(\"person\").property(\"name\",\"stephen\").next()").all().get().get(0).getVertex();
+        assertEquals("person", vertexBeforeTx.label());
 
-        final Vertex vertexFromV = client.submit("graph.vertices().next()").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexFromV.values("name").next());
+        final String nameValueFromV = client.submit("g.V().values('name').next()").all().get().get(0).getString();
+        assertEquals("stephen", nameValueFromV);
 
         final Vertex vertexFromBinding = client.submit("v").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexFromBinding.values("name").next());
+        assertEquals("person", vertexFromBinding.label());
 
-        final Vertex vertexAfterTx = client.submit("v.property(\"color\",\"blue\"); graph.tx().commit(); v").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexAfterTx.values("name").next());
-        assertEquals("blue", vertexAfterTx.values("color").next());
+        final Map<String,Object> vertexAfterTx = client.submit("g.V(v).property(\"color\",\"blue\").iterate(); g.tx().commit(); g.V(v).valueMap().by(unfold())").all().get().get(0).get(Map.class);
+        assertEquals("stephen", vertexAfterTx.get("name"));
+        assertEquals("blue", vertexAfterTx.get("color"));
 
         cluster.close();
     }
@@ -1197,29 +1165,29 @@
         client.submit("graph.tx().onReadWrite(Transaction.READ_WRITE_BEHAVIOR.MANUAL);null").all().get();
         client.submit("graph.tx().open()").all().get();
 
-        final Vertex vertexBeforeTx = client.submit("v=graph.addVertex(\"name\",\"stephen\")").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexBeforeTx.values("name").next());
+        final Vertex vertexBeforeTx = client.submit("v=g.addV(\"person\").property(\"name\", \"stephen\").next()").all().get().get(0).getVertex();
+        assertEquals("person", vertexBeforeTx.label());
 
-        final Vertex vertexFromV = client.submit("graph.vertices().next()").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexFromV.values("name").next());
+        final String nameValueFromV = client.submit("g.V().values(\"name\").next()").all().get().get(0).getString();
+        assertEquals("stephen", nameValueFromV);
 
         final Vertex vertexFromBinding = client.submit("v").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexFromBinding.values("name").next());
+        assertEquals("person", vertexFromBinding.label());
 
-        client.submit("v.property(\"color\",\"blue\")").all().get();
-        client.submit("graph.tx().commit()").all().get();
+        client.submit("g.V(v).property(\"color\",\"blue\")").all().get();
+        client.submit("g.tx().commit()").all().get();
 
         // Run a sessionless request to change transaction.readWriteConsumer back to AUTO
         // The will make the next in session request fail if consumers aren't ThreadLocal
-        sessionlessClient.submit("graph.vertices().next()").all().get();
+        sessionlessClient.submit("g.V().next()").all().get();
 
-        client.submit("graph.tx().open()").all().get();
+        client.submit("g.tx().open()").all().get();
 
-        final Vertex vertexAfterTx = client.submit("graph.vertices().next()").all().get().get(0).getVertex();
-        assertEquals("stephen", vertexAfterTx.values("name").next());
-        assertEquals("blue", vertexAfterTx.values("color").next());
+        final Map<String,Object> vertexAfterTx = client.submit("g.V().valueMap().by(unfold())").all().get().get(0).get(Map.class);
+        assertEquals("stephen", vertexAfterTx.get("name"));
+        assertEquals("blue", vertexAfterTx.get("color"));
 
-        client.submit("graph.tx().rollback()").all().get();
+        client.submit("g.tx().rollback()").all().get();
 
         cluster.close();
     }
@@ -1234,20 +1202,20 @@
             final Client sessionlessClient = cluster.connect();
 
             //open transaction in session, then add vertex and commit
-            sessionClient.submit("graph.tx().open()").all().get();
-            final Vertex vertexBeforeTx = sessionClient.submit("v=graph.addVertex(\"name\",\"stephen\")").all().get().get(0).getVertex();
-            assertEquals("stephen", vertexBeforeTx.values("name").next());
-            sessionClient.submit("graph.tx().commit()").all().get();
+            sessionClient.submit("g.tx().open()").all().get();
+            final Vertex vertexBeforeTx = sessionClient.submit("v=g.addV(\"person\").property(\"name\",\"stephen\").next()").all().get().get(0).getVertex();
+            assertEquals("person", vertexBeforeTx.label());
+            sessionClient.submit("g.tx().commit()").all().get();
 
             // check that session transaction is closed
-            final boolean isOpen = sessionClient.submit("graph.tx().isOpen()").all().get().get(0).getBoolean();
+            final boolean isOpen = sessionClient.submit("g.tx().isOpen()").all().get().get(0).getBoolean();
             assertTrue("Transaction should be closed", !isOpen);
 
             //run a sessionless read
-            sessionlessClient.submit("graph.traversal().V()").all().get();
+            sessionlessClient.submit("g.V()").all().get();
 
             // check that session transaction is still closed
-            final boolean isOpenAfterSessionless = sessionClient.submit("graph.tx().isOpen()").all().get().get(0).getBoolean();
+            final boolean isOpenAfterSessionless = sessionClient.submit("g.tx().isOpen()").all().get().get(0).getBoolean();
             assertTrue("Transaction should stil be closed", !isOpenAfterSessionless);
         } finally {
             cluster.close();
@@ -1444,8 +1412,8 @@
         }
 
         final Client rebound = cluster.connect().alias("graph");
-        final Vertex v = rebound.submit("g.addVertex('name','jason')").all().get().get(0).getVertex();
-        assertEquals("jason", v.value("name"));
+        final Vertex v = rebound.submit("g.addVertex(T.label,'person')").all().get().get(0).getVertex();
+        assertEquals("person", v.label());
 
         cluster.close();
     }
@@ -1456,28 +1424,27 @@
         final Client client = cluster.connect();
 
         try {
-            client.submit("g.addVertex('name','stephen');").all().get().get(0).getVertex();
+            client.submit("g.addVertex(label,'person','name','stephen');").all().get().get(0).getVertex();
             fail("Should have tossed an exception because \"g\" does not have the addVertex method under default config");
         } catch (Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
             assertThat(root, instanceOf(ResponseException.class));
             final ResponseException re = (ResponseException) root;
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, re.getResponseStatusCode());
+            assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, re.getResponseStatusCode());
         }
 
         final Client rebound = cluster.connect().alias("graph");
-        final Vertex v = rebound.submit("g.addVertex('name','jason')").all().get().get(0).getVertex();
-        assertEquals("jason", v.value("name"));
+        final Vertex v = rebound.submit("g.addVertex(label,'person','name','jason')").all().get().get(0).getVertex();
+        assertEquals("person", v.label());
 
         cluster.close();
     }
 
     @Test
     public void shouldAliasTraversalSourceVariables() throws Exception {
-        final Cluster cluster = TestClientFactory.open();
+        final Cluster cluster = TestClientFactory.build().serializer(Serializers.GRYO_V3D0).create();
         final Client client = cluster.connect();
-        try {
-
+        try {    
             try {
                 client.submit("g.addV().property('name','stephen')").all().get().get(0).getVertex();
                 fail("Should have tossed an exception because \"g\" is readonly in this context");
@@ -1485,7 +1452,7 @@
                 final Throwable root = ExceptionUtils.getRootCause(ex);
                 assertThat(root, instanceOf(ResponseException.class));
                 final ResponseException re = (ResponseException) root;
-                assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, re.getResponseStatusCode());
+                assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, re.getResponseStatusCode());
             }
 
             final Client clientAliased = client.alias("g1");
@@ -1498,7 +1465,7 @@
 
     @Test
     public void shouldAliasGraphVariablesInSession() throws Exception {
-        final Cluster cluster = TestClientFactory.open();
+        final Cluster cluster = TestClientFactory.build().serializer(Serializers.GRYO_V3D0).create();
         final Client client = cluster.connect(name.getMethodName());
 
         try {
@@ -1508,7 +1475,7 @@
             final Throwable root = ExceptionUtils.getRootCause(ex);
             assertThat(root, instanceOf(ResponseException.class));
             final ResponseException re = (ResponseException) root;
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, re.getResponseStatusCode());
+            assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, re.getResponseStatusCode());
         }
 
         final Client aliased = client.alias("graph");
@@ -1521,7 +1488,7 @@
 
     @Test
     public void shouldAliasTraversalSourceVariablesInSession() throws Exception {
-        final Cluster cluster = TestClientFactory.open();
+        final Cluster cluster = TestClientFactory.build().serializer(Serializers.GRYO_V3D0).create();
         final Client client = cluster.connect(name.getMethodName());
 
         try {
@@ -1531,7 +1498,7 @@
             final Throwable root = ExceptionUtils.getRootCause(ex);
             assertThat(root, instanceOf(ResponseException.class));
             final ResponseException re = (ResponseException) root;
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, re.getResponseStatusCode());
+            assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, re.getResponseStatusCode());
         }
 
         final Client clientAliased = client.alias("g1");
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuditLogIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuditLogIntegrateTest.java
index 8eb6106..4843c6c 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuditLogIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuditLogIntegrateTest.java
@@ -25,20 +25,19 @@
 import org.apache.http.util.EntityUtils;
 import org.apache.log4j.Logger;
 import org.apache.log4j.spi.LoggingEvent;
-import org.apache.tinkerpop.gremlin.driver.Channelizer;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
+import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
 import org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator;
 import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
 import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
-import org.apache.tinkerpop.gremlin.server.channel.NioChannelizer;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
 import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
 import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.LoggerFactory;
 
@@ -74,7 +73,6 @@
 
     private KdcFixture kdcServer;
 
-    @Before
     @Override
     public void setUp() throws Exception {
         recordingAppender = new Log4jRecordingAppender();
@@ -82,9 +80,10 @@
         rootLogger.addAppender(recordingAppender);
 
         try {
-            final String buildDir = System.getProperty("build.dir");
-            kdcServer = new KdcFixture(buildDir +
-                    "/test-classes/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf");
+            final String moduleBaseDir = System.getProperty("basedir");
+            final String authConfigName = moduleBaseDir + "/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf";
+            System.setProperty("java.security.auth.login.config", authConfigName);
+            kdcServer = new KdcFixture(moduleBaseDir);
             kdcServer.setUp();
         } catch(Exception e)  {
             logger.warn(e.getMessage());
@@ -92,13 +91,14 @@
         super.setUp();
     }
 
-    @After
     @Override
     public void tearDown() throws Exception {
         super.tearDown();
         final Logger rootLogger = Logger.getRootLogger();
         rootLogger.removeAppender(recordingAppender);
         kdcServer.close();
+        System.clearProperty("java.security.auth.login.config");
+        super.tearDown();
     }
 
     /**
@@ -106,7 +106,7 @@
      */
     @Override
     public Settings overrideSettings(final Settings settings) {
-        settings.host = kdcServer.hostname;
+        settings.host = kdcServer.gremlinHostname;
         final Settings.SslSettings sslConfig = new Settings.SslSettings();
         sslConfig.enabled = false;
         settings.ssl = sslConfig;
@@ -122,6 +122,7 @@
             case "shouldAuditLogWithAllowAllAuthenticator":
                 authSettings.authenticator = AllowAllAuthenticator.class.getName();
                 break;
+            case "shouldAuditLogWithTraversalOp":
             case "shouldAuditLogWithSimpleAuthenticator":
                 authSettings.authenticator = SimpleAuthenticator.class.getName();
                 authConfig.put(SimpleAuthenticator.CONFIG_CREDENTIALS_DB, "conf/tinkergraph-credentials.properties");
@@ -133,11 +134,6 @@
                 authConfig.put("keytab", kdcServer.serviceKeytabFile.getAbsolutePath());
                 authConfig.put("principal", kdcServer.serverPrincipal);
                 break;
-            case "shouldAuditLogWithNioTransport":
-                settings.channelizer = NioChannelizer.class.getName();
-                authConfig.put("keytab", kdcServer.serviceKeytabFile.getAbsolutePath());
-                authConfig.put("principal", kdcServer.serverPrincipal);
-                break;
             case "shouldAuditLogWithHttpTransport":
                 settings.host = "localhost";
                 settings.channelizer = HttpChannelizer.class.getName();
@@ -151,7 +147,7 @@
     @Test
     public void shouldAuditLogWithAllowAllAuthenticator() throws Exception {
 
-        final Cluster cluster = TestClientFactory.build().addContactPoint(kdcServer.hostname).create();
+        final Cluster cluster = TestClientFactory.build().addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
 
         try {
@@ -179,7 +175,7 @@
         final String password = "password";
 
         final Cluster cluster = TestClientFactory.build().credentials(username, password)
-                .addContactPoint(kdcServer.hostname).create();
+                .addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
 
         try {
@@ -215,7 +211,7 @@
     @Test
     public void shouldAuditLogWithKrb5Authenticator() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         try {
             assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
@@ -247,7 +243,7 @@
     @Test
     public void shouldNotAuditLogWhenDisabled() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         try {
             assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
@@ -273,38 +269,6 @@
     }
 
     @Test
-    public void shouldAuditLogWithNioTransport() throws Exception {
-        final Cluster cluster = TestClientFactory.build().channelizer(Channelizer.NioChannelizer.class.getName())
-                .jaasEntry(TESTCONSOLE).protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
-        final Client client = cluster.connect();
-        try {
-            assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
-            assertEquals(3, client.submit("1+2").all().get().get(0).getInt());
-            assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
-        } finally {
-            cluster.close();
-        }
-
-        // wait for logger to flush - (don't think there is a way to detect this)
-        stopServer();
-        Thread.sleep(1000);
-
-        final List<LoggingEvent> log = recordingAppender.getEvents();
-        final Stream<LoggingEvent> auditEvents = log.stream().filter(event -> event.getLoggerName().equals(AUDIT_LOGGER_NAME));
-        final LoggingEvent authEvent = auditEvents
-                .filter(event -> event.getMessage().toString().contains("Krb5Authenticator")).iterator().next();
-        final String authMsg = authEvent.getMessage().toString();
-        assertTrue(authEvent.getLevel() == INFO &&
-                authMsg.matches(String.format("User %s with address .*? authenticated by Krb5Authenticator", kdcServer.clientPrincipalName)));
-        assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
-                item.getMessage().toString().matches("User with address .*? requested: 1\\+1")));
-        assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
-                item.getMessage().toString().matches("User with address .*? requested: 1\\+2")));
-        assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
-                item.getMessage().toString().matches("User with address .*? requested: 1\\+3")));
-    }
-
-    @Test
     public void shouldAuditLogWithHttpTransport() throws Exception {
         final CloseableHttpClient httpclient = HttpClients.createDefault();
         final HttpGet httpget = new HttpGet(TestClientFactory.createURLString("?gremlin=1-1"));
@@ -336,12 +300,46 @@
     }
 
     @Test
+    public void shouldAuditLogWithTraversalOp() throws Exception {
+        final String username = "stephen";
+        final String password = "password";
+
+        final Cluster cluster = TestClientFactory.build().credentials(username, password)
+                .addContactPoint(kdcServer.gremlinHostname).create();
+        final Client client = cluster.connect();
+        final GraphTraversalSource g = AnonymousTraversalSource.traversal().
+                withRemote(DriverRemoteConnection.using(cluster, "gmodern"));
+
+        try {
+            assertEquals(6, g.V().count().next().intValue());
+        } finally {
+            cluster.close();
+        }
+
+        // wait for logger to flush - (don't think there is a way to detect this)
+        stopServer();
+        Thread.sleep(1000);
+
+        final String simpleAuthenticatorName = SimpleAuthenticator.class.getSimpleName();
+
+        final List<LoggingEvent> log = recordingAppender.getEvents();
+        final Stream<LoggingEvent> auditEvents = log.stream().filter(event -> event.getLoggerName().equals(AUDIT_LOGGER_NAME));
+        final LoggingEvent authEvent = auditEvents
+                .filter(event -> event.getMessage().toString().contains(simpleAuthenticatorName)).iterator().next();
+        final String authMsg = authEvent.getMessage().toString();
+        assertTrue(authEvent.getLevel() == INFO &&
+                authMsg.matches(String.format("User %s with address .*? authenticated by %s", username, simpleAuthenticatorName)));
+        assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+                item.getMessage().toString().matches("User with address .*? requested: \\[\\[], \\[V\\(\\), count\\(\\)]]")));
+    }
+
+    @Test
     public void shouldAuditLogTwoClientsWithKrb5Authenticator() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         final Cluster cluster2 = TestClientFactory.build().jaasEntry(TESTCONSOLE2)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client2 = cluster2.connect();
         try {
             assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthKrb5IntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthKrb5IntegrateTest.java
index 029a408..476e962 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthKrb5IntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthKrb5IntegrateTest.java
@@ -29,7 +29,6 @@
 import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0;
 import org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator;
 import org.ietf.jgss.GSSException;
-import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.LoggerFactory;
 
@@ -54,13 +53,13 @@
 
     private KdcFixture kdcServer;
 
-    @Before
     @Override
     public void setUp() throws Exception {
         try {
-            final String buildDir = System.getProperty("build.dir");
-            kdcServer = new KdcFixture(buildDir +
-                    "/test-classes/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf");
+            final String projectBaseDir = System.getProperty("basedir");
+            final String authConfigName = projectBaseDir + "/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf";
+            System.setProperty("java.security.auth.login.config", authConfigName);
+            kdcServer = new KdcFixture(projectBaseDir);
             kdcServer.setUp();
         } catch(Exception e)  {
             logger.warn(e.getMessage());
@@ -68,12 +67,19 @@
         super.setUp();
     }
 
+    @Override
+    public void tearDown() throws Exception {
+        kdcServer.close();
+        System.clearProperty("java.security.auth.login.config");
+        super.tearDown();
+    }
+
     /**
      * Configure specific Gremlin Server settings for specific tests.
      */
     @Override
     public Settings overrideSettings(final Settings settings) {
-        settings.host = kdcServer.hostname;
+        settings.host = kdcServer.gremlinHostname;
         final Settings.SslSettings sslConfig = new Settings.SslSettings();
         sslConfig.enabled = false;
         settings.ssl = sslConfig;
@@ -120,7 +126,7 @@
     @Test
     public void shouldAuthenticateWithDefaults() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         assertConnection(cluster, client);
     }
@@ -128,7 +134,7 @@
     @Test
     public void shouldFailWithoutClientJaasEntry() throws Exception {
         final Cluster cluster = TestClientFactory.build().protocol(kdcServer.serverPrincipalName)
-                .addContactPoint(kdcServer.hostname).create();
+                .addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         try {
             client.submit("1+1").all().get();
@@ -144,7 +150,7 @@
     @Test
     public void shouldFailWithoutClientTicketCache() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE_NOT_LOGGED_IN)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         try {
             client.submit("1+1").all().get();
@@ -177,7 +183,7 @@
         final String oldQop = System.getProperty("javax.security.sasl.qop", "");
         System.setProperty("javax.security.sasl.qop", "auth-conf");
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         try {
             assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
@@ -192,7 +198,7 @@
     @Test
     public void shouldAuthenticateWithSsl() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE).enableSsl(true).sslSkipCertValidation(true)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         assertConnection(cluster, client);
     }
@@ -217,7 +223,7 @@
         config.put("serializeResultToString", true);
         serializer.configure(config, null);
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).serializer(serializer).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).serializer(serializer).create();
         final Client client = cluster.connect();
         assertConnection(cluster, client);
     }
@@ -237,7 +243,7 @@
      */
     private void assertFailedLogin() throws Exception {
         final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
-                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+                .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.gremlinHostname).create();
         final Client client = cluster.connect();
         try {
             client.submit("1+1").all().get();
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
index 0bd9ecf..f34b0f2 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
@@ -49,6 +49,7 @@
 import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.StringContains.containsString;
 import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertEquals;
 
@@ -773,7 +774,7 @@
             final JsonNode node = mapper.readTree(json);
             assertEquals("java.lang.ArithmeticException", node.get(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS).get(0).asText());
             assertEquals(1, node.get(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS).size());
-            assertThat(node.get(Tokens.STATUS_ATTRIBUTE_STACK_TRACE).asText(), startsWith("java.lang.ArithmeticException: Division by zero\n\tat java.math.BigDecimal.divide(BigDecimal.java"));
+            assertThat(node.get(Tokens.STATUS_ATTRIBUTE_STACK_TRACE).asText(), containsString("Division by zero"));
         }
     }
 
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index 23d4fe0..6e9f166 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.server;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
@@ -34,7 +34,6 @@
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
-import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversalSideEffects;
 import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import org.apache.tinkerpop.gremlin.driver.simple.SimpleClient;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
@@ -43,10 +42,8 @@
 import org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin;
 import org.apache.tinkerpop.gremlin.structure.RemoteGraph;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.apache.tinkerpop.gremlin.server.handler.OpSelectorHandler;
 import org.apache.tinkerpop.gremlin.server.op.AbstractEvalOpProcessor;
 import org.apache.tinkerpop.gremlin.server.op.standard.StandardOpProcessor;
@@ -60,13 +57,12 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import java.lang.reflect.Field;
+
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -76,7 +72,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_SCRIPT_EVAL_TIMEOUT;
+import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_EVAL_TIMEOUT;
 import static org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin.Compilation.COMPILE_STATIC;
 import static org.apache.tinkerpop.gremlin.process.remote.RemoteConnection.GREMLIN_REMOTE;
 import static org.apache.tinkerpop.gremlin.process.remote.RemoteConnection.GREMLIN_REMOTE_CONNECTION_CLASS;
@@ -91,12 +87,14 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+
 /**
  * Integration tests for server-side settings and processing.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegrationTest {
+
     private Level previousLogLevel;
 
     private Log4jRecordingAppender recordingAppender = null;
@@ -195,9 +193,6 @@
             case "shouldTimeOutRemoteTraversal":
                 settings.evaluationTimeout = 500;
                 break;
-            case "shouldTimeOutRemoteTraversalUsingDeprecatedConfiguration":
-                settings.scriptEvaluationTimeout = 500;
-                break;
             case "shouldPingChannelIfClientDies":
                 settings.keepAliveInterval = 1000;
                 break;
@@ -249,7 +244,7 @@
         } catch (Exception ex) {
             final Throwable t = ex.getCause();
             assertThat(t, instanceOf(ResponseException.class));
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, ((ResponseException) t).getResponseStatusCode());
+            assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, ((ResponseException) t).getResponseStatusCode());
         }
 
         // make a graph with a cycle in it to force a long run traversal
@@ -327,40 +322,12 @@
     }
 
     @Test
-    public void shouldTimeOutRemoteTraversalUsingDeprecatedConfiguration() throws Exception {
-        final GraphTraversalSource g = traversal().withRemote(conf);
-
-        try {
-            // tests sleeping thread
-            g.inject(1).sideEffect(Lambda.consumer("Thread.sleep(10000)")).iterate();
-            fail("This traversal should have timed out");
-        } catch (Exception ex) {
-            final Throwable t = ex.getCause();
-            assertThat(t, instanceOf(ResponseException.class));
-            assertEquals(ResponseStatusCode.SERVER_ERROR_TIMEOUT, ((ResponseException) t).getResponseStatusCode());
-        }
-
-        // make a graph with a cycle in it to force a long run traversal
-        graphGetter.get().traversal().addV("person").as("p").addE("self").to("p").iterate();
-
-        try {
-            // tests an "unending" traversal
-            g.V().repeat(__.out()).until(__.outE().count().is(0)).iterate();
-            fail("This traversal should have timed out");
-        } catch (Exception ex) {
-            final Throwable t = ex.getCause();
-            assertThat(t, instanceOf(ResponseException.class));
-            assertEquals(ResponseStatusCode.SERVER_ERROR_TIMEOUT, ((ResponseException) t).getResponseStatusCode());
-        }
-    }
-
-    @Test
     public void shouldTimeOutRemoteTraversalWithPerRequestOption() {
         final GraphTraversalSource g = traversal().withRemote(conf);
 
         try {
             // tests sleeping thread
-            g.with(ARGS_SCRIPT_EVAL_TIMEOUT, 500L).inject(1).sideEffect(Lambda.consumer("Thread.sleep(10000)")).iterate();
+            g.with(ARGS_EVAL_TIMEOUT, 500L).inject(1).sideEffect(Lambda.consumer("Thread.sleep(10000)")).iterate();
             fail("This traversal should have timed out");
         } catch (Exception ex) {
             final Throwable t = ex.getCause();
@@ -373,7 +340,7 @@
 
         try {
             // tests an "unending" traversal
-            g.with(ARGS_SCRIPT_EVAL_TIMEOUT, 500L).V().repeat(__.out()).until(__.outE().count().is(0)).iterate();
+            g.with(ARGS_EVAL_TIMEOUT, 500L).V().repeat(__.out()).until(__.outE().count().is(0)).iterate();
             fail("This traversal should have timed out");
         } catch (Exception ex) {
             final Throwable t = ex.getCause();
@@ -741,22 +708,6 @@
 
     @Test
     @SuppressWarnings("unchecked")
-    public void shouldReceiveFailureTimeOutOnScriptEvalUsingOverride() throws Exception {
-        try (SimpleClient client = TestClientFactory.createWebSocketClient()) {
-            final RequestMessage msg = RequestMessage.build("eval")
-                    .addArg(ARGS_SCRIPT_EVAL_TIMEOUT, 100L)
-                    .addArg(Tokens.ARGS_GREMLIN, "Thread.sleep(3000);'some-stuff-that-should not return'")
-                    .create();
-            final List<ResponseMessage> responses = client.submit(msg);
-            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Evaluation exceeded the configured 'evaluationTimeout' threshold of 100 ms"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
     public void shouldReceiveFailureTimeOutOnEvalUsingOverride() throws Exception {
         try (SimpleClient client = TestClientFactory.createWebSocketClient()) {
             final RequestMessage msg = RequestMessage.build("eval")
@@ -821,7 +772,7 @@
         final Client client = cluster.connect();
 
         try {
-            client.submit("def class C { def C getC(){return this}}; new C()").all().join();
+            client.submit("class C { def C getC(){return this}}; new C()").all().join();
             fail("Should throw an exception.");
         } catch (RuntimeException re) {
             final Throwable root = ExceptionUtils.getRootCause(re);
@@ -962,7 +913,7 @@
             final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
                     .addArg(Tokens.ARGS_GREMLIN, "new String().doNothingAtAllBecauseThis is a syntax error").create();
             final List<ResponseMessage> responses = client.submit(request);
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, responses.get(0).getStatus().getCode());
+            assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, responses.get(0).getStatus().getCode());
             assertEquals(1, responses.size());
         }
     }
@@ -976,178 +927,6 @@
     }
 
     @Test
-    public void shouldGetSideEffectKeysAndStatusUsingWithRemote() throws Exception {
-        final GraphTraversalSource g = traversal().withRemote(conf);
-        g.addV("person").property("age", 20).iterate();
-        g.addV("person").property("age", 10).iterate();
-        final GraphTraversal traversal = g.V().aggregate("a").aggregate("b");
-        traversal.iterate();
-        final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
-        assertThat(se.statusAttributes().containsKey(Tokens.ARGS_HOST), is(true));
-
-        // Get keys
-        final Set<String> sideEffectKeys = se.keys();
-        assertEquals(2, sideEffectKeys.size());
-
-        // Get side effects
-        final BulkSet aSideEffects = se.get("a");
-        assertThat(aSideEffects.isEmpty(), is(false));
-        final BulkSet bSideEffects = se.get("b");
-        assertThat(bSideEffects.isEmpty(), is(false));
-
-        // Should get local keys/side effects after close
-        se.close();
-
-        final Set<String> localSideEffectKeys = se.keys();
-        assertEquals(2, localSideEffectKeys.size());
-
-        final BulkSet localASideEffects = se.get("a");
-        assertThat(localASideEffects.isEmpty(), is(false));
-
-        final BulkSet localBSideEffects = se.get("b");
-        assertThat(localBSideEffects.isEmpty(), is(false));
-
-        final GraphTraversal gdotv = g.V();
-        gdotv.toList();
-        final DriverRemoteTraversalSideEffects gdotvSe = (DriverRemoteTraversalSideEffects) gdotv.asAdmin().getSideEffects();
-        assertThat(gdotvSe.statusAttributes().containsKey(Tokens.ARGS_HOST), is(true));
-    }
-
-    @Test
-    public void shouldCloseSideEffectsUsingWithRemote() throws Exception {
-        final GraphTraversalSource g = traversal().withRemote(conf);
-        g.addV("person").property("age", 20).iterate();
-        g.addV("person").property("age", 10).iterate();
-        final GraphTraversal traversal = g.V().aggregate("a").aggregate("b");
-        traversal.iterate();
-        final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
-        final BulkSet sideEffects = se.get("a");
-        assertThat(sideEffects.isEmpty(), is(false));
-        se.close();
-
-        // Can't get new side effects after close
-        try {
-            se.get("b");
-            fail("The traversal is closed");
-        } catch (Exception ex) {
-            assertThat(ex, instanceOf(IllegalStateException.class));
-            assertEquals("Traversal has been closed - no new side-effects can be retrieved", ex.getMessage());
-        }
-
-        // Earlier keys should be cached locally
-        final Set<String> localSideEffectKeys = se.keys();
-        assertEquals(2, localSideEffectKeys.size());
-        final BulkSet localSideEffects = se.get("a");
-        assertThat(localSideEffects.isEmpty(), is(false));
-
-        // Try to get side effect from server
-        final Cluster cluster = TestClientFactory.open();
-        final Client client = cluster.connect();
-        final Field field = DriverRemoteTraversalSideEffects.class.getDeclaredField("serverSideEffect");
-        field.setAccessible(true);
-        final UUID serverSideEffectId = (UUID) field.get(se);
-        final Map<String, String> aliases = new HashMap<>();
-        aliases.put("g", "g");
-        final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)
-                .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffectId)
-                .addArg(Tokens.ARGS_SIDE_EFFECT_KEY, "b")
-                .addArg(Tokens.ARGS_ALIASES, aliases)
-                .processor("traversal").create();
-        boolean error;
-        try {
-            client.submitAsync(msg).get().one();
-            error = false;
-        } catch (Exception ex) {
-            error = true;
-        }
-        assertThat(error, is(true));
-    }
-
-    @Test
-    public void shouldBlockWhenGettingSideEffectKeysUsingWithRemote() throws Exception {
-        final GraphTraversalSource g = traversal().withRemote(conf);
-        g.addV("person").property("age", 20).iterate();
-        g.addV("person").property("age", 10).iterate();
-        final GraphTraversal traversal = g.V().aggregate("a")
-                .sideEffect(Lambda.consumer("{Thread.sleep(3000)}"))
-                .aggregate("b");
-
-        // force strategy application - if this doesn't happen then getSideEffects() returns DefaultTraversalSideEffects
-        traversal.hasNext();
-
-        // start a separate thread to iterate
-        final Thread t = new Thread(traversal::iterate);
-        t.start();
-
-        // blocks here until traversal iteration is complete
-        final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
-
-        // Get keys
-        final Set<String> sideEffectKeys = se.keys();
-        assertEquals(2, sideEffectKeys.size());
-
-        // Get side effects
-        final BulkSet aSideEffects = se.get("a");
-        assertThat(aSideEffects.isEmpty(), is(false));
-        final BulkSet bSideEffects = se.get("b");
-        assertThat(bSideEffects.isEmpty(), is(false));
-
-        // Should get local keys/side effects after close
-        se.close();
-
-        final Set<String> localSideEffectKeys = se.keys();
-        assertEquals(2, localSideEffectKeys.size());
-
-        final BulkSet localASideEffects = se.get("a");
-        assertThat(localASideEffects.isEmpty(), is(false));
-
-        final BulkSet localBSideEffects = se.get("b");
-        assertThat(localBSideEffects.isEmpty(), is(false));
-    }
-
-    @Test
-    public void shouldBlockWhenGettingSideEffectValuesUsingWithRemote() throws Exception {
-        final GraphTraversalSource g = traversal().withRemote(conf);
-        g.addV("person").property("age", 20).iterate();
-        g.addV("person").property("age", 10).iterate();
-        final GraphTraversal traversal = g.V().aggregate("a")
-                .sideEffect(Lambda.consumer("{Thread.sleep(3000)}"))
-                .aggregate("b");
-
-        // force strategy application - if this doesn't happen then getSideEffects() returns DefaultTraversalSideEffects
-        traversal.hasNext();
-
-        // start a separate thread to iterate
-        final Thread t = new Thread(traversal::iterate);
-        t.start();
-
-        // blocks here until traversal iteration is complete
-        final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
-
-        // Get side effects
-        final BulkSet aSideEffects = se.get("a");
-        assertThat(aSideEffects.isEmpty(), is(false));
-        final BulkSet bSideEffects = se.get("b");
-        assertThat(bSideEffects.isEmpty(), is(false));
-
-        // Get keys
-        final Set<String> sideEffectKeys = se.keys();
-        assertEquals(2, sideEffectKeys.size());
-
-        // Should get local keys/side effects after close
-        se.close();
-
-        final Set<String> localSideEffectKeys = se.keys();
-        assertEquals(2, localSideEffectKeys.size());
-
-        final BulkSet localASideEffects = se.get("a");
-        assertThat(localASideEffects.isEmpty(), is(false));
-
-        final BulkSet localBSideEffects = se.get("b");
-        assertThat(localBSideEffects.isEmpty(), is(false));
-    }
-
-    @Test
     public void shouldDoNonBlockingPromiseWithRemote() throws Exception {
         final GraphTraversalSource g = traversal().withRemote(conf);
         g.addV("person").property("age", 20).promise(Traversal::iterate).join();
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
index ddf39d3..3dc58ae 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
@@ -49,7 +49,7 @@
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.IsCollectionContaining.hasItem;
+import static org.hamcrest.core.IsIterableContaining.hasItem;
 import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
@@ -70,8 +70,7 @@
         switch (nameOfTest) {
             case "shouldCloseSessionOnceOnRequest":
             case "shouldHaveTheSessionTimeout":
-            case "shouldBlockAdditionalRequestsDuringClose":
-            case "shouldBlockAdditionalRequestsDuringForceClose":
+            case "shouldCloseSessionOnClientClose":
                 Logger.getRootLogger().setLevel(Level.INFO);
                 break;
         }
@@ -101,8 +100,7 @@
                 processorSettings.config.put(SessionOpProcessor.CONFIG_SESSION_TIMEOUT, 3000L);
                 settings.processors.add(processorSettings);
                 break;
-            case "shouldBlockAdditionalRequestsDuringClose":
-            case "shouldBlockAdditionalRequestsDuringForceClose":
+            case "shouldCloseSessionOnClientClose":
                 clearNeo4j(settings);
                 break;
             case "shouldEnsureSessionBindingsAreThreadSafe":
@@ -132,6 +130,38 @@
     }
 
     @Test
+    public void shouldCloseSessionOnClientClose() throws Exception {
+        assumeNeo4jIsPresent();
+
+        final Cluster cluster1 = TestClientFactory.open();
+        final Client client1 = cluster1.connect(name.getMethodName());
+        client1.submit("x = 1").all().join();
+        client1.submit("graph.addVertex()").all().join();
+        client1.close();
+        cluster1.close();
+
+        assertThat(recordingAppender.getMessages(), hasItem("INFO - Skipped attempt to close open graph transactions on shouldCloseSessionOnClientClose - close was forced\n"));
+        assertThat(recordingAppender.getMessages(), hasItem("INFO - Session shouldCloseSessionOnClientClose closed\n"));
+
+        // try to reconnect to that session and make sure no state is there
+        final Cluster clusterReconnect = TestClientFactory.open();
+        final Client clientReconnect = clusterReconnect.connect(name.getMethodName());
+
+        // should get an error because "x" is not defined as this is a new session
+        try {
+            clientReconnect.submit("x").all().join();
+            fail("Should not have been successful as 'x' was only defined in the old session");
+        } catch(Exception ex) {
+            final Throwable root = ExceptionUtils.getRootCause(ex);
+            assertThat(root.getMessage(), startsWith("No such property"));
+        }
+
+        // the commit from client1 should not have gone through so there should be no data present.
+        assertEquals(0, clientReconnect.submit("graph.traversal().V().count()").all().join().get(0).getInt());
+        clusterReconnect.close();
+    }
+
+    @Test
     public void shouldUseGlobalFunctionCache() throws Exception {
         final Cluster cluster = TestClientFactory.open();
         final Client client = cluster.connect(name.getMethodName());
@@ -168,85 +198,24 @@
     }
 
     @Test
-    public void shouldBlockAdditionalRequestsDuringClose() throws Exception {
-        assumeNeo4jIsPresent();
-
-        // this is sorta cobbled together a bit given limits/rules about how you can use Cluster/Client instances.
-        // basically, we need one to submit the long run job and one to do the close operation that will cancel the
-        // long run job. it is probably possible to do this with some low-level message manipulation but that's
-        // probably not necessary
-        //
-        // this test wont work so well once we remove the sending of the session close message from the driver which
-        // got deprecated at 3.3.11 and lock a session to the connection that created it. in that case, two Client
-        // instances won't be able to connect to the same session which is what is happening below. not sure what
-        // form this test should take then especially since transactions will force close when the channel closes.
-        // perhaps it should just be removed.
+    public void shouldNotAllowMoreThanOneClientPerSession() throws Exception {
         final Cluster cluster1 = TestClientFactory.open();
         final Client client1 = cluster1.connect(name.getMethodName());
-        client1.submit("graph.addVertex()").all().join();
-        final Cluster cluster2 = TestClientFactory.open();
-        final Client client2 = cluster2.connect(name.getMethodName());
-        client2.submit("1+1").all().join();
-
-        final ResultSet rs = client1.submit("Thread.sleep(3000);1+1");
-
-        // close while the previous request is still executing
-        client2.close();
-
-        assertEquals(2, rs.all().join().get(0).getInt());
-
-        client1.close();
-
-        cluster1.close();
-        cluster2.close();
-
-        // triggered an error during close and since we didn't force close, the attempt to close the transaction
-        // is made
-        assertThat(recordingAppender.getMessages(), hasItem("INFO - Rolling back open transactions on graph before killing session: " + name.getMethodName() + "\n"));
-
-    }
-
-    @Test
-    public void shouldBlockAdditionalRequestsDuringForceClose() throws Exception {
-        assumeNeo4jIsPresent();
-
-        // this is sorta cobbled together a bit given limits/rules about how you can use Cluster/Client instances.
-        // basically, we need one to submit the long run job and one to do the close operation that will cancel the
-        // long run job. it is probably possible to do this with some low-level message manipulation but that's
-        // probably not necessary
-        //
-        // this test wont work so well once we remove the sending of the session close message from the driver which
-        // got deprecated at 3.3.11 and lock a session to the connection that created it. in that case, two Client
-        // instances won't be able to connect to the same session which is what is happening below. not sure what
-        // form this test should take then especially since transactions will force close when the channel closes.
-        // perhaps it should just be removed.
-        final Cluster cluster1 = TestClientFactory.open();
-        final Client client1 = cluster1.connect(name.getMethodName());
-        client1.submit("graph.addVertex()").all().join();
+        client1.submit("1+1").all().join();
         final Cluster cluster2 = TestClientFactory.open();
         final Client.SessionSettings sessionSettings = Client.SessionSettings.build()
                 .sessionId(name.getMethodName())
                 .forceClosed(true).create();
         final Client client2 = cluster2.connect(Client.Settings.build().useSession(sessionSettings).create());
-        client2.submit("1+1").all().join();
-
-        final ResultSet rs = client1.submit("Thread.sleep(10000);1+1");
-
-        client2.close();
-
-        // because the close was forced, the message should appear immediately
-        assertThat(recordingAppender.getMessages(), hasItem("INFO - Skipped attempt to close open graph transactions on " + name.getMethodName() + " - close was forced\n"));
 
         try {
-            rs.all().join();
-            fail("The close of the session on client2 should have interrupted the script sent on client1");
+            client2.submit("2+2").all().join();
+            fail("Can't have more than one client connecting to the same session");
         } catch (Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
-            assertThat(root.getMessage(), startsWith("Evaluation exceeded the configured 'evaluationTimeout' threshold of 30000 ms or evaluation was otherwise cancelled directly for request"));
+            assertEquals("Session shouldNotAllowMoreThanOneClientPerSession is not bound to the connecting client", root.getMessage());
         }
 
-        client1.close();
-
         cluster1.close();
         cluster2.close();
     }
@@ -331,7 +300,7 @@
         } catch (Exception ex) {
             final Throwable cause = ExceptionUtils.getCause(ex);
             assertThat(cause, instanceOf(ResponseException.class));
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, ((ResponseException) cause).getResponseStatusCode());
+            assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, ((ResponseException) cause).getResponseStatusCode());
 
             // validate that we can still send messages to the server
             assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
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 ab75b8e..dd3aa80 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
@@ -39,10 +39,6 @@
 import static org.junit.Assert.fail;
 
 public class GremlinServerSslIntegrateTest extends AbstractGremlinServerIntegrationTest {
-    private static final String PEM_SERVER_KEY = "src/test/resources/server.key.pk8";
-    private static final String PEM_SERVER_CRT = "src/test/resources/server.crt";
-    private static final String PEM_CLIENT_KEY = "src/test/resources/client.key.pk8";
-    private static final String PEM_CLIENT_CRT = "src/test/resources/client.crt";
 
     /**
      * Configure specific Gremlin Server settings for specific tests.
@@ -64,28 +60,6 @@
                 settings.ssl.enabled = true;
                 settings.ssl.overrideSslContext(createServerSslContext());
                 break;
-            case "shouldEnableSslAndClientCertificateAuthWithLegacyPem":
-            case "shouldEnableSslAndClientCertificateAuthAndFailWithoutCertWithLegacyPem":
-                settings.ssl = new Settings.SslSettings();
-                settings.ssl.enabled = true;
-                settings.ssl.needClientAuth = ClientAuth.REQUIRE;
-                settings.ssl.keyCertChainFile = PEM_SERVER_CRT;
-                settings.ssl.keyFile = PEM_SERVER_KEY;
-                settings.ssl.keyPassword = KEY_PASS;
-                // Trust the client
-                settings.ssl.trustCertChainFile = PEM_CLIENT_CRT;
-                break;
-            // Trust the client
-            case "shouldEnableSslAndClientCertificateAuthAndFailWithoutTrustedClientCertWithLegacyPem":
-                settings.ssl = new Settings.SslSettings();
-                settings.ssl.enabled = true;
-                settings.ssl.needClientAuth = ClientAuth.REQUIRE;
-                settings.ssl.keyCertChainFile = PEM_SERVER_CRT;
-                settings.ssl.keyFile = PEM_SERVER_KEY;
-                settings.ssl.keyPassword = KEY_PASS;
-                // Trust ONLY the server cert
-                settings.ssl.trustCertChainFile = PEM_SERVER_CRT;
-                break;
             case "shouldEnableSslAndClientCertificateAuthWithPkcs12":
                 settings.ssl = new Settings.SslSettings();
                 settings.ssl.enabled = true;
@@ -210,54 +184,6 @@
     }
 
     @Test
-    public void shouldEnableSslAndClientCertificateAuthWithLegacyPem() {
-        final Cluster cluster = TestClientFactory.build().enableSsl(true)
-                .keyCertChainFile(PEM_CLIENT_CRT).keyFile(PEM_CLIENT_KEY)
-                .keyPassword(KEY_PASS).trustCertificateChainFile(PEM_SERVER_CRT).create();
-        final Client client = cluster.connect();
-
-        try {
-            assertEquals("test", client.submit("'test'").one().getString());
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldEnableSslAndClientCertificateAuthAndFailWithoutCertWithLegacyPem() {
-        final Cluster cluster = TestClientFactory.build().enableSsl(true).keyStore(JKS_SERVER_KEY).keyStorePassword(KEY_PASS).sslSkipCertValidation(true).create();
-        final Client client = cluster.connect();
-
-        try {
-            client.submit("'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) {
-            final Throwable root = ExceptionUtils.getRootCause(x);
-            assertThat(root, instanceOf(TimeoutException.class));
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldEnableSslAndClientCertificateAuthAndFailWithoutTrustedClientCertWithLegacyPem() {
-        final Cluster cluster = TestClientFactory.build().enableSsl(true)
-                .keyCertChainFile(PEM_CLIENT_CRT).keyFile(PEM_CLIENT_KEY)
-                .keyPassword(KEY_PASS).trustCertificateChainFile(PEM_SERVER_CRT).create();
-        final Client client = cluster.connect();
-
-        try {
-            client.submit("'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) {
-            final Throwable root = ExceptionUtils.getRootCause(x);
-            assertThat(root, instanceOf(TimeoutException.class));
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
     public void shouldEnableSslAndClientCertificateAuthWithPkcs12() {
         final Cluster cluster = TestClientFactory.build().enableSsl(true).keyStore(P12_CLIENT_KEY).keyStorePassword(KEY_PASS)
                 .keyStoreType(KEYSTORE_TYPE_PKCS12).trustStore(P12_CLIENT_TRUST).trustStorePassword(KEY_PASS).create();
@@ -377,42 +303,4 @@
             cluster2.close();
         }
     }
-
-    @Test
-    public void shouldEnableSslAndClientCertificateAuthAndFailWithIncorrectKeyStoreType() {
-        final Cluster cluster = TestClientFactory.build().enableSsl(true)
-                .keyStore(JKS_CLIENT_KEY).keyStorePassword(KEY_PASS).keyStoreType(KEYSTORE_TYPE_PKCS12)
-                .trustStore(P12_CLIENT_TRUST).trustStorePassword(KEY_PASS).trustStoreType(TRUSTSTORE_TYPE_PKCS12)
-                .create();
-        final Client client = cluster.connect();
-
-        try {
-            String res = client.submit("'test'").one().getString();
-            fail("Should throw exception because incorrect keyStoreType is specified");
-        } catch (Exception x) {
-            final Throwable root = ExceptionUtils.getRootCause(x);
-            assertThat(root, instanceOf(TimeoutException.class));
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldEnableSslAndClientCertificateAuthAndFailWithIncorrectTrustStoreType() {
-        final Cluster cluster = TestClientFactory.build().enableSsl(true)
-                .keyStore(P12_CLIENT_KEY).keyStorePassword(KEY_PASS).keyStoreType(KEYSTORE_TYPE_PKCS12)
-                .trustStore(JKS_CLIENT_TRUST).trustStorePassword(KEY_PASS).trustStoreType(TRUSTSTORE_TYPE_PKCS12)
-                .create();
-        final Client client = cluster.connect();
-
-        try {
-            client.submit("'test'").one();
-            fail("Should throw exception because incorrect trustStoreType is specified");
-        } catch (Exception x) {
-            final Throwable root = ExceptionUtils.getRootCause(x);
-            assertThat(root, instanceOf(TimeoutException.class));
-        } finally {
-            cluster.close();
-        }
-    }
 }
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
deleted file mode 100644
index 0234e24..0000000
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.server;
-
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.client.KrbClient;
-import org.apache.kerby.kerberos.kerb.client.KrbConfig;
-import org.apache.kerby.kerberos.kerb.client.KrbConfigKey;
-import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
-import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
-import org.apache.kerby.util.NetworkUtil;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.net.Inet4Address;
-
-
-/**
- * This class is derived from the following classes from https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0-RC2:
- *  - org.apache.kerby.kerberos.kerb.server.TestKdcServer
- *  - org.apache.kerby.kerberos.kerb.server.KdcTestBase
- *  - org.apache.kerby.kerberos.kerb.server.LoginTestBase
- *
- * See also: gremlin-server/src/main/static/NOTICE
- *
- * @author Marc de Lignie
- */
-public class KdcFixture {
-
-    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KdcFixture.class);
-
-    final String clientPassword = "123456";
-    final String clientPassword2 = "1234562";
-    final String clientPrincipalName = "drankye";
-    final String clientPrincipalName2 = "drankye2";
-    final String serverPrincipalName = "test-service";
-    final String ticketCacheFileName = "test-tkt.cc";
-    final String ticketCacheFileName2 = "test-tkt2.cc";
-    final String serviceKeytabFileName = "test-service.keytab";
-
-    final String clientPrincipal;
-    final String clientPrincipal2;
-    final String serverPrincipal;
-    final File testDir;
-    final File ticketCacheFile;
-    final File ticketCacheFile2;
-    final File serviceKeytabFile;
-
-    final String hostname;
-    private SimpleKdcServer kdcServer;
-
-    public KdcFixture(final String authConfigName) {
-        System.setProperty("java.security.auth.login.config", authConfigName);
-        hostname = findHostname();
-        serverPrincipal = serverPrincipalName + "/" + hostname + "@" + KdcFixture.TestKdcServer.KDC_REALM;
-        clientPrincipal = clientPrincipalName + "@" + KdcFixture.TestKdcServer.KDC_REALM;
-        clientPrincipal2 = clientPrincipalName2 + "@" + KdcFixture.TestKdcServer.KDC_REALM;
-        testDir = createTestDir();
-        ticketCacheFile = new File(testDir, ticketCacheFileName);
-        ticketCacheFile2 = new File(testDir, ticketCacheFileName2);
-        serviceKeytabFile = new File(testDir, serviceKeytabFileName);
-    }
-
-    private String findHostname() {
-        // Hostname setting must be consistent with the way gremlin-console sets gremlin-server's hostname
-        // and derives gremlin-server's principal name. Also, the hostname needs to be lowercase for use
-        // in principal names.
-        String hostname = "";
-        try {
-            hostname = Inet4Address.getLocalHost().getCanonicalHostName().toLowerCase();
-        } catch (Exception e) {
-            logger.error("Hostname not found: " + e.getMessage());
-        }
-        return hostname;
-    }
-
-    private File createTestDir() {
-        final String basedir = System.getProperty("basedir");
-        final File targetdir = new File(basedir, "target");
-        final File testDir = new File(targetdir, "kdc");
-        testDir.mkdirs();
-        return testDir;
-    }
-
-    private class TestKdcServer extends SimpleKdcServer {
-        public static final String KDC_REALM = "TEST.COM";
-        public static final String HOSTNAME = "localhost";
-
-        TestKdcServer() throws KrbException {
-            setKdcRealm(KDC_REALM);
-            setKdcHost(HOSTNAME);
-            setAllowTcp(true);
-            setAllowUdp(false);    // There are still udp issues in Apache Directory-Kerby 1.0.0-RC2
-            setKdcTcpPort(NetworkUtil.getServerPort());
-
-            final KrbClient krbClnt = getKrbClient();
-            final KrbConfig krbConfig = krbClnt.getKrbConfig();
-            krbConfig.setString(KrbConfigKey.PERMITTED_ENCTYPES,
-                    "aes128-cts-hmac-sha1-96 des-cbc-crc des-cbc-md5 des3-cbc-sha1");
-            krbClnt.setTimeout(10 * 1000);
-        }
-    }
-
-    public void setUp() throws Exception {
-        setUpKdcServer();
-        setUpPrincipals();
-    }
-
-    private void setUpKdcServer() throws Exception {
-        kdcServer = new TestKdcServer();
-        kdcServer.setWorkDir(testDir);
-        kdcServer.init();
-        kdcServer.start();
-    }
-
-    private void setUpPrincipals() throws KrbException {
-        kdcServer.createPrincipals(serverPrincipal);
-        kdcServer.exportPrincipal(serverPrincipal, serviceKeytabFile);
-
-        kdcServer.createPrincipal(clientPrincipal, clientPassword);
-        final TgtTicket tgt = kdcServer.getKrbClient().requestTgt(clientPrincipal, clientPassword);
-        kdcServer.getKrbClient().storeTicket(tgt, ticketCacheFile);
-
-        kdcServer.createPrincipal(clientPrincipal2, clientPassword2);
-        final TgtTicket tgt2 = kdcServer.getKrbClient().requestTgt(clientPrincipal2, clientPassword2);
-        kdcServer.getKrbClient().storeTicket(tgt2, ticketCacheFile2);
-    }
-
-    public void close() throws Exception {
-        deletePrincipals();
-        kdcServer.stop();
-        ticketCacheFile.delete();
-        ticketCacheFile2.delete();
-        serviceKeytabFile.delete();
-        testDir.delete();
-        System.clearProperty("java.security.auth.login.config");
-    }
-
-    private void deletePrincipals() throws KrbException {
-        kdcServer.getKadmin().deleteBuiltinPrincipals();
-        kdcServer.deletePrincipals(serverPrincipal);
-        kdcServer.deletePrincipal(clientPrincipal);
-        kdcServer.deletePrincipal(clientPrincipal2);
-    }
-
-    public void createPrincipal(final String principal) throws KrbException {
-        kdcServer.createPrincipal(principal);
-    }
-}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ResponseHandlerContextTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ResponseHandlerContextTest.java
deleted file mode 100644
index b072c21..0000000
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ResponseHandlerContextTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.server;
-
-import io.netty.channel.ChannelHandlerContext;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.server.handler.Frame;
-import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.mockito.Mockito;
-
-import java.util.Arrays;
-import java.util.UUID;
-import java.util.function.BiFunction;
-
-import static org.junit.Assert.assertTrue;
-
-@RunWith(Parameterized.class)
-public class ResponseHandlerContextTest {
-
-    @Parameterized.Parameter(value = 0)
-    public BiFunction<Context, ResponseStatusCode, Void> writeInvoker;
-
-    private final ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class);
-    private final RequestMessage request = RequestMessage.build("test").create();
-    private final Context context = new Context(request, ctx, null, null, null, null);
-    private final Log4jRecordingAppender recordingAppender = new Log4jRecordingAppender();
-
-    private Level originalLogLevel;
-
-    @Parameterized.Parameters(name = "{0}")
-    public static Iterable<Object[]> data() {
-        return Arrays.asList(new Object[][] {
-            {
-                new BiFunction<Context, ResponseStatusCode, Void>() {
-                    @Override
-                    public Void apply(final Context context, final ResponseStatusCode code) {
-                        context.writeAndFlush(code, "testMessage");
-                        return null;
-                    }
-
-                    @Override
-                    public String toString() {
-                        return "writeAndFlush(ResponseStatusCode, Object)";
-                    }
-                }
-            }, {
-                new BiFunction<Context, ResponseStatusCode, Void>() {
-                    @Override
-                    public Void apply(final Context context, final ResponseStatusCode code) {
-                        context.writeAndFlush(ResponseMessage.build(UUID.randomUUID()).code(code).create());
-                        return null;
-                    }
-
-                    @Override
-                    public String toString() {
-                        return "writeAndFlush(ResponseMessage)";
-                    }
-                }
-            },
-        });
-    }
-
-    @Before
-    public void addRecordingAppender() {
-        final Logger rootLogger = Logger.getRootLogger();
-        rootLogger.addAppender(recordingAppender);
-        originalLogLevel = rootLogger.getLevel();
-        rootLogger.setLevel(Level.ALL);
-    }
-
-    @After
-    public void removeRecordingAppender() {
-        final Logger rootLogger = Logger.getRootLogger();
-        rootLogger.setLevel(originalLogLevel);
-        rootLogger.removeAppender(recordingAppender);
-    }
-
-    @Test
-    public void shouldAllowMultipleNonFinalResponses() {
-        writeInvoker.apply(context, ResponseStatusCode.AUTHENTICATE);
-        Mockito.verify(ctx, Mockito.times(1)).writeAndFlush(Mockito.any());
-
-        writeInvoker.apply(context, ResponseStatusCode.PARTIAL_CONTENT);
-        Mockito.verify(ctx, Mockito.times(2)).writeAndFlush(Mockito.any());
-
-        writeInvoker.apply(context, ResponseStatusCode.PARTIAL_CONTENT);
-        Mockito.verify(ctx, Mockito.times(3)).writeAndFlush(Mockito.any());
-    }
-
-    @Test
-    public void shouldAllowAtMostOneFinalResponse() {
-        writeInvoker.apply(context, ResponseStatusCode.AUTHENTICATE);
-        Mockito.verify(ctx, Mockito.times(1)).writeAndFlush(Mockito.any());
-
-        writeInvoker.apply(context, ResponseStatusCode.SUCCESS);
-        Mockito.verify(ctx, Mockito.times(2)).writeAndFlush(Mockito.any());
-
-        writeInvoker.apply(context, ResponseStatusCode.SERVER_ERROR_TIMEOUT);
-        assertTrue(recordingAppender.logContainsAny(".*" + request.getRequestId() + ".*"));
-        assertTrue(recordingAppender.logContainsAny(".*" + ResponseStatusCode.SERVER_ERROR_TIMEOUT + ".*"));
-
-        // ensure there were no other writes to the channel
-        Mockito.verify(ctx, Mockito.times(2)).writeAndFlush(Mockito.any());
-    }
-
-    @Test
-    public void shouldNotAllowNonFinalMessagesAfterFinalResponse() {
-        writeInvoker.apply(context, ResponseStatusCode.SERVER_ERROR_TIMEOUT);
-        Mockito.verify(ctx, Mockito.times(1)).writeAndFlush(Mockito.any());
-
-        writeInvoker.apply(context, ResponseStatusCode.PARTIAL_CONTENT);
-        assertTrue(recordingAppender.logContainsAny(".*" + request.getRequestId() + ".*"));
-        assertTrue(recordingAppender.logContainsAny(".*" + ResponseStatusCode.PARTIAL_CONTENT + ".*"));
-
-        // ensure there were no other writes to the channel
-        Mockito.verify(ctx, Mockito.times(1)).writeAndFlush(Mockito.any());
-    }
-
-    @Test
-    public void shouldReleaseIgnoredFrames() {
-        writeInvoker.apply(context, ResponseStatusCode.SERVER_ERROR_TIMEOUT);
-        Mockito.verify(ctx, Mockito.times(1)).writeAndFlush(Mockito.any());
-
-        Frame frame = Mockito.mock(Frame.class);
-        context.writeAndFlush(ResponseStatusCode.SUCCESS, frame);
-
-        assertTrue(recordingAppender.logContainsAny(".*" + request.getRequestId() + ".*"));
-        assertTrue(recordingAppender.logContainsAny(".*" + ResponseStatusCode.SUCCESS + ".*"));
-
-        // ensure there were no other writes to the channel
-        Mockito.verify(ctx, Mockito.times(1)).writeAndFlush(Mockito.any());
-
-        // ensure the frame was released
-        Mockito.verify(frame, Mockito.times(1)).tryRelease();
-    }
-}
\ No newline at end of file
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/TestClientFactory.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/TestClientFactory.java
index 0eb1467..f760442 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/TestClientFactory.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/TestClientFactory.java
@@ -19,7 +19,6 @@
 package org.apache.tinkerpop.gremlin.server;
 
 import org.apache.tinkerpop.gremlin.driver.Cluster;
-import org.apache.tinkerpop.gremlin.driver.simple.NioClient;
 import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient;
 
 import java.net.URI;
@@ -31,7 +30,6 @@
 
     public static final int PORT = 45940;
     public static final URI WEBSOCKET_URI = URI.create("ws://localhost:" + PORT + "/gremlin");
-    public static final URI NIO_URI = URI.create("gs://localhost:" + PORT);
     public static final String HTTP = "http://localhost:" + PORT;
     public static final String RESOURCE_PATH = "conf/remote-objects.yaml";
 
@@ -47,10 +45,6 @@
         return new WebSocketClient(WEBSOCKET_URI);
     }
 
-    public static NioClient createNioClient() {
-        return new NioClient(NIO_URI);
-    }
-
     public static String createURLString() {
         return createURLString("");
     }
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/AbstractGremlinServerChannelizerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/AbstractGremlinServerChannelizerIntegrateTest.java
index a7ea488..38f2c9a 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/AbstractGremlinServerChannelizerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/AbstractGremlinServerChannelizerIntegrateTest.java
@@ -22,7 +22,6 @@
 import org.apache.tinkerpop.gremlin.driver.AuthProperties;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
-import org.apache.tinkerpop.gremlin.driver.Channelizer;
 import org.apache.tinkerpop.gremlin.server.AbstractGremlinServerIntegrationTest;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.TestClientFactory;
@@ -62,8 +61,6 @@
     protected static final String WSS = "wss";
     protected static final String WS_AND_HTTP = "wsAndHttp";
     protected static final String WSS_AND_HTTPS = "wssAndHttps";
-    protected static final String NIO = "nio";
-    protected static final String NIO_SECURE = "nioSecure";
 
     public abstract String getProtocol();
     public abstract String getSecureProtocol();
@@ -181,10 +178,7 @@
         private CloseableHttpClient httpClient = null;
         private Cluster wsCluster = null;
         private Cluster.Builder wsBuilder = null;
-        private Cluster nioCluster = null;
-        private Cluster.Builder nioBuilder = null;
         private Client wsClient = null;
-        private Client.ClusteredClient nioClient = null;
         private boolean secure = false;
 
 
@@ -213,13 +207,6 @@
                     secure = true;
                     this.wsBuilder = TestClientFactory.build();
                     break;
-                case NIO:
-                    this.nioBuilder = TestClientFactory.build();
-                    break;
-                case NIO_SECURE:
-                    this.nioBuilder = TestClientFactory.build();
-                    secure = true;
-                    break;
             }
         }
 
@@ -252,9 +239,6 @@
             if (wsCluster != null) {
                 wsCluster.close();
             }
-            if (nioCluster != null) {
-                nioCluster.close();
-            }
         }
 
         public void sendAndAssertUnauthorized(final String gremlin, final String username, final String password) throws Exception {
@@ -273,15 +257,6 @@
                     assertEquals("Username and/or password are incorrect", e.getCause().getMessage());
                 }
             }
-            if (nioBuilder != null) {
-                setNioClient(username, password);
-                try {
-                    nioClient.submit(gremlin);
-                } catch(Exception e) {
-                    assertEquals("Username and/or password are incorrect", e.getCause().getMessage());
-                }
-            }
-
         }
 
         public void sendAndAssert(final String gremlin, final Object result, final String username, final String password) throws Exception {
@@ -299,24 +274,6 @@
                 setWsClient(username, password);
                 assertEquals(result, wsClient.submit(gremlin).all().get().get(0).getInt());
             }
-            if (nioClient != null) {
-                assertEquals(result, nioClient.submit(gremlin).all().get().get(0).getInt());
-            }
-        }
-
-        private void setNioClient(final String username, final String password) {
-            nioBuilder.channelizer(Channelizer.NioChannelizer.class.getName());
-            if (username != null && password != null) {
-                final AuthProperties authProps = new AuthProperties()
-                                                .with(Property.USERNAME, username)
-                                                .with(Property.PASSWORD, password);
-
-                nioCluster = nioBuilder.enableSsl(secure).sslSkipCertValidation(true).authProperties(authProps).create();
-                nioClient = nioCluster.connect();
-            } else {
-                nioCluster = nioBuilder.enableSsl(secure).create();
-                nioClient = nioCluster.connect();
-            }
         }
 
         private void setWsClient(final String username, final String password) {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizerIntegrateTest.java
deleted file mode 100644
index 8388b40..0000000
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizerIntegrateTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.server.channel;
-
-
-import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
-import org.apache.tinkerpop.gremlin.server.Settings;
-
-import java.util.Map;
-import java.util.HashMap;
-
-public class NioChannelizerIntegrateTest extends AbstractGremlinServerChannelizerIntegrateTest {
-
-    @Override
-    public String getProtocol() {
-        return NIO;
-    }
-
-    @Override
-    public String getSecureProtocol() {
-        return NIO_SECURE;
-    }
-
-    @Override
-    public String getChannelizer() {
-        return NioChannelizer.class.getName();
-    }
-
-    @Override
-    public Settings.AuthenticationSettings getAuthSettings() {
-        final Settings.AuthenticationSettings authSettings = new Settings.AuthenticationSettings();
-        final Map<String,Object> authConfig = new HashMap<>();
-        authSettings.authenticator = SimpleAuthenticator.class.getName();
-        authConfig.put(SimpleAuthenticator.CONFIG_CREDENTIALS_DB, "conf/tinkergraph-credentials.properties");
-        authSettings.config = authConfig;
-
-        return authSettings;
-    }
-
-}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessorTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessorTest.java
index 485a74d..a8005e8 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessorTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessorTest.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.server.op;
 
 import io.netty.channel.ChannelHandlerContext;
+import org.apache.tinkerpop.gremlin.driver.Tokens;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
@@ -44,7 +45,9 @@
     @Test
     public void evalOpInternalShouldHandleAllEvaluationExceptions() throws OpProcessorException {
         final AbstractEvalOpProcessor processor = new StandardOpProcessor();
-        final RequestMessage request = RequestMessage.build("test").create();
+        final RequestMessage request = RequestMessage.build("test").
+                addArg(Tokens.ARGS_LANGUAGE, "gremlin-groovy").
+                addArg(Tokens.ARGS_GREMLIN, "1+1").create();
         final Settings settings = new Settings();
         final ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class);
         final ArgumentCaptor<ResponseMessage> responseCaptor = ArgumentCaptor.forClass(ResponseMessage.class);
@@ -60,7 +63,7 @@
         processor.evalOpInternal(contextspy, contextspy::getGremlinExecutor, SimpleBindings::new);
 
         Mockito.verify(contextspy, Mockito.times(1)).writeAndFlush(responseCaptor.capture());
-        assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, responseCaptor.getValue().getStatus().getCode());
+        assertEquals(ResponseStatusCode.SERVER_ERROR_EVALUATION, responseCaptor.getValue().getStatus().getCode());
         assertEquals(request.getRequestId(), responseCaptor.getValue().getRequestId());
         assertThat(responseCaptor.getValue().getStatus().getMessage(), CoreMatchers.containsString("test-exception"));
     }
diff --git a/gremlin-server/src/test/resources/client.crt b/gremlin-server/src/test/resources/client.crt
deleted file mode 100644
index 297335b..0000000
--- a/gremlin-server/src/test/resources/client.crt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- */
-
------BEGIN CERTIFICATE-----
-MIIDajCCAlICCQCG0QGj7JgLvTANBgkqhkiG9w0BAQsFADB2MQswCQYDVQQGEwJV
-UzELMAkGA1UECAwCTkMxEDAOBgNVBAcMB1JhbGVpZ2gxEzARBgNVBAoMCkNsaWVu
-dCBBcHAxDzANBgNVBAMMBmNsaWVudDEiMCAGCSqGSIb3DQEJARYTZ3JlbWxpbi11
-c2VyQGNsaWVudDAgFw0xNzAxMjMxODQzMjNaGA8yMTE2MTIzMDE4NDMyM1owdjEL
-MAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5DMRAwDgYDVQQHDAdSYWxlaWdoMRMwEQYD
-VQQKDApDbGllbnQgQXBwMQ8wDQYDVQQDDAZjbGllbnQxIjAgBgkqhkiG9w0BCQEW
-E2dyZW1saW4tdXNlckBjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQDU7U5tNN+0HCKZX31ZKMZwAUI7qGCpYXd05z5SKRWesNsrEeCLnu1DgYhL
-j+hSi2LI+RwTF45DH8zEPIzQ6HEMzuCd2uy7bdDrXv6H/tFUx9Iw0ea5oXGX1qNa
-tzjPTSmw22VXbSo+B5EG0coC5oDy9SpYb2HxeDmegI2OZL6ROFPKbCUTzyJfqTpy
-1mdgnnKTVuQdtWvj/sXDAZzRqtFHwBkHezKCOC4yLNi5+pI01+0V7FbtyCqH7iPS
-VS9VKsLuhPkzAkRh/x9CxaSrwicyzyB3Kyfg7kjmtdrUOrfgxdw+MMPog3JrGoLr
-tfvc9LUh0ImpLPngyWhwc5iNGwmLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEi0
-IVUIbDuirNivJXXXT5eFUgfAx5iPjbR1XBjCuHO061d0B8itU7cidKs0y5mDoauy
-vuywNBih6FAsHoYLrqI1gt65fybGxq3wlhnqdLH7GDeHw65e2PB2x+M4NtQlkPTq
-dUgUtQzAo8Hc4DNR5BrvCtLjqT7Knq8QHtGLys8eoDur09894+6WeUjrgUTp88Jl
-uqrZqRHvdMW7sge73cpU1dsDJW0rJqCLZ+qA2V+ZRRCQY1oHuHeK6Dkokabaq3rr
-WrpxfppIPCusJx4nnIwu4d0gZwAKwabOS8lJPjV0frRkA0BuAEpMIbOwZ10Tw7ZM
-2HzamAOiiks4NFDSs94=
------END CERTIFICATE-----
diff --git a/gremlin-server/src/test/resources/client.key.pk8 b/gremlin-server/src/test/resources/client.key.pk8
deleted file mode 100644
index 213cce3..0000000
--- a/gremlin-server/src/test/resources/client.key.pk8
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE6TAbBgkqhkiG9w0BBQMwDgQIuH3rVXHniaECAggABIIEyDzHWny/fttnN6ze
-Q/iNE1z72HBg2anTK3gHdu8W3F9W6BSLhuKaUumxcxX6IfkZmxinqwUxSNrRBswr
-s71EZ7QmX2eaeiWxlo6zP0I898fzqvSBWk6NhntV1SVG++/CMeIMZARs85OxcNGN
-fKEXtBUf5jlo+hy9bVgQRO2M1vHzek/deOHyj1eXwEi2Oxcw1ly3o9lRayIFJFou
-0olp58h8pD5qOsSfIrNG6bHBg00eP1ILE1FUPCdOfDrQEjiKKVqllCXdsUz/KjBY
-0iGYMw3aT2LELnibTy0alFswGaDBRqlzGSIGrejdGTOBj7NmeiW2yOY+aUjCkdXw
-ll862oItlJZO/B16EGgI+czdXZgcL5YRGVOu6loOlGxU60Y681Acjn9wdlxxOqXa
-te7khLGX6qm3ceMJ2DQbMO8JS6UBsGjZqq/ictwfGxNDiTeiWmoyrQvO3qkaqsEt
-iLBJdSsogzxx+hfj+xiBRorf9Gvkk6hDnzeuZl9Voak5qY7RrcmxD8ecdh3g2faO
-VFtxTAxmHJakgGF7fZ7jQoxZJzzRn+rjIhATaEH1/MMME77Z+8rkE74oxFOrizDU
-Eb4AMUV/xgrAtQLGpIFALL7oPk2r1exFgywL40q5/BcXCx65eliXtyoBIc5X+t90
-fTB8lA3K5mT2MXzwMyMPv2n8d8Ta2OjisRHjSue6AqNqifBuniVfSpHP9OUlsKaL
-u3eN8mSuPDhlo7RGG8+B7mSqGDjORR/+BJvwgFreIyurOL22g887uPwjzPXs6lll
-3VFclsrfEqNMP6kBsXlHNAxjT10WoWrF+ONPEyg9PrzTGryTRqW+ptzBqtiQrVag
-/KMee3sdg6i9GN+EGc43DNJzxxlFXvT9kBvOk66tOPEE5963k3ZikjuAX7xBVOvM
-AlqzHHW727fHXqYp0yabWTpr72RuUGQOqPZiMsWd6x65HL2I0WHP9PXTf1vMmnj3
-NgiN1paATl5L8S9Jt8WL8iLskVt2f+CAKJuQfamY5Fg54m/cJzNHV8nAMTTl+0EN
-9vUhvn672wZd9JfB4PMtrIhYFNJElJmmdAwjFrop6goXA/UGgf3M4QNiQetFGxWP
-aJ0tMSdA/ax9nGA5LU6iCwPe51ExrQJAVFw+oE3I8+J1oz1fQOl8zIgyOFwG+bJx
-/Y/JyraEssZ5RLtaGgcm9vZm8Wo8a5TQCbqhoY8x7MwyF7/VpbRZ3bGEUFnWd/yF
-1tCPeZ+q5HN79P3qfZzAcFAU3z3HawXDwQ3XO3Plix04Vjr+QFENeJxhL+3FXtLx
-4nF+Y9Fq6I5x8YQLrPYkIyRz8xWxVBQFZTeNhWx5nYWNcDXgz/S8v3ipY+EPEj9Q
-uOQWNdSJ9XOR+Ju/KSP0151guLkUwpHBCi/CFY4TgD6iFglTyLuZpW2bbim1mmDI
-LSDHwrERQWNmcNznK4PIw227w6EZqUEI0jjkANhXQG6dz1VkaTIZAoEVWHhFNi8S
-gSPkhsWN822QzxZQb+74JoUFBTifP50giaCd6p2HKw8U20FAPyseVIY3IsYatuLU
-8VhfeBQ1GLOOy8/5mRyjL+Gjn/OfNPwps9uuOogx/jGf0JhtjAEY2WNoEEB9DkUv
-AijT0ck1+DM3by4MlA==
------END ENCRYPTED PRIVATE KEY-----
diff --git a/gremlin-server/src/test/resources/server.crt b/gremlin-server/src/test/resources/server.crt
deleted file mode 100644
index b777e34..0000000
--- a/gremlin-server/src/test/resources/server.crt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
------BEGIN CERTIFICATE-----
-MIIDrjCCApYCCQCg8hxjInTcQzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMC
-VVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50YSBDbGFyYTEZMBcGA1UECgwQ
-QXBhY2hlIFRpbmtlclBvcDEQMA4GA1UECwwHR3JlbWxpbjESMBAGA1UEAwwJbG9j
-YWxob3N0MSQwIgYJKoZIhvcNAQkBFhVzcG1hbGxldHRlQGFwYWNoZS5vcmcwIBcN
-MTcwMTIzMTg0MTEwWhgPMjExNjEyMzAxODQxMTBaMIGXMQswCQYDVQQGEwJVUzEL
-MAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJhMRkwFwYDVQQKDBBBcGFj
-aGUgVGlua2VyUG9wMRAwDgYDVQQLDAdHcmVtbGluMRIwEAYDVQQDDAlsb2NhbGhv
-c3QxJDAiBgkqhkiG9w0BCQEWFXNwbWFsbGV0dGVAYXBhY2hlLm9yZzCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAK5l+5DDrSGq1n1vYIMbb95buWlo4u5s
-V8wHNmeFCuqNvGfxermHS88SSy6qvdSXISfe+kj9Jkfn1Pjx4czwcnF/q4Au3Gc6
-T9MiAKJUfb4+MwPKERacFobk6LTreKpzvXymAhhM1ktvvA7/opZ+nENDEoIJK/KS
-CY9vRWeHqI1Q+Rf5Nrqw8eySq/ZhPDlppsu5sQr1ghSsuzXhpYNhq8VBMsysL2Zi
-VF5DFMqg9yhBkxrqo70W/pjo4kQJ/iF/4d/3HHicSCVq3/NCkWMVg0HeOZ1eVaZ/
-D6EXv8cYwyaRmf7SldE7RtdbAU0M+Y0Lmuoi2evls0Oiqf8uxEDXeLUCAwEAATAN
-BgkqhkiG9w0BAQsFAAOCAQEAJFAAUxYeUbf6tAGEKCXISted10TybPW/qCxOXEPN
-TTO+xvnzksbcbzOc2X0N+yYIKtkfiuWgD9UJ4QnLSeEKmouMbkTk0ToYJj7SrviI
-f+9R1IiZMiwz+n0igETkEGOK0Ql26Z4g3kc1IueSD07QOLASTvVLtEyoya7LD4S6
-jk1LnbpbHVmgHY4kmtsg6lVQ1zkqrsDQg9goh8dI5AlNCudpd8zLxzsPbm+Q2+DC
-Wd4A2lKdh3rbY2LYpbVhBj9c6E0laaqgyGC7s37XfmyBp4wYlX/30p6RpCR2rcRW
-SKh5NXN52Xx3WuiP42wm9ZC/de8gaODrW8n44xlEaMPJ3A==
------END CERTIFICATE-----
diff --git a/gremlin-server/src/test/resources/server.key.pk8 b/gremlin-server/src/test/resources/server.key.pk8
deleted file mode 100644
index 9dc6720..0000000
--- a/gremlin-server/src/test/resources/server.key.pk8
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE6TAbBgkqhkiG9w0BBQMwDgQIJi2M3dPcx+cCAggABIIEyG/0PwTaqm3ekGkn
-8daHjfcqxCpvwOku0pCCgV7AMsrsj4TvMOHOkId+xKVs4AlXV2grPfTQoMrIFFp0
-26hzpZOHEjAe9XbtzVWgphwLVeWOr5ugovyXPxdCqMBrn251y9Yg6csh5pPrsHEp
-RLTZPQPvEVIhA0tRkPPag5BSlj//nH7PnXYRm4VSRg7WQS15ieHsC1xDM9zYni/b
-ffU++twOGvCdvtGd/lqjJj3dPomKynb6Y4cEc73vQ6cQjeXN1W1Nil4QsDZ53H3U
-KvoWuEVYDf1WDFySgHMFgePHXMMWA8ZkgS6rOrV1TDnoZIhG5BSe7aJNJQdVVMub
-NAxZB4C1unIICuAtsP9IEAhevbfNGySi0jbrnun0pTD22Q95HZVycl1YWamrr1Hl
-17TmHQT7zh4GLlXVI3L/FevoswbuR7misyqE3ketNpxdLcHKs82MVLCwbLzuqm60
-tpSm/jrexhNErKU28kdPzWCwruEHdrlOuMSS8N2YgSZxHIjEId8pZED8dsnPvqhe
-CAEa3F68Js9sngeMvThYirpr0wOsSGmGCDrXTmQvTw+q8C+DJLWpjfpKZA4g624f
-E3CUojwOaPrmaEa25eYm0oYDstY8QncG7nBAuljeXWBYfxARYcLI/bLC/M/q+UeS
-gzjQgoacH4r2Y7rwEA0aeYC+9TWn5rPHPWegdc01A2e7OlYKrlu9C1aKZr//GyBM
-lEVRc0u8RL+RVhmp7ftRyATDG9kJR+zDT26hewaEa5atnPKLjf+37hu7a/6GI+2X
-dpWTzmvWal4eEkFuBg2ekl1lCsuuCUBDWyYrlhsWPYTOSKJ/PTuLq7HVqdGB9kEw
-SavnXV5LPOaY4nAzJTdRk9DHdxSwSrjZ5rvMMD1CAbob/GA9t8aYaGcAWtTwMFs4
-sps40mmab3X0LLvTblHtmRCHWswcACbH2DC6H+0awsaZNI80GxSSutKN+2vH3N0C
-6fLwP1VaYm0qPA3pI1vp9Xu5I//6Hzt3aT/R+6KhS+CH3qbJiHNzg1ywdNqgD3Pp
-bJNEiDKWdLd65bvclVVyWHovWIvvEly1TWUsp4YbdrT5asL/VV82fvo4wCttOq96
-msk9OL5vQADJ32D7vnnYadiT2tpJMjNSug7JKHutJ/cJmm8qkqNwFm/BH+w2t7kh
-elbG0f2P7FpPXVMCJPHhmI/+OBECqBHAAWgRRn91GqeGgY+Xy05orL2R/qeNdBbT
-qmrxqm7LesPgo0IqU82quTkiBERaXMu8qUYaYPGVJIskQuWqd/aArhaFmqZhK3bz
-lepJMDAaeaBT/3ULICHdhsSVAhl6iwid40ow8x1cRFoPEljZ9t6fERN1h2ptNyZT
-LRJ4DUXy4RWTHl3+AVyzwcgMpxkxRTzdjguzAjceOHEMm7UNCvSVhFHVBkG6kXXw
-940iYvhkRnn6HRcPbP5xeJp6GX8RoAl42giRO6OGnkhkepOuAcFKJCC2N5OgdKmq
-mlVGEKndriwyzyiPN8noEJksenL1iMSA7HSnM34uCJoEetTBRuv8+721bTdz8dy0
-s/GghsYztugLjho4yivn2fcxw4gMFiSiliyrfbocJnHAubDMZwEu0fpfY+0fBi9+
-e/Odgw8aTlMUKSo+UA==
------END ENCRYPTED PRIVATE KEY-----
diff --git a/gremlin-server/src/test/scripts/test-server-start.groovy b/gremlin-server/src/test/scripts/test-server-start.groovy
index e721aff..324492e 100644
--- a/gremlin-server/src/test/scripts/test-server-start.groovy
+++ b/gremlin-server/src/test/scripts/test-server-start.groovy
@@ -18,6 +18,7 @@
  */
 
 import org.apache.tinkerpop.gremlin.server.GremlinServer
+import org.apache.tinkerpop.gremlin.server.KdcFixture
 import org.apache.tinkerpop.gremlin.server.Settings
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -25,8 +26,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Changes to this file need to be appropriately replicated to
 //
-// - docker/gremlin-server/gremlin-server-integration.yaml
-// - docker/gremlin-server/gremlin-server-integration-secure.yaml
+// - docker/gremlin-server/*
+// - docker/gremlin-server.sh
 //
 // Without such changes, the test docker server can't be started for independent
 // testing with Gremlin Language Variants.
@@ -43,17 +44,14 @@
 settings.graphs.grateful = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
 settings.graphs.sink = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
 settings.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files = [gremlinServerDir + "/src/test/scripts/generate-all.groovy"]
-if (Boolean.parseBoolean(python)) {
-    settings.scriptEngines["gremlin-python"] = new Settings.ScriptEngineSettings()
-    settings.scriptEngines["gremlin-jython"] = new Settings.ScriptEngineSettings()
-}
 settings.port = 45940
 
 def server = new GremlinServer(settings)
 server.start().join()
 
 project.setContextValue("gremlin.server", server)
-log.info("Gremlin Server with no authentication started on port 45940")
+log.info("Gremlin Server without authentication started on port 45940")
+
 
 def securePropsFile = new File("${projectBaseDir}/target/tinkergraph-credentials.properties")
 if (!securePropsFile.exists()) {
@@ -72,10 +70,6 @@
 settingsSecure.graphs.grateful = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
 settingsSecure.graphs.sink = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
 settingsSecure.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files = [gremlinServerDir + "/src/test/scripts/generate-all.groovy"]
-if (Boolean.parseBoolean(python)) {
-    settingsSecure.scriptEngines["gremlin-python"] = new Settings.ScriptEngineSettings()
-    settingsSecure.scriptEngines["gremlin-jython"] = new Settings.ScriptEngineSettings()
-}
 settingsSecure.port = 45941
 settingsSecure.authentication.authenticator = "org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator"
 settingsSecure.authentication.config = [credentialsDb: projectBaseDir + "/target/tinkergraph-credentials.properties"]
@@ -84,4 +78,31 @@
 serverSecure.start().join()
 
 project.setContextValue("gremlin.server.secure", serverSecure)
-log.info("Gremlin Server with authentication started on port 45941")
\ No newline at end of file
+log.info("Gremlin Server with password authentication started on port 45941")
+
+
+def kdcServer = new KdcFixture(projectBaseDir)
+kdcServer.setUp()
+
+project.setContextValue("gremlin.server.kdcserver", kdcServer)
+log.info("KDC started with configuration ${projectBaseDir}/target/kdc/krb5.conf")
+
+def settingsKrb5 = Settings.read("${settingsFile}")
+settingsKrb5.graphs.graph = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
+settingsKrb5.graphs.classic = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
+settingsKrb5.graphs.modern = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
+settingsKrb5.graphs.crew = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
+settingsKrb5.graphs.grateful = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
+settingsKrb5.graphs.sink = gremlinServerDir + "/src/test/scripts/tinkergraph-empty.properties"
+settingsKrb5.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files = [gremlinServerDir + "/src/test/scripts/generate-all.groovy"]
+settingsKrb5.port = 45942
+settingsKrb5.authentication.authenticator = "org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator"
+settingsKrb5.authentication.config = [
+        "principal": kdcServer.serverPrincipal,
+        "keytab": kdcServer.serviceKeytabFile.getAbsolutePath()]
+
+def serverKrb5 = new GremlinServer(settingsKrb5)
+serverKrb5.start().join()
+
+project.setContextValue("gremlin.server.krb5", serverKrb5)
+log.info("Gremlin Server with kerberos authentication started on port 45942")
diff --git a/gremlin-server/src/test/scripts/test-server-stop.groovy b/gremlin-server/src/test/scripts/test-server-stop.groovy
index 595d9bd..d9fc629 100644
--- a/gremlin-server/src/test/scripts/test-server-stop.groovy
+++ b/gremlin-server/src/test/scripts/test-server-stop.groovy
@@ -29,4 +29,12 @@
 log.info("Shutting down $serverSecure")
 serverSecure.stop().join()
 
+def kdcServer = project.getContextValue("gremlin.server.kdcserver")
+log.info("Shutting down $kdcServer")
+kdcServer.close()
+
+def serverKrb5 = project.getContextValue("gremlin.server.krb5")
+log.info("Shutting down $serverKrb5")
+serverKrb5.stop().join()
+
 log.info("All Gremlin Server instances are shutdown for ${executionName}")
\ No newline at end of file
diff --git a/gremlin-shaded/pom.xml b/gremlin-shaded/pom.xml
index 942d037..8d0f847 100644
--- a/gremlin-shaded/pom.xml
+++ b/gremlin-shaded/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-shaded</artifactId>
     <name>Apache TinkerPop :: Gremlin Shaded</name>
diff --git a/gremlin-test/features/branch/Branch.feature b/gremlin-test/features/branch/Branch.feature
index e160fc8..a161ba7 100644
--- a/gremlin-test/features/branch/Branch.feature
+++ b/gremlin-test/features/branch/Branch.feature
@@ -42,13 +42,15 @@
 
   Scenario: g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX
     Given the modern graph
+    And using the parameter one defined as "d[1].l"
+    And using the parameter zero defined as "d[0].l"
     And the traversal of
       """
       g.V().
         branch(__.label().is("person").count()).
-          option(1L, __.values("age")).
-          option(0L, __.values("lang")).
-          option(0L, __.values("name"))
+          option(one, __.values("age")).
+          option(zero, __.values("lang")).
+          option(zero, __.values("name"))
       """
     When iterated to list
     Then the result should be unordered
@@ -64,13 +66,15 @@
 
   Scenario: g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX_optionXany__labelX
     Given the modern graph
+    And using the parameter one defined as "d[1].l"
+    And using the parameter zero defined as "d[0].l"
     And the traversal of
       """
       g.V().
         branch(__.label().is("person").count()).
-          option(1L, __.values("age")).
-          option(0L, __.values("lang")).
-          option(0L, __.values("name")).
+          option(one, __.values("age")).
+          option(zero, __.values("lang")).
+          option(zero, __.values("name")).
           option(Pick.any, __.label())
       """
     When iterated to list
diff --git a/gremlin-test/features/branch/Choose.feature b/gremlin-test/features/branch/Choose.feature
index 7bb8c03..99ff4c4 100644
--- a/gremlin-test/features/branch/Choose.feature
+++ b/gremlin-test/features/branch/Choose.feature
@@ -19,11 +19,13 @@
 
   Scenario: g_V_chooseXout_countX_optionX2L_nameX_optionX3L_ageX
     Given the modern graph
+    And using the parameter two defined as "d[2].l"
+    And using the parameter three defined as "d[3].l"
     And the traversal of
       """
       g.V().choose(__.out().count()).
-        option(2L, __.values("name")).
-        option(3L, __.values("age"))
+        option(two, __.values("name")).
+        option(three, __.values("age"))
       """
     When iterated to list
     Then the result should be unordered
diff --git a/gremlin-test/features/filter/Dedup.feature b/gremlin-test/features/filter/Dedup.feature
index 501d02b..f533a9c 100644
--- a/gremlin-test/features/filter/Dedup.feature
+++ b/gremlin-test/features/filter/Dedup.feature
@@ -235,3 +235,35 @@
       | result |
       | d[0].l |
 
+  Scenario: g_V_bothE_properties_dedup_count
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().bothE().properties().dedup().count()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[4].l |
+
+  Scenario: g_V_both_properties_dedup_count
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().both().properties().dedup().count()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[12].l |
+
+  Scenario: g_V_both_properties_properties_dedup_count
+    Given the crew graph
+    And the traversal of
+      """
+      g.V().both().properties().properties().dedup().count()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[21].l |
\ No newline at end of file
diff --git a/gremlin-test/features/filter/Is.feature b/gremlin-test/features/filter/Is.feature
index 4eec274..70c7a9a 100644
--- a/gremlin-test/features/filter/Is.feature
+++ b/gremlin-test/features/filter/Is.feature
@@ -65,9 +65,10 @@
 
   Scenario: g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX
     Given the modern graph
+    And using the parameter two defined as "d[2].l"
     And the traversal of
       """
-      g.V().where(__.in("created").count().is(P.gte(2l))).values("name")
+      g.V().where(__.in("created").count().is(P.gte(two))).values("name")
       """
     When iterated to list
     Then the result should be unordered
diff --git a/gremlin-test/features/filter/Or.feature b/gremlin-test/features/filter/Or.feature
index 7f4782d..437bcd1 100644
--- a/gremlin-test/features/filter/Or.feature
+++ b/gremlin-test/features/filter/Or.feature
@@ -19,9 +19,10 @@
 
   Scenario: g_V_orXhasXage_gt_27X__outE_count_gte_2X_name
     Given the modern graph
+    And using the parameter two defined as "d[2].l"
     And the traversal of
       """
-      g.V().or(__.has("age", P.gt(27)), __.outE().count().is(P.gte(2l))).values("name")
+      g.V().or(__.has("age", P.gt(27)), __.outE().count().is(P.gte(two))).values("name")
       """
     When iterated to list
     Then the result should be unordered
diff --git a/gremlin-test/features/map/AddEdge.feature b/gremlin-test/features/map/AddEdge.feature
index 7f4b0aa..8e03ac3 100644
--- a/gremlin-test/features/map/AddEdge.feature
+++ b/gremlin-test/features/map/AddEdge.feature
@@ -72,6 +72,31 @@
     And the graph should return 4 for count of "g.V(v1Id).bothE()"
     And the graph should return 1 for count of "g.V(v1Id).inE().has(\"weight\", 2.0)"
 
+  Scenario: g_V_outE_propertyXweight_nullX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 1).property("name", "marko").property("age", 29).as("marko").
+        addV("person").property(T.id, 2).property("name", "vadas").property("age", 27).as("vadas").
+        addV("software").property(T.id, 3).property("name", "lop").property("lang", "java").as("lop").
+        addV("person").property(T.id, 4).property("name","josh").property("age", 32).as("josh").
+        addV("software").property(T.id, 5).property("name", "ripple").property("lang", "java").as("ripple").
+        addV("person").property(T.id, 6).property("name", "peter").property("age", 35).as('peter').
+        addE("knows").from("marko").to("vadas").property(T.id, 7).property("weight", 0.5).
+        addE("knows").from("marko").to("josh").property(T.id, 8).property("weight", 1.0).
+        addE("created").from("marko").to("lop").property(T.id, 9).property("weight", 0.4).
+        addE("created").from("josh").to("ripple").property(T.id, 10).property("weight", 1.0).
+        addE("created").from("josh").to("lop").property(T.id, 11).property("weight", 0.4).
+        addE("created").from("peter").to("lop").property(T.id, 12).property("weight", 0.2)
+      """
+    And the traversal of
+      """
+      g.V().outE().property("weight", null)
+      """
+    When iterated to list
+    Then the result should have a count of 6
+    And the graph should return 0 for count of "g.E().properties(\"weight\")"
+
   Scenario: g_V_aggregateXxX_asXaX_selectXxX_unfold_addEXexistsWithX_toXaX_propertyXtime_nowX
     Given the empty graph
     And the graph initializer of
diff --git a/gremlin-test/features/map/AddVertex.feature b/gremlin-test/features/map/AddVertex.feature
index a60fefb..943b303 100644
--- a/gremlin-test/features/map/AddVertex.feature
+++ b/gremlin-test/features/map/AddVertex.feature
@@ -93,6 +93,31 @@
     Then the result should have a count of 1
     And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"stephen\")"
 
+  Scenario: g_V_hasLabelXpersonX_propertyXname_nullX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 1).property("name", "marko").property("age", 29).as("marko").
+        addV("person").property(T.id, 2).property("name", "vadas").property("age", 27).as("vadas").
+        addV("software").property(T.id, 3).property("name", "lop").property("lang", "java").as("lop").
+        addV("person").property(T.id, 4).property("name","josh").property("age", 32).as("josh").
+        addV("software").property(T.id, 5).property("name", "ripple").property("lang", "java").as("ripple").
+        addV("person").property(T.id, 6).property("name", "peter").property("age", 35).as('peter').
+        addE("knows").from("marko").to("vadas").property(T.id, 7).property("weight", 0.5).
+        addE("knows").from("marko").to("josh").property(T.id, 8).property("weight", 1.0).
+        addE("created").from("marko").to("lop").property(T.id, 9).property("weight", 0.4).
+        addE("created").from("josh").to("ripple").property(T.id, 10).property("weight", 1.0).
+        addE("created").from("josh").to("lop").property(T.id, 11).property("weight", 0.4).
+        addE("created").from("peter").to("lop").property(T.id, 12).property("weight", 0.2)
+      """
+    And the traversal of
+      """
+      g.V().hasLabel("person").property("name", null)
+      """
+    When iterated to list
+    Then the result should have a count of 4
+    And the graph should return 2 for count of "g.V().properties(\"name\")"
+
   Scenario: g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenmX
     Given the empty graph
     And the graph initializer of
@@ -387,3 +412,22 @@
       | result |
       | name |
 
+  Scenario: g_addVXnullX_propertyXid_nullX
+    Given the empty graph
+    And the traversal of
+      """
+      g.addV(null).property(T.id, null)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 1 for count of "g.V().hasLabel(\"vertex\")"
+
+  Scenario: g_addV_propertyXlabel_personX
+    Given the empty graph
+    And the traversal of
+      """
+      g.addV().property(T.label, "person")
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 1 for count of "g.V().hasLabel(\"person\")"
diff --git a/gremlin-test/features/map/Constant.feature b/gremlin-test/features/map/Constant.feature
index 9ad8d13..ed25b25 100644
--- a/gremlin-test/features/map/Constant.feature
+++ b/gremlin-test/features/map/Constant.feature
@@ -19,7 +19,6 @@
 
   Scenario: g_V_constantX123X
     Given the modern graph
-    And using the parameter v1Id defined as "v[marko].id"
     And the traversal of
       """
       g.V().constant(123)
@@ -34,6 +33,22 @@
       | d[123].i |
       | d[123].i |
 
+  Scenario: g_V_constantXnullX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().constant(null)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | null |
+      | null |
+      | null |
+      | null |
+      | null |
+      | null |
+
   Scenario: g_V_chooseXhasLabelXpersonX_valuesXnameX_constantXinhumanXX
     Given the modern graph
     And the traversal of
diff --git a/gremlin-test/features/map/Map.feature b/gremlin-test/features/map/Map.feature
index 8d1029f..5f404ea 100644
--- a/gremlin-test/features/map/Map.feature
+++ b/gremlin-test/features/map/Map.feature
@@ -106,3 +106,19 @@
       | v[josh] |
       | v[ripple] |
       | v[peter]  |
+
+  Scenario: g_V_mapXconstantXnullXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().map(__.constant(null))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | null |
+      | null |
+      | null |
+      | null |
+      | null |
+      | null |
\ No newline at end of file
diff --git a/gremlin-test/features/map/Order.feature b/gremlin-test/features/map/Order.feature
index 6a06890..3a118f6 100644
--- a/gremlin-test/features/map/Order.feature
+++ b/gremlin-test/features/map/Order.feature
@@ -51,22 +51,6 @@
       | josh   |
       | lop    |
 
-  Scenario: g_V_order_byXname_incrX_name
-    Given the modern graph
-    And the traversal of
-      """
-      g.V().order().by("name", Order.incr).values("name")
-      """
-    When iterated to list
-    Then the result should be ordered
-      | result |
-      | josh |
-      | lop  |
-      | marko |
-      | peter |
-      | ripple |
-      | vadas  |
-
   Scenario: g_V_order_byXname_ascX_name
     Given the modern graph
     And the traversal of
@@ -99,22 +83,6 @@
       | ripple |
       | vadas  |
 
-  Scenario: g_V_outE_order_byXweight_decrX_weight
-    Given the modern graph
-    And the traversal of
-      """
-      g.V().outE().order().by("weight", Order.decr).values("weight")
-      """
-    When iterated to list
-    Then the result should be ordered
-      | result |
-      | d[1.0].d |
-      | d[1.0].d |
-      | d[0.5].d |
-      | d[0.4].d |
-      | d[0.4].d |
-      | d[0.2].d |
-
   Scenario: g_V_outE_order_byXweight_descX_weight
     Given the modern graph
     And the traversal of
diff --git a/gremlin-test/features/map/PageRank.feature b/gremlin-test/features/map/PageRank.feature
index fa5aaf6..479a309 100644
--- a/gremlin-test/features/map/PageRank.feature
+++ b/gremlin-test/features/map/PageRank.feature
@@ -34,11 +34,11 @@
       | v[peter] |
     And the graph should return 6 for count of "g.withComputer().V().pageRank().has(\"gremlin.pageRankVertexProgram.pageRank\")"
 
-  Scenario: g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX
+  Scenario: g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().out("created").pageRank().by(__.bothE()).by("projectRank").times(0).valueMap("name", "projectRank")
+      g.withComputer().V().out("created").pageRank().with("~tinkerpop.pageRank.edges",__.bothE()).with("~tinkerpop.pageRank.propertyName","projectRank").with("~tinkerpop.pageRank.times",0).valueMap("name", "projectRank")
       """
     When iterated to list
     Then the result should be unordered
@@ -48,11 +48,11 @@
       | m[{"name": ["lop"], "projectRank": [3.0]}] |
       | m[{"name": ["ripple"], "projectRank": [1.0]}] |
 
-  Scenario: g_V_pageRank_order_byXpageRank_decrX_byXnameX_name
+  Scenario: g_V_pageRank_order_byXpageRank_descX_byXnameX_name
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank", Order.decr).by("name").values("name")
+      g.withComputer().V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank", Order.desc).by("name").values("name")
       """
     When iterated to list
     Then the result should be ordered
@@ -64,11 +64,11 @@
       | marko  |
       | peter  |
 
-  Scenario: g_V_pageRank_order_byXpageRank_decrX_name_limitX2X
+  Scenario: g_V_pageRank_order_byXpageRank_descX_name_limitX2X
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank", Order.decr).values("name").limit(2)
+      g.withComputer().V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank", Order.desc).values("name").limit(2)
       """
     When iterated to list
     Then the result should be ordered
@@ -76,11 +76,11 @@
       | lop    |
       | ripple |
 
-  Scenario: g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX
+  Scenario: g_V_pageRank_withXedges_outEXknowsXX_withXpropertyName_friendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().pageRank().by(__.outE("knows")).by("friendRank").project("name", "friendRank").by("name").by(__.values("friendRank").math("ceil(_ * 100)"))
+      g.withComputer().V().pageRank().with("~tinkerpop.pageRank.edges",__.outE("knows")).with("~tinkerpop.pageRank.propertyName","friendRank").project("name", "friendRank").by("name").by(__.values("friendRank").math("ceil(_ * 100)"))
       """
     When iterated to list
     Then the result should be unordered
@@ -92,11 +92,11 @@
       | m[{"name": "ripple", "friendRank": 15.0}] |
       | m[{"name": "peter", "friendRank": 15.0}] |
 
-  Scenario: g_V_hasLabelXpersonX_pageRank_byXpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX
+  Scenario: g_V_hasLabelXpersonX_pageRank_withXpropertyName_kpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().hasLabel("person").pageRank().by("pageRank").project("name", "pageRank").by("name").by(__.values("pageRank").math("ceil(_ * 100)"))
+      g.withComputer().V().hasLabel("person").pageRank().with("~tinkerpop.pageRank.propertyName","pageRank").project("name", "pageRank").by("name").by(__.values("pageRank").math("ceil(_ * 100)"))
       """
     When iterated to list
     Then the result should be unordered
@@ -106,11 +106,11 @@
       | m[{"name": "josh", "pageRank": 59.0}] |
       | m[{"name": "peter", "pageRank": 46.0}] |
 
-  Scenario: g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX
+  Scenario: g_V_pageRank_withXpropertyName_pageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().pageRank().by("pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").by().by(__.math("ceil(_ * 100)"))
+      g.withComputer().V().pageRank().with("~tinkerpop.pageRank.propertyName","pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").by().by(__.math("ceil(_ * 100)"))
       """
     When iterated to list
     Then the result should be unordered
@@ -118,11 +118,11 @@
       | m[{"a": "v[marko]", "b": 15.0}] |
       | m[{"a": "v[marko]", "b": 15.0}] |
 
-  Scenario: g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX
+  Scenario: g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_withXedges_inEXcreatedX_withXtimes_1X_withXpropertyName_priorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().hasLabel("software").has("name", "ripple").pageRank(1.0).by(__.inE("created")).times(1).by("priors").in("created").union(__.both(), __.identity()).valueMap("name", "priors")
+      g.withComputer().V().hasLabel("software").has("name", "ripple").pageRank(1.0).with("~tinkerpop.pageRank.edges",__.inE("created")).with("~tinkerpop.pageRank.times",1).with("~tinkerpop.pageRank.propertyName","priors").in("created").union(__.both(), __.identity()).valueMap("name", "priors")
       """
     When iterated to list
     Then the result should be unordered
@@ -132,17 +132,11 @@
       | m[{"name": ["lop"], "priors": [0.0]}] |
       | m[{"name": ["ripple"], "priors": [0.0]}] |
 
-  Scenario: g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_byXpageRankX_byXinEX_timesX1X_inXcreatedX_groupXmX_byXpageRankX_capXmX
+  Scenario: g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_withXpropertyName_pageRankX_withXedges_inEX_withXtimes_1X_inXcreatedX_groupXmX_byXpageRankX_capXmX
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().out("created").group("m").by(T.label).pageRank(1.0).by("pageRank").by(__.inE()).times(1).in("created").group("m").by("pageRank").cap("m")
+      g.withComputer().V().out("created").group("m").by(T.label).pageRank(1.0).with("~tinkerpop.pageRank.propertyName", "pageRank").with("~tinkerpop.pageRank.edges",__.inE()).with("~tinkerpop.pageRank.times", 1).in("created").group("m").by("pageRank").cap("m")
       """
     When iterated next
-    Then the result should have a count of 3
-
-    # TODO: would really like to have a full assertion here, but withComputer() makes stuff not always return in order.
-    # order could be forced, but that just bulks up the test. we could write better assertion logic but that makes it
-    # harder for GLVs to be tested.  
-    #  | result |
-    #  | m[{"d[1.0].d":"l[v[marko],v[marko],v[marko],v[peter],v[peter],v[peter]]","d[2.0].d":"l[v[josh],v[josh],v[josh],v[josh]]","software":"l[v[lop],v[lop],v[lop],v[ripple]]"}] |
+    Then the result should have a count of 3
\ No newline at end of file
diff --git a/gremlin-test/features/map/PeerPressure.feature b/gremlin-test/features/map/PeerPressure.feature
index 81ca6f8..4b73300 100644
--- a/gremlin-test/features/map/PeerPressure.feature
+++ b/gremlin-test/features/map/PeerPressure.feature
@@ -34,34 +34,18 @@
       | v[peter] |
     And the graph should return 6 for count of "g.withComputer().V().peerPressure().has(\"gremlin.peerPressureVertexProgram.cluster\")"
 
-  Scenario: g_V_peerPressure_byXclusterX_byXoutEXknowsXX_pageRankX1X_byXrankX_byXoutEXknowsXX_timesX2X_group_byXclusterX_byXrank_sumX_limitX100X
+  Scenario: g_V_peerPressure_withXpropertyName_clusterX_withXedges_outEXknowsXX_pageRankX1X_byXrankX_withXedges_outEXknowsX_withXtimes_2X_group_byXclusterX_byXrank_sumX_limitX100X
     Given the modern graph
     And the traversal of
       """
-      g.withComputer().V().peerPressure().by("cluster").by(__.outE("knows")).pageRank(1.0).by("rank").by(__.outE("knows")).times(1).group().by("cluster").by(__.values("rank").sum()).limit(100)
+      g.withComputer().V().peerPressure().with("~tinkerpop.peerPressure.propertyName","cluster").with("~tinkerpop.peerPressure.edges",__.outE("knows")).pageRank(1.0).with("~tinkerpop.pageRank.propertyName", "rank").with("~tinkerpop.pageRank.edges", __.outE("knows")).with("~tinkerpop.pageRank.times", 1).group().by("cluster").by(__.values("rank").sum()).limit(100)
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | m[{"d[1].i":"d[0.5833333333333333].d","d[3].i":"d[0.1388888888888889].d","d[5].i":"d[0.1388888888888889].d","d[6].i":"d[0.1388888888888889].d"}] |
 
-  Scenario: g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX
-    Given the modern graph
-    And the traversal of
-      """
-      g.withComputer().V().has("name", "ripple").in("created").peerPressure().by(__.outE()).by("cluster").repeat(__.union(__.identity(), __.both())).times(2).dedup().valueMap("name", "cluster")
-      """
-    When iterated to list
-    Then the result should be unordered
-      | result |
-      | m[{"name": ["marko"], "cluster": [1]}] |
-      | m[{"name": ["vadas"], "cluster": [2]}] |
-      | m[{"name": ["lop"], "cluster": [4]}] |
-      | m[{"name": ["josh"], "cluster": [4]}] |
-      | m[{"name": ["ripple"], "cluster": [4]}] |
-      | m[{"name": ["peter"], "cluster": [6]}] |
-
-  Scenario: g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXEDGES_outEX_withXPROPERTY_NAME_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX
+  Scenario: g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withyXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX
     Given the modern graph
     And the traversal of
       """
diff --git a/gremlin-test/features/map/Select.feature b/gremlin-test/features/map/Select.feature
index 4a6d5e7..de5d41b 100644
--- a/gremlin-test/features/map/Select.feature
+++ b/gremlin-test/features/map/Select.feature
@@ -185,9 +185,10 @@
 
   Scenario: g_V_chooseXoutE_count_isX0X__asXaX__asXbXX_chooseXselectXaX__selectXaX__selectXbXX
     Given the modern graph
+    And using the parameter zero defined as "d[0].l"
     And the traversal of
       """
-      g.V().choose(__.outE().count().is(0L),
+      g.V().choose(__.outE().count().is(zero),
                    __.as("a"),
                    __.as("b")).
             choose(__.select("a"),
@@ -790,4 +791,27 @@
     Then the result should be unordered
       | result |
       | v[marko] |
-      | v[marko] |
\ No newline at end of file
+      | v[marko] |
+  Scenario: g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX
+    Given the modern graph
+    And using the parameter e11Id defined as "e[josh-created->lop].id"
+    And the traversal of
+      """
+      g.E(e11Id).properties("weight").as("a").select("a").by(T.key)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | weight |
+
+  Scenario: g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX
+    Given the modern graph
+    And using the parameter e11Id defined as "e[josh-created->lop].id"
+    And the traversal of
+      """
+      g.E(e11Id).properties("weight").as("a").select("a").by(T.value)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[0.4].d |
\ No newline at end of file
diff --git a/gremlin-test/features/sideEffect/Group.feature b/gremlin-test/features/sideEffect/Group.feature
index e69b447..a4a5500 100644
--- a/gremlin-test/features/sideEffect/Group.feature
+++ b/gremlin-test/features/sideEffect/Group.feature
@@ -28,6 +28,17 @@
       | result |
       | m[{"ripple":"l[v[ripple]]", "peter":"l[v[peter]]", "vadas":"l[v[vadas]]", "josh": "l[v[josh]]", "lop":"l[v[lop]]", "marko":"l[v[marko]]"}] |
 
+  Scenario: g_V_group_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().group().by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"null":"l[v[lop],v[ripple]]", "d[35].i":"l[v[peter]]", "d[27].i":"l[v[vadas]]", "d[32].i": "l[v[josh]]", "d[29].i":"l[v[marko]]"}] |
+
   Scenario: g_V_group_byXnameX_by
     Given the modern graph
     And the traversal of
@@ -262,3 +273,25 @@
       | result |
       | m[{"ripple":"d[32].l", "lop":"d[96].l"}] |
 
+
+  Scenario: g_V_group_byXlabelX_byXlabel_countX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().group().by(__.label()).by(__.label().count())
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"software":"d[2].l", "person":"d[4].l"}] |
+
+  Scenario: g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().group("m").by(__.label()).by(__.label().count()).cap("m")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"software":"d[2].l", "person":"d[4].l"}] |
diff --git a/gremlin-test/features/sideEffect/Inject.feature b/gremlin-test/features/sideEffect/Inject.feature
index 740928d..20d6bd2 100644
--- a/gremlin-test/features/sideEffect/Inject.feature
+++ b/gremlin-test/features/sideEffect/Inject.feature
@@ -66,3 +66,42 @@
       | lop   |
       | vadas |
       | josh  |
+
+  Scenario: g_injectXnull_1_3_nullX
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject(null, 1, 3, null)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | null |
+      | d[1].i |
+      | d[3].i |
+      | null |
+
+  Scenario: g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject(10,20,null,20,10,10).groupCount("x").dedup().as("y").project("a","b").by().by(__.select("x").select(__.select("y")))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"a":"d[10].i", "b":"d[3].l"}] |
+      | m[{"a":"d[20].i", "b":"d[2].l"}] |
+      | m[{"a":null, "b":"d[1].l"}] |
+
+  Scenario: g_injectXname_marko_age_nullX_selectXname_ageX
+    Given the empty graph
+    And using the parameter m defined as "m[{\"name\":\"marko\", \"age\":null}]"
+    And the traversal of
+      """
+      g.inject(m).select("name","age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"name":"marko", "age":null}] |
\ No newline at end of file
diff --git a/gremlin-test/pom.xml b/gremlin-test/pom.xml
index 3d737bc..d9efbca 100644
--- a/gremlin-test/pom.xml
+++ b/gremlin-test/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-test</artifactId>
     <name>Apache TinkerPop :: Gremlin Test</name>
@@ -45,13 +45,18 @@
         </dependency>
         <dependency>
             <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
+            <artifactId>hamcrest</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-log4j12</artifactId>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.apache.kerby</groupId>
+            <artifactId>kerb-simplekdc</artifactId>
+            <version>2.0.0</version>
+        </dependency>
     </dependencies>
     <build>
         <directory>${basedir}/target</directory>
@@ -77,6 +82,24 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
+            <plugin>
+                <!--Needed for docker/gremlin-server.sh-->
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
@@ -96,7 +119,7 @@
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-surefire-plugin</artifactId>
                         <configuration>
-                            <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true
+                            <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true ${suresafeArgs}
                             </argLine>
                             <excludes>
                                 <exclude>TraversalInterruptionTest.java</exclude>
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractFileGraphProvider.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractFileGraphProvider.java
index 18e9a0d..cedbf38 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractFileGraphProvider.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractFileGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.io.Storage;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONResourceAccess;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
index 3ec2ab1..cc2df41 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
@@ -23,8 +23,8 @@
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoIo;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoReader;
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoResourceAccess;
 import org.slf4j.Logger;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java
index f069a12..ccb8ad3 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphManager.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphManager.java
index 7506226..a0eb9f6 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphManager.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphManager.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphProvider.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphProvider.java
index efe270a..da81e15 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphProvider.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/GraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
@@ -116,8 +116,7 @@
 
     /**
      * Creates a new {@link Graph} instance using the default
-     * {@code org.apache.commons.configuration.Configuration} from
-     * {@link #standardGraphConfiguration(Class, String, LoadGraphWith.GraphData)}.
+     * {@code Configuration} from {@link #standardGraphConfiguration(Class, String, LoadGraphWith.GraphData)}.
      */
     default public Graph standardTestGraph(final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData loadGraphWith) {
         return GraphFactory.open(standardGraphConfiguration(test, testMethodName, loadGraphWith));
@@ -146,11 +145,11 @@
     /**
      * If possible (usually with persisted graph) clear the space on disk given the configuration that would be used
      * to construct the graph.  The default implementation simply calls
-     * {@link #clear(Graph, org.apache.commons.configuration.Configuration)} with
+     * {@link #clear(Graph, Configuration)} with
      * a null graph argument.
      * <p/>
-     * Implementations should be able to accept an argument of null for the {@code org.apache.commons.configuration.Configuration}
-     * as well, and a proper handling is needed. Otherwise, a NullPointerException may be thrown.
+     * Implementations should be able to accept an argument of null for the {@code Configuration} as well, and a
+     * proper handling is needed. Otherwise, a NullPointerException may be thrown.
      */
     public default void clear(final Configuration configuration) throws Exception {
         clear(null, configuration);
@@ -166,8 +165,8 @@
      * that can be performed is a clear given the configuration.  The method will typically be called this way
      * as clean up task on setup to ensure that a persisted graph has a clear space to create a test graph.
      * <p/>
-     * Implementations should be able to accept an argument of null for the {@code org.apache.commons.configuration.Configuration}
-     * as well, and a proper handling is needed. Otherwise, a NullPointerException may be thrown.
+     * Implementations should be able to accept an argument of null for the {@code Configuration} as well, and a
+     * proper handling is needed. Otherwise, a NullPointerException may be thrown.
      * <p/>
      * Calls to this method may occur multiple times for a specific test. Develop this method to be idempotent.
      */
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/CommunityGeneratorTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/CommunityGeneratorTest.java
index f8e5cad..2ba5874 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/CommunityGeneratorTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/CommunityGeneratorTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.algorithm.generator;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/DistributionGeneratorTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/DistributionGeneratorTest.java
index 8a2842f..376e8bb 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/DistributionGeneratorTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/DistributionGeneratorTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.algorithm.generator;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
index 7d1e0a7..1ff71d4 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
@@ -38,7 +38,6 @@
 
 import static org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineSuite.ENGINE_TO_TEST;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.AnyOf.anyOf;
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assume.assumeThat;
@@ -163,12 +162,9 @@
     }
 
     private static GraphTraversal<Vertex, Long> getTraversalWithLambda(final GraphTraversalSource g) {
-        assumeThat("This test is not enabled for this ScriptEngine: " + ENGINE_TO_TEST, ENGINE_TO_TEST,
-                anyOf(is("gremlin-python"), is("gremlin-jython"), is("gremlin-groovy")));
+        assumeThat("This test is not enabled for this ScriptEngine: " + ENGINE_TO_TEST, ENGINE_TO_TEST, is("gremlin-groovy"));
         if (ENGINE_TO_TEST.equals("gremlin-groovy"))
             return g.V().out("created").map(Lambda.function("{x -> x.get().values('name')}")).count();
-        else if (ENGINE_TO_TEST.equals("gremlin-python") || ENGINE_TO_TEST.equals("gremlin-jython"))
-            return g.V().out("created").map(Lambda.function("x : x.get().values('name')")).count();
         else
             throw new RuntimeException("The " + ENGINE_TO_TEST + " ScriptEngine is not supported by this test");
     }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
index 0a2a405..09044de 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
@@ -20,7 +20,6 @@
 
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.GraphManager;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
@@ -35,6 +34,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -98,14 +98,7 @@
             assertThat(sideEffects.keys().contains(key), is(true));
             assertThat(sideEffects.exists(key), is(true));
             assertThat(sideEffects.exists(UUID.randomUUID().toString()), is(false));
-
-            // there is slightly different behavior for remote side-effects so carving out a few asserts with that
-            // in mind. the client really doesnt' really have a way of knowing what type of object to create when it
-            // gets an empty iterator so it makes the result null and therefore we end up with a NPE if we try to
-            // access it. the rest of the behavior is solid so better to do this than OptOut I think
-            if (!(sideEffects instanceof RemoteTraversalSideEffects)) {
-                assertEquals(clazz, sideEffects.get((String) keysClasses[i]).getClass());
-            }
+            assertEquals(clazz, sideEffects.get((String) keysClasses[i]).getClass());
         }
         assertEquals(sideEffects.keys().size(), counter);
         assertThat(sideEffects.keys().contains(UUID.randomUUID().toString()), is(false));
@@ -192,10 +185,10 @@
         }
 
         for (int i = 0; i < actualList.size(); i++) {
-            if (!actualList.get(i).getKey().equals(expectedList.get(i).getKey())) {
+            if (!Objects.equals(actualList.get(i).getKey(), expectedList.get(i).getKey())) {
                 return false;
             }
-            if (!actualList.get(i).getValue().equals(expectedList.get(i).getValue())) {
+            if (!Objects.equals(actualList.get(i).getValue(), expectedList.get(i).getValue())) {
                 return false;
             }
         }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
index 3ca5b76..8785e90 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
@@ -21,10 +21,7 @@
 import org.apache.tinkerpop.gremlin.AbstractGremlinSuite;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputerTest;
-import org.apache.tinkerpop.gremlin.process.computer.bulkdumping.BulkDumperVertexProgramTest;
-import org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgramTest;
 import org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgramTest;
-import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.PeerPressureVertexProgramTest;
 import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgramTest;
 import org.apache.tinkerpop.gremlin.process.computer.search.path.ShortestPathVertexProgramTest;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
@@ -92,6 +89,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StoreTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategyProcessTest;
@@ -201,10 +199,7 @@
 
             // algorithms
             PageRankVertexProgramTest.class,
-            PeerPressureVertexProgramTest.class,
             ShortestPathVertexProgramTest.class,
-            BulkLoaderVertexProgramTest.class,
-            BulkDumperVertexProgramTest.class,
             CloneVertexProgramTest.class,
 
             // creations
@@ -212,6 +207,7 @@
 
             // decorations
             ReadOnlyStrategyProcessTest.class,
+            SeedStrategyProcessTest.class,
             SubgraphStrategyProcessTest.class,
 
             // optimizations
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index f127ca0..2f31678 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -86,6 +86,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategyProcessTest;
@@ -193,6 +194,7 @@
             EventStrategyProcessTest.class,
             ReadOnlyStrategyProcessTest.class,
             PartitionStrategyProcessTest.class,
+            SeedStrategyProcessTest.class,
             SubgraphStrategyProcessTest.class,
 
             // optimizations
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index d16c8b8..1cd5de5 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.process.computer;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationUtils;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ConfigurationUtils;
 import org.apache.tinkerpop.gremlin.ExceptionCoverage;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
@@ -1168,6 +1168,7 @@
     /////////////////////////////////////////////
 
     /////////////////////////////////////////////
+
     @Test
     @LoadGraphWith(MODERN)
     public void shouldStartAndEndWorkersForVertexProgramAndMapReduce() throws Exception {
@@ -1175,17 +1176,17 @@
         MapReduceI.WORKER_END.clear();
         assertEquals(3, graphProvider.getGraphComputer(graph).program(new VertexProgramJ()).mapReduce(new MapReduceI()).submit().get().memory().<Integer>get("a").intValue());
         if (MapReduceI.WORKER_START.size() == 2) {
-            assertEquals(2, MapReduceI.WORKER_START.size());
+            assertEquals(2, MapReduceI.countTrue(MapReduceI.WORKER_START));
             assertTrue(MapReduceI.WORKER_START.contains(MapReduce.Stage.MAP) && MapReduceI.WORKER_START.contains(MapReduce.Stage.REDUCE));
         } else {
-            assertEquals(3, MapReduceI.WORKER_START.size());
+            assertEquals(3, MapReduceI.countTrue(MapReduceI.WORKER_START));
             assertTrue(MapReduceI.WORKER_START.contains(MapReduce.Stage.MAP) && MapReduceI.WORKER_START.contains(MapReduce.Stage.COMBINE) && MapReduceI.WORKER_START.contains(MapReduce.Stage.REDUCE));
         }
         if (MapReduceI.WORKER_END.size() == 2) {
-            assertEquals(2, MapReduceI.WORKER_END.size());
+            assertEquals(2, MapReduceI.countTrue(MapReduceI.WORKER_END));
             assertTrue(MapReduceI.WORKER_END.contains(MapReduce.Stage.MAP) && MapReduceI.WORKER_END.contains(MapReduce.Stage.REDUCE));
         } else {
-            assertEquals(3, MapReduceI.WORKER_END.size());
+            assertEquals(3, MapReduceI.countTrue(MapReduceI.WORKER_END));
             assertTrue(MapReduceI.WORKER_END.contains(MapReduce.Stage.MAP) && MapReduceI.WORKER_END.contains(MapReduce.Stage.COMBINE) && MapReduceI.WORKER_END.contains(MapReduce.Stage.REDUCE));
         }
     }
@@ -1272,14 +1273,14 @@
         @Override
         public void map(final Vertex vertex, final MapEmitter<NullObject, Integer> emitter) {
             emitter.emit(1);
-            assertEquals(1, WORKER_START.size());
+            assertEquals(1, countTrue(WORKER_START));
             assertTrue(WORKER_START.contains(Stage.MAP));
         }
 
         @Override
         public void combine(final NullObject key, final Iterator<Integer> values, final ReduceEmitter<NullObject, Integer> emitter) {
             emitter.emit(2);
-            assertEquals(2, WORKER_START.size());
+            assertEquals(2, countTrue(WORKER_START));
             assertTrue(WORKER_START.contains(Stage.MAP) && WORKER_START.contains(Stage.COMBINE));
             assertFalse(WORKER_END.isEmpty());
         }
@@ -1287,11 +1288,11 @@
         @Override
         public void reduce(final NullObject key, final Iterator<Integer> values, final ReduceEmitter<NullObject, Integer> emitter) {
             emitter.emit(3);
-            if (WORKER_START.size() == 2) {
-                assertEquals(2, WORKER_START.size());
+            if (IteratorUtils.count(WORKER_START) == 2) {
+                assertEquals(2, countTrue(WORKER_START));
                 assertTrue(WORKER_START.contains(Stage.MAP) && WORKER_START.contains(Stage.REDUCE));
             } else {
-                assertEquals(3, WORKER_START.size());
+                assertEquals(3, countTrue(WORKER_START));
                 assertTrue(WORKER_START.contains(Stage.MAP) && WORKER_START.contains(Stage.COMBINE) && WORKER_START.contains(Stage.REDUCE));
             }
             assertFalse(WORKER_END.isEmpty());
@@ -1315,6 +1316,15 @@
         public String getMemoryKey() {
             return "a";
         }
+
+        /**
+         * Javadoc for {@code ConcurrentSkipListSet} includes this little note: "Beware that, unlike in most
+         * collections, the size method is not a constant-time operation." Doing a traversal of elements will yield
+         * the correct count. Java 11 upgrade seemed to force this failure consistently.
+         */
+        static int countTrue(final Set<Stage> s) {
+            return Long.valueOf(IteratorUtils.count(s)).intValue();
+        }
     }
 
     /////////////////////////////////////////////
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkdumping/BulkDumperVertexProgramTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkdumping/BulkDumperVertexProgramTest.java
deleted file mode 100644
index 62104c0..0000000
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkdumping/BulkDumperVertexProgramTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.computer.bulkdumping;
-
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
-import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
-import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
-import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.junit.Test;
-
-import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class BulkDumperVertexProgramTest extends AbstractGremlinProcessTest {
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldDumpWholeGraph() throws Exception {
-        if (graphProvider.getGraphComputer(graph).features().supportsResultGraphPersistCombination(GraphComputer.ResultGraph.NEW, GraphComputer.Persist.EDGES)) {
-            final ComputerResult result = graphProvider.getGraphComputer(graph).program(BulkDumperVertexProgram.build().create(graph)).submit().get();
-            result.graph().traversal().V().forEachRemaining(v -> {
-                assertEquals(2, v.keys().size());
-                assertTrue(v.keys().contains("name"));
-                assertTrue(v.keys().contains("age") || v.keys().contains("lang"));
-                assertEquals(1, IteratorUtils.count(v.values("name")));
-                assertEquals(1, IteratorUtils.count(v.values("age", "lang")));
-                final String name = v.value("name");
-                if (name.equals("marko")) {
-                    assertEquals("person", v.label());
-                    assertEquals(Integer.valueOf(29), v.value("age"));
-                    assertEquals(3, IteratorUtils.count(v.edges(Direction.OUT)));
-                    assertEquals(2, IteratorUtils.count(v.edges(Direction.OUT, "knows")));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.OUT, "created")));
-                    assertEquals(0, IteratorUtils.count(v.edges(Direction.IN)));
-                } else if (name.equals("vadas")) {
-                    assertEquals("person", v.label());
-                    assertEquals(Integer.valueOf(27), v.value("age"));
-                    assertEquals(0, IteratorUtils.count(v.edges(Direction.OUT)));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.IN)));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.IN, "knows")));
-                } else if (name.equals("lop")) {
-                    assertEquals("software", v.label());
-                    assertEquals("java", v.value("lang"));
-                    assertEquals(0, IteratorUtils.count(v.edges(Direction.OUT)));
-                    assertEquals(3, IteratorUtils.count(v.edges(Direction.IN)));
-                    assertEquals(3, IteratorUtils.count(v.edges(Direction.IN, "created")));
-                } else if (name.equals("josh")) {
-                    assertEquals("person", v.label());
-                    assertEquals(Integer.valueOf(32), v.value("age"));
-                    assertEquals(2, IteratorUtils.count(v.edges(Direction.OUT)));
-                    assertEquals(2, IteratorUtils.count(v.edges(Direction.OUT, "created")));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.IN)));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.IN, "knows")));
-                } else if (name.equals("ripple")) {
-                    assertEquals("software", v.label());
-                    assertEquals("java", v.value("lang"));
-                    assertEquals(0, IteratorUtils.count(v.edges(Direction.OUT)));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.IN)));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.IN, "created")));
-                } else if (name.equals("peter")) {
-                    assertEquals("person", v.label());
-                    assertEquals(Integer.valueOf(35), v.value("age"));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.OUT)));
-                    assertEquals(1, IteratorUtils.count(v.edges(Direction.OUT, "created")));
-                    assertEquals(0, IteratorUtils.count(v.edges(Direction.IN)));
-                } else
-                    throw new IllegalStateException("The following vertex should not exist in the graph: " + name);
-            });
-            assertEquals(3.5, (Double) result.graph().traversal().E().values("weight").sum().next(), 0.01);
-            assertEquals(1.5, (Double) result.graph().traversal().E().hasLabel("knows").values("weight").sum().next(), 0.01);
-            assertEquals(2.0, (Double) result.graph().traversal().E().hasLabel("created").values("weight").sum().next(), 0.01);
-            assertEquals(result.memory().getIteration(), 0);
-            assertEquals(result.memory().asMap().size(), 0);
-        }
-    }
-}
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoaderVertexProgramTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoaderVertexProgramTest.java
deleted file mode 100644
index 47eb1eb..0000000
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/bulkloading/BulkLoaderVertexProgramTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.computer.bulkloading;
-
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
-import org.apache.tinkerpop.gremlin.TestHelper;
-import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
-import org.apache.tinkerpop.gremlin.process.IgnoreEngine;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
-import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.junit.After;
-import org.junit.Test;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.Iterator;
-import java.util.function.Function;
-
-import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class BulkLoaderVertexProgramTest extends AbstractGremlinProcessTest {
-
-    final static String TINKERGRAPH_LOCATION = TestHelper.makeTestDataFile(BulkLoaderVertexProgramTest.class, "tinkertest.kryo");
-
-    private BulkLoader getBulkLoader(final BulkLoaderVertexProgram blvp) throws Exception {
-        final Field field = BulkLoaderVertexProgram.class.getDeclaredField("bulkLoader");
-        field.setAccessible(true);
-        return (BulkLoader) field.get(blvp);
-    }
-
-    private Configuration getWriteGraphConfiguration() {
-        final Configuration configuration = new BaseConfiguration();
-        configuration.setProperty(Graph.GRAPH, "org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph");
-        configuration.setProperty("gremlin.tinkergraph.graphLocation", TINKERGRAPH_LOCATION);
-        configuration.setProperty("gremlin.tinkergraph.graphFormat", "gryo");
-        return configuration;
-    }
-
-    private Graph getWriteGraph() {
-        return GraphFactory.open(getWriteGraphConfiguration());
-    }
-
-    @After
-    public void cleanup() {
-        final File graph = new File(TINKERGRAPH_LOCATION);
-        assertTrue(!graph.exists() || graph.delete());
-    }
-
-    @Test
-    public void shouldUseIncrementalBulkLoaderByDefault() throws Exception {
-        final BulkLoader loader = getBulkLoader(BulkLoaderVertexProgram.build().create(graph));
-        assertTrue(loader instanceof IncrementalBulkLoader);
-        assertTrue(loader.keepOriginalIds());
-        assertFalse(loader.useUserSuppliedIds());
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldStoreOriginalIds() throws Exception {
-        final BulkLoaderVertexProgram blvp = BulkLoaderVertexProgram.build()
-                .userSuppliedIds(false)
-                .writeGraph(getWriteGraphConfiguration()).create(graph);
-        final BulkLoader loader = getBulkLoader(blvp);
-        assertFalse(loader.useUserSuppliedIds());
-        graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get();
-        assertGraphEquality(graph, getWriteGraph(), v -> v.value(loader.getVertexIdProperty()));
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldNotStoreOriginalIds() throws Exception {
-        final BulkLoaderVertexProgram blvp = BulkLoaderVertexProgram.build()
-                .userSuppliedIds(true)
-                .writeGraph(getWriteGraphConfiguration()).create(graph);
-        final BulkLoader loader = getBulkLoader(blvp);
-        assertTrue(loader.useUserSuppliedIds());
-        graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get();
-        assertGraphEquality(graph, getWriteGraph());
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldOverwriteExistingElements() throws Exception {
-        final BulkLoaderVertexProgram blvp = BulkLoaderVertexProgram.build()
-                .userSuppliedIds(true)
-                .writeGraph(getWriteGraphConfiguration()).create(graph);
-        graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get(); // initial
-        graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get(); // incremental
-        assertGraphEquality(graph, getWriteGraph());
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    @IgnoreEngine(TraversalEngine.Type.COMPUTER) // we can't modify the graph in computer mode
-    public void shouldProperlyHandleMetaProperties() throws Exception {
-        graph.traversal().V().has("name", "marko").properties("name").property("alias", "okram").iterate();
-        final BulkLoaderVertexProgram blvp = BulkLoaderVertexProgram.build()
-                .userSuppliedIds(true)
-                .writeGraph(getWriteGraphConfiguration()).create(graph);
-        graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get();
-        assertGraphEquality(graph, getWriteGraph());
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldUseOneTimeBulkLoader() throws Exception {
-        for (int iteration = 1; iteration <= 2; iteration++) {
-            final BulkLoaderVertexProgram blvp = BulkLoaderVertexProgram.build()
-                    .bulkLoader(OneTimeBulkLoader.class)
-                    .writeGraph(getWriteGraphConfiguration()).create(graph);
-            final BulkLoader loader = getBulkLoader(blvp);
-            assertTrue(loader instanceof OneTimeBulkLoader);
-            graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get();
-            final Graph result = getWriteGraph();
-            assertEquals(6 * iteration, IteratorUtils.count(result.vertices()));
-            assertEquals(6 * iteration, IteratorUtils.count(result.edges()));
-            result.close();
-        }
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldUseOneTimeBulkLoaderWithUserSuppliedIds() throws Exception {
-        final BulkLoaderVertexProgram blvp = BulkLoaderVertexProgram.build()
-                .bulkLoader(OneTimeBulkLoader.class)
-                .userSuppliedIds(true)
-                .writeGraph(getWriteGraphConfiguration()).create(graph);
-        final BulkLoader loader = getBulkLoader(blvp);
-        assertTrue(loader instanceof OneTimeBulkLoader);
-        graphProvider.getGraphComputer(graph).workers(1).program(blvp).submit().get();
-        final Graph result = getWriteGraph();
-        assertEquals(6, IteratorUtils.count(result.vertices()));
-        assertEquals(6, IteratorUtils.count(result.edges()));
-        result.close();
-    }
-
-    private static void assertGraphEquality(final Graph source, final Graph target) {
-        assertGraphEquality(source, target, Element::id);
-    }
-
-    private static void assertGraphEquality(final Graph source, final Graph target, final Function<Vertex, Object> idAccessor) {
-        final GraphTraversalSource tg = target.traversal();
-        assertEquals(IteratorUtils.count(source.vertices()), IteratorUtils.count(target.vertices()));
-        assertEquals(IteratorUtils.count(source.edges()), IteratorUtils.count(target.edges()));
-        source.vertices().forEachRemaining(originalVertex -> {
-            Vertex tmpVertex = null;
-            final Iterator<Vertex> vertexIterator = target.vertices();
-            while (vertexIterator.hasNext()) {
-                final Vertex v = vertexIterator.next();
-                if (idAccessor.apply(v).toString().equals(originalVertex.id().toString())) {
-                    tmpVertex = v;
-                    break;
-                }
-            }
-
-            CloseableIterator.closeIterator(vertexIterator);
-
-            assertNotNull(tmpVertex);
-            final Vertex clonedVertex = tmpVertex;
-            assertEquals(IteratorUtils.count(originalVertex.edges(Direction.IN)), IteratorUtils.count(clonedVertex.edges(Direction.IN)));
-            assertEquals(IteratorUtils.count(originalVertex.edges(Direction.OUT)), IteratorUtils.count(clonedVertex.edges(Direction.OUT)));
-            assertEquals(originalVertex.label(), clonedVertex.label());
-            originalVertex.properties().forEachRemaining(originalProperty -> {
-                VertexProperty clonedProperty = null;
-                final Iterator<VertexProperty<Object>> vertexPropertyIterator = clonedVertex.properties(originalProperty.key());
-                while (vertexPropertyIterator.hasNext()) {
-                    final VertexProperty p = vertexPropertyIterator.next();
-                    if (p.value().equals(originalProperty.value())) {
-                        clonedProperty = p;
-                        break;
-                    }
-                }
-                assertNotNull(clonedProperty);
-                assertEquals(originalProperty.isPresent(), clonedProperty.isPresent());
-                assertEquals(originalProperty.value(), clonedProperty.value());
-            });
-            originalVertex.edges(Direction.OUT).forEachRemaining(originalEdge -> {
-                GraphTraversal t = tg.V(clonedVertex).outE(originalEdge.label());
-                originalEdge.properties().forEachRemaining(p -> t.has(p.key(), p.value()));
-                assertTrue(t.hasNext());
-                CloseableIterator.closeIterator(t);
-            });
-        });
-    }
-}
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgramTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgramTest.java
deleted file mode 100644
index 1d840b0..0000000
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgramTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.computer.clustering.peerpressure;
-
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
-import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
-import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
-import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.junit.Test;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class PeerPressureVertexProgramTest extends AbstractGremlinProcessTest {
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void shouldExecutePeerPressure() throws Exception {
-        /*if (g.getGraphComputer().get().features().supportsResultGraphPersistCombination(GraphComputer.ResultGraph.NEW, GraphComputer.Persist.VERTEX_PROPERTIES)) {
-            final ComputerResult result = graph.compute(g.getGraphComputer().get().getClass()).program(PeerPressureVertexProgram.build().create(graph)).submit().get();
-            final Set<Object> clusters = new HashSet<>();
-            result.graph().traversal().V().forEachRemaining(v -> {
-                assertEquals(4, v.keys().size()); // name, age/lang, voteStrength, cluster
-                assertTrue(v.keys().contains("name"));
-                assertTrue(v.keys().contains(PeerPressureVertexProgram.VOTE_STRENGTH));
-                assertTrue(v.keys().contains(PeerPressureVertexProgram.CLUSTER));
-                assertEquals(1, IteratorUtils.count(v.values("name")));
-                assertEquals(1, IteratorUtils.count(v.values(PeerPressureVertexProgram.CLUSTER)));
-                final Object cluster = v.value(PeerPressureVertexProgram.CLUSTER);
-                clusters.add(cluster);
-            });
-            //assertEquals(2, clusters.size());
-            //assertEquals(3, result.memory().getIteration());
-            assertEquals(1, result.memory().asMap().size());
-            assertTrue(result.memory().keys().contains("gremlin.peerPressureVertexProgram.voteToHalt"));  // this is private in PeerPressureVertexProgram (and that is okay)
-        }*/
-    }
-}
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java
index cf34ee2..43dcf15 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java
@@ -51,6 +51,7 @@
 import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -68,6 +69,44 @@
 public class CoreTraversalTest extends AbstractGremlinProcessTest {
 
     @Test
+    @LoadGraphWith(MODERN)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES)
+    public void g_addVXpersonX_propertyXname_nullX() {
+        final Traversal<Vertex, Vertex> traversal = g.addV("person").property("name", null);
+        printTraversalForm(traversal);
+        final Vertex nulled = traversal.next();
+        assertFalse(traversal.hasNext());
+        assertEquals("person", nulled.label());
+        assertNull(nulled.value("name"));
+        assertEquals(1, IteratorUtils.count(nulled.properties()));
+        assertEquals(7, IteratorUtils.count(g.V()));
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+    @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_NULL_PROPERTY_VALUES)
+    public void g_VX1X_asXaX_outXcreatedX_addEXcreatedByX_toXaX_propertyXweight_nullX() {
+        final Traversal<Vertex, Edge> traversal = g.V(convertToVertexId("marko")).as("a").out("created").addE("createdBy").to("a").property("weight", null);
+        printTraversalForm(traversal);
+        int count = 0;
+        while (traversal.hasNext()) {
+            final Edge edge = traversal.next();
+            assertEquals("createdBy", edge.label());
+            assertNull(g.E(edge).<Double>values("weight").next());
+            assertEquals(1, g.E(edge).properties().count().next().intValue());
+            count++;
+
+
+        }
+        assertEquals(1, count);
+        assertEquals(7, IteratorUtils.count(g.E()));
+        assertEquals(6, IteratorUtils.count(g.V()));
+    }
+
+    @Test
     @LoadGraphWith
     public void shouldNeverPropagateANoBulkTraverser() {
         try {
@@ -80,18 +119,6 @@
     }
 
     @Test
-    @LoadGraphWith
-    public void shouldNeverPropagateANullValuedTraverser() {
-        try {
-            assertFalse(g.V().map(t -> null).hasNext());
-            assertEquals(0, g.V().map(t -> null).toList().size());
-            g.V().map(t -> null).sideEffect(t -> fail("this should not have happened")).iterate();
-        } catch (VerificationException e) {
-            // its okay if lambdas can't be serialized by the test suite
-        }
-    }
-
-    @Test
     @LoadGraphWith(MODERN)
     public void shouldFilterOnIterate() {
         final Traversal<Vertex,String> traversal = g.V().out().out().<String>values("name").aggregate("x").iterate();
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
index 0110d44..f7735c6 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
@@ -317,27 +317,27 @@
             return g.withoutStrategies(ComputerVerificationStrategy.class, PathRetractionStrategy.class).
                     V().as("v").both().as("v").
                     project("src", "tgt", "p").
-                    by(select(first, "v")).
-                    by(select(last, "v")).
-                    by(select(all, "v")).as("triple").
+                      by(select(first, "v")).
+                      by(select(last, "v")).
+                      by(select(all, "v")).as("triple").
                     group("x").
-                    by(select("src", "tgt")).
-                    by(select("p").fold()).select("tgt").barrier().
+                      by(select("src", "tgt")).
+                      by(select("p").fold()).select("tgt").barrier().
                     repeat(both().as("v").
                             project("src", "tgt", "p").
-                            by(select(first, "v")).
-                            by(select(last, "v")).
-                            by(select(all, "v")).as("t").
+                              by(select(first, "v")).
+                              by(select(last, "v")).
+                              by(select(all, "v")).as("t").
                             filter(select(all, "p").count(local).as("l").
-                                    select(last, "t").select(all, "p").dedup(local).count(local).where(eq("l"))).
+                                   select(last, "t").select(all, "p").dedup(local).count(local).where(eq("l"))).
                             select(last, "t").
                             not(select(all, "p").as("p").count(local).as("l").
-                                    select(all, "x").unfold().filter(select(keys).where(eq("t")).by(select("src", "tgt"))).
-                                    filter(select(values).unfold().or(count(local).where(lt("l")), where(eq("p"))))).
+                                select(all, "x").unfold().filter(select(keys).where(eq("t")).by(select("src", "tgt"))).
+                                filter(select(values).unfold().or(count(local).where(lt("l")), where(eq("p"))))).
                             barrier().
                             group("x").
-                            by(select("src", "tgt")).
-                            by(select(all, "p").fold()).select("tgt").barrier()).
+                              by(select("src", "tgt")).
+                              by(select(all, "p").fold()).select("tgt").barrier()).
                     cap("x").select(values).unfold().unfold().map(unfold().id().fold());
         }
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
index 0877ddb..d8342f3 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
@@ -40,6 +40,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.CREW;
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE;
@@ -91,6 +92,12 @@
 
     public abstract Traversal<Vertex, Long> get_g_V_repeatXdedupX_timesX2X_count();
 
+    public abstract Traversal<Vertex, Long> get_g_V_bothE_properties_dedup_count();
+
+    public abstract Traversal<Vertex, Long> get_g_V_both_properties_dedup_count();
+
+    public abstract Traversal<Vertex, Long> get_g_V_both_properties_properties_dedup_count();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold() {
@@ -312,6 +319,33 @@
         assertFalse(traversal.hasNext());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_bothE_properties_dedup_count() {
+        final Traversal<Vertex, Long> traversal = get_g_V_bothE_properties_dedup_count();
+        printTraversalForm(traversal);
+        assertEquals(4L, traversal.next().longValue());
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_both_properties_dedup_count() {
+        // vertex properties behave like Element with their dedup() so 12 is the right number there
+        final Traversal<Vertex, Long> traversal = get_g_V_both_properties_dedup_count();
+        printTraversalForm(traversal);
+        assertEquals(12L, traversal.next().longValue());
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(CREW)
+    public void g_V_both_properties_properties_dedup_count() {
+        final Traversal<Vertex, Long> traversal = get_g_V_both_properties_properties_dedup_count();
+        printTraversalForm(traversal);
+        assertEquals(21L, traversal.next().longValue());
+        assertFalse(traversal.hasNext());
+    }
 
     public static class Traversals extends DedupTest {
         @Override
@@ -393,5 +427,20 @@
         public Traversal<Vertex, Long> get_g_V_repeatXdedupX_timesX2X_count() {
             return g.V().repeat(dedup()).times(2).count();
         }
+
+        @Override
+        public Traversal<Vertex, Long> get_g_V_bothE_properties_dedup_count() {
+            return g.V().bothE().properties().dedup().count();
+        }
+
+        @Override
+        public Traversal<Vertex, Long> get_g_V_both_properties_dedup_count() {
+            return g.V().both().properties().dedup().count();
+        }
+
+        @Override
+        public Traversal<Vertex, Long> get_g_V_both_properties_properties_dedup_count() {
+            return g.V().both().properties().properties().dedup().count();
+        }
     }
 }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeTest.java
index 3a565be..5480108 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeTest.java
@@ -183,7 +183,7 @@
     }
 
     /**
-     * Scenario: limit step, Scope.local, >1 item requested, List<String> input, List<String> output
+     * Scenario: limit step, Scope.local, &gt;1 item requested, List&lt;String&gt; input, List&lt;String&gt; output
      */
     @Test
     @LoadGraphWith(MODERN)
@@ -212,7 +212,7 @@
     }
 
     /**
-     * Scenario: range step, Scope.local, >1 item requested, List<String> input, List<String> output
+     * Scenario: range step, Scope.local, &gt;1 item requested, List&lt;String&gt; input, List&lt;String&gt; output
      */
     @Test
     @LoadGraphWith(MODERN)
@@ -256,7 +256,7 @@
     }
 
     /**
-     * Scenario: limit step, Scope.local, >1 item requested, Map input, Map output
+     * Scenario: limit step, Scope.local, &gt;1 item requested, Map input, Map output
      */
     @Test
     @LoadGraphWith(MODERN)
@@ -286,7 +286,7 @@
     }
 
     /**
-     * Scenario: range step, Scope.local, >1 item requested, Map input, Map output
+     * Scenario: range step, Scope.local, &gt;1 item requested, Map input, Map output
      */
     @Test
     @LoadGraphWith(MODERN)
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java
index f48d0af..ce02bb3 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java
@@ -147,7 +147,7 @@
     }
 
     /**
-     * Scenario: Local scope, List input, N>1
+     * Scenario: Local scope, List input, N&gt;1
      */
     @Test
     @LoadGraphWith(MODERN)
@@ -202,7 +202,7 @@
     }
 
     /**
-     * Scenario: Local scope, Map input, N>1
+     * Scenario: Local scope, Map input, N&gt;1
      */
     @Test
     @LoadGraphWith(MODERN)
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeTest.java
index 54c4091..1e7f162 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeTest.java
@@ -44,6 +44,8 @@
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
 import static org.apache.tinkerpop.gremlin.structure.Column.keys;
 import static org.apache.tinkerpop.gremlin.structure.Column.values;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
@@ -58,6 +60,8 @@
 
     public abstract Traversal<Vertex, Edge> get_g_VX1X_asXaX_outXcreatedX_addEXcreatedByX_toXaX_propertyXweight_2X(final Object v1Id);
 
+    public abstract Traversal<Vertex, Edge> get_g_V_outE_propertyXweight_nullX();
+
     public abstract Traversal<Vertex, Edge> get_g_V_aggregateXxX_asXaX_selectXxX_unfold_addEXexistsWithX_toXaX_propertyXtime_nowX();
 
     public abstract Traversal<Vertex, Edge> get_g_V_asXaX_outXcreatedX_inXcreatedX_whereXneqXaXX_asXbX_addEXcodeveloperX_fromXaX_toXbX_propertyXyear_2009X();
@@ -120,6 +124,15 @@
 
     @Test
     @LoadGraphWith(MODERN)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES, supported = false)
+    public void g_V_outE_propertyXweight_nullX() {
+        final Traversal<Vertex, Edge> traversal = get_g_V_outE_propertyXweight_nullX();
+        printTraversalForm(traversal);
+        traversal.forEachRemaining(e -> assertThat(e.properties("weight").hasNext(), is(false)));
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
     public void g_V_aggregateXxX_asXaX_selectXxX_unfold_addEXexistsWithX_toXaX_propertyXtime_nowX() {
         final Traversal<Vertex, Edge> traversal = get_g_V_aggregateXxX_asXaX_selectXxX_unfold_addEXexistsWithX_toXaX_propertyXtime_nowX();
@@ -306,6 +319,11 @@
         }
 
         @Override
+        public Traversal<Vertex, Edge> get_g_V_outE_propertyXweight_nullX() {
+            return g.V().outE().property("weight", null);
+        }
+
+        @Override
         public Traversal<Vertex, Edge> get_g_V_aggregateXxX_asXaX_selectXxX_unfold_addEXexistsWithX_toXaX_propertyXtime_nowX() {
             return g.V().aggregate("x").as("a").select("x").unfold().addE("existsWith").to("a").property("time", "now");
         }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java
index 21fbb8c..ad0e1dd 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java
@@ -40,8 +40,11 @@
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.V;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -56,6 +59,12 @@
 
     public abstract Traversal<Vertex, Vertex> get_g_addVXpersonX_propertyXname_stephenX();
 
+    public abstract Traversal<Vertex, Vertex> get_g_V_hasLabelXpersonX_propertyXname_nullX();
+
+    public abstract Traversal<Vertex, Vertex> get_g_addVXnullX_propertyXid_nullX();
+
+    public abstract Traversal<Vertex, Vertex> get_g_addV_propertyXlabel_personX();
+
     public abstract Traversal<Vertex, Vertex> get_g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenmX();
 
     public abstract Traversal<Vertex, Vertex> get_g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenm_since_2010X();
@@ -91,7 +100,6 @@
         assertEquals(7, IteratorUtils.count(g.V()));
     }
 
-
     @Test
     @LoadGraphWith(MODERN)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
@@ -112,6 +120,31 @@
     }
 
     @Test
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
+    public void g_addVXnullX_propertyXid_nullX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_addVXnullX_propertyXid_nullX();
+        printTraversalForm(traversal);
+
+        final Vertex vertex = traversal.next();
+        assertEquals(Vertex.DEFAULT_LABEL, vertex.label());
+
+        // should generate an id for the null value
+        assertNotNull(vertex.id());
+    }
+
+    @Test
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
+    public void g_addV_propertyXlabel_personX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_addV_propertyXlabel_personX();
+        printTraversalForm(traversal);
+
+        final Vertex vertex = traversal.next();
+        assertEquals("person", vertex.label());
+    }
+
+    @Test
     @LoadGraphWith(MODERN)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
@@ -128,6 +161,15 @@
 
     @Test
     @LoadGraphWith(MODERN)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES, supported = false)
+    public void g_V_hasLabelXpersonX_propertyXname_nullX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasLabelXpersonX_propertyXname_nullX();
+        printTraversalForm(traversal);
+        traversal.forEachRemaining(v -> assertThat(v.properties("name").hasNext(), is(false)));
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
     public void g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenmX() {
@@ -315,6 +357,11 @@
         }
 
         @Override
+        public Traversal<Vertex, Vertex> get_g_V_hasLabelXpersonX_propertyXname_nullX() {
+            return g.V().hasLabel("person").property("name", null);
+        }
+
+        @Override
         public Traversal<Vertex, Vertex> get_g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenmX() {
             return g.addV("person").property(VertexProperty.Cardinality.single, "name", "stephen").property(VertexProperty.Cardinality.single, "name", "stephenm");
         }
@@ -363,5 +410,16 @@
         public Traversal<Vertex, Map<Object, Object>> get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX() {
             return g.V().as("a").has("name", "marko").out("created").as("b").addV(select("a").label()).property("test", select("b").label()).valueMap().with(WithOptions.tokens);
         }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_addVXnullX_propertyXid_nullX() {
+            // testing Traversal but should work the same for String
+            return g.addV((Traversal.Admin<?, String>) null).property(T.id, null);
+        }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_addV_propertyXlabel_personX() {
+            return g.addV().property(T.label, "person");
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantTest.java
index e35db43..07a7b55 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantTest.java
@@ -46,9 +46,10 @@
 
     public abstract Traversal<Vertex, Integer> get_g_V_constantX123X();
 
+    public abstract Traversal<Vertex, Void> get_g_V_constantXnullX();
+
     public abstract Traversal<Vertex, String> get_g_V_chooseXhasLabelXpersonX_valuesXnameX_constantXinhumanXX();
 
-    /** Scenario: Trivial use case from GraphTraversal */
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_constantX123X() {
@@ -56,6 +57,13 @@
         printTraversalForm(traversal);
         assertEquals(Arrays.asList(123, 123, 123, 123, 123, 123), traversal.toList());
     }
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_constantXnullX() {
+        final Traversal<Vertex, Void> traversal = get_g_V_constantXnullX();
+        printTraversalForm(traversal);
+        assertEquals(Arrays.asList(null, null, null, null, null, null), traversal.toList());
+    }
 
     /** Scenario: Anonymous traversal within choose */
     @Test
@@ -74,6 +82,11 @@
         }
 
         @Override
+        public Traversal<Vertex, Void> get_g_V_constantXnullX() {
+            return g.V().constant(null);
+        }
+
+        @Override
         public Traversal<Vertex, String> get_g_V_chooseXhasLabelXpersonX_valuesXnameX_constantXinhumanXX() {
             return g.V().choose(hasLabel("person"), values("name"), constant("inhuman"));
         }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapTest.java
index 9006fec..35faa03 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapTest.java
@@ -31,9 +31,11 @@
 import java.util.List;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.constant;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -53,6 +55,8 @@
 
     public abstract Traversal<Vertex, Vertex> get_g_V_mapXselectXaXX();
 
+    public abstract Traversal<Vertex, Vertex> get_g_V_mapXconstantXnullXX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_VX1X_mapXnameX() {
@@ -139,6 +143,19 @@
         assertEquals(6, counter);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_mapXconstantXnullXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_mapXconstantXnullXX();
+        printTraversalForm(traversal);
+        int counter = 0;
+        while (traversal.hasNext()) {
+            counter++;
+            assertNull(traversal.next());
+        }
+        assertEquals(6, counter);
+    }
+
     public static class Traversals extends MapTest {
         @Override
         public Traversal<Vertex, String> get_g_VX1X_mapXnameX(final Object v1Id) {
@@ -169,5 +186,10 @@
         public Traversal<Vertex, Vertex> get_g_V_mapXselectXaXX() {
             return g.V().as("a").map(select("a"));
         }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_mapXconstantXnullXX() {
+            return g.V().map(constant(null));
+        }
     }
 }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
index edca31d..674d1a1 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
@@ -29,6 +29,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
@@ -64,14 +65,10 @@
 
     public abstract Traversal<Vertex, String> get_g_V_name_order_byXa1_b1X_byXb2_a2X();
 
-    public abstract Traversal<Vertex, String> get_g_V_order_byXname_incrX_name();
-
     public abstract Traversal<Vertex, String> get_g_V_order_byXname_ascX_name();
 
     public abstract Traversal<Vertex, String> get_g_V_order_byXnameX_name();
 
-    public abstract Traversal<Vertex, Double> get_g_V_outE_order_byXweight_decrX_weight();
-
     public abstract Traversal<Vertex, Double> get_g_V_outE_order_byXweight_descX_weight();
 
     public abstract Traversal<Vertex, String> get_g_V_order_byXname_a1_b1X_byXname_b2_a2X_name();
@@ -110,6 +107,10 @@
 
     public abstract Traversal<Vertex, Map.Entry<Object, Object>> get_g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold(final Object v1Id);
 
+    public abstract Traversal<Vertex, Vertex> get_g_V_order_byXlabelX();
+
+    public abstract Traversal<Vertex, Vertex> get_g_V_order_byXlabel_descX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_name_order() {
@@ -128,14 +129,6 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_order_byXname_incrX_name() {
-        final Traversal<Vertex, String> traversal = get_g_V_order_byXname_incrX_name();
-        printTraversalForm(traversal);
-        checkOrderedResults(Arrays.asList("josh", "lop", "marko", "peter", "ripple", "vadas"), traversal);
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
     public void g_V_order_byXname_ascX_name() {
         final Traversal<Vertex, String> traversal = get_g_V_order_byXname_ascX_name();
         printTraversalForm(traversal);
@@ -152,14 +145,6 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_outE_order_byXweight_decrX_weight() {
-        final Traversal<Vertex, Double> traversal = get_g_V_outE_order_byXweight_decrX_weight();
-        printTraversalForm(traversal);
-        checkOrderedResults(Arrays.asList(1.0d, 1.0d, 0.5d, 0.4d, 0.4d, 0.2d), traversal);
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
     public void g_V_outE_order_byXweight_descX_weight() {
         final Traversal<Vertex, Double> traversal = get_g_V_outE_order_byXweight_descX_weight();
         printTraversalForm(traversal);
@@ -425,6 +410,22 @@
         assertEquals(1.9, entry.getValue().doubleValue(), 0.0001);
     }
 
+    public void g_V_order_byXlabelX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_order_byXlabelX();
+        printTraversalForm(traversal);
+        for (int i = 0; i < 4; i++) {
+            assertTrue(traversal.hasNext());
+            final Vertex v = traversal.next();
+            assertEquals("person", v.label());
+        }
+        for (int i = 0; i < 2; i++) {
+            assertTrue(traversal.hasNext());
+            final Vertex v = traversal.next();
+            assertEquals("software", v.label());
+        }
+        assertFalse(traversal.hasNext());
+    }
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_hasLabelXpersonX_group_byXnameX_byXoutE_weight_sumX_unfold_order_byXvalues_descX() {
@@ -448,6 +449,22 @@
         assertFalse(traversal.hasNext());
     }
 
+    public void g_V_order_byXlabel_descX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_order_byXlabel_descX();
+        printTraversalForm(traversal);
+        for (int i = 0; i < 2; i++) {
+            assertTrue(traversal.hasNext());
+            final Vertex v = traversal.next();
+            assertEquals("software", v.label());
+        }
+        for (int i = 0; i < 4; i++) {
+            assertTrue(traversal.hasNext());
+            final Vertex v = traversal.next();
+            assertEquals("person", v.label());
+        }
+        assertFalse(traversal.hasNext());
+    }
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold() {
@@ -489,11 +506,6 @@
         }
 
         @Override
-        public Traversal<Vertex, String> get_g_V_order_byXname_incrX_name() {
-            return g.V().order().by("name", Order.incr).values("name");
-        }
-
-        @Override
         public Traversal<Vertex, String> get_g_V_order_byXname_ascX_name() {
             return g.V().order().by("name", Order.asc).values("name");
         }
@@ -504,11 +516,6 @@
         }
 
         @Override
-        public Traversal<Vertex, Double> get_g_V_outE_order_byXweight_decrX_weight() {
-            return g.V().outE().order().by("weight", Order.decr).values("weight");
-        }
-
-        @Override
         public Traversal<Vertex, Double> get_g_V_outE_order_byXweight_descX_weight() {
             return g.V().outE().order().by("weight", desc).values("weight");
         }
@@ -611,5 +618,14 @@
         public Traversal<Vertex, Map.Entry<Object, Object>> get_g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold(final Object v1Id) {
             return g.V(v1Id).elementMap().order(Scope.local).by(keys, desc).unfold();
         }
+
+        public Traversal<Vertex, Vertex> get_g_V_order_byXlabelX() {
+            return g.V().order().by(__.label());
+        }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_order_byXlabel_descX() {
+            return g.V().order().by(__.label(), Order.desc);
+        }
     }
 }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
index 864ebb0..33ba805 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
@@ -51,24 +51,22 @@
 
     public abstract Traversal<Vertex, Vertex> get_g_V_pageRank_hasXpageRankX();
 
-    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankXwithXtimes_0X_valueMapXname_projectRankX();
 
     public abstract Traversal<Vertex, String> get_g_V_pageRank_order_byXpageRank_descX_byXnameX_name();
 
     public abstract Traversal<Vertex, String> get_g_V_pageRank_order_byXpageRank_descX_name_limitX2X();
 
-    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX();
+    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_withXedges_outEXknowsXX_withXpropertyName_friendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX();
 
-    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_hasLabelXpersonX_pageRank_byXpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX();
+    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_hasLabelXpersonX_pageRank_withXpropertyName_pageRankX_project_byXnameX_byXvaluesXpageRankX_mathX();
 
-    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX();
+    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_withXpropertyName_pageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX();
 
-    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_withXedges_inEXcreatedXX_withXtimes_1X_withXpropertyName_priorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
 
     public abstract Traversal<Vertex, Map<Object, List<Vertex>>> get_g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_withXpropertyName_pageRankXX_withXedges_inEXX_withXtimes_1X_inXcreatedX_groupXmX_byXpageRankX_capXmX();
 
-    public abstract Traversal<Vertex, Map<Object, List<Vertex>>> get_g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_byXpageRankX_byXinEX_timesX1X_inXcreatedX_groupXmX_byXpageRankX_capXmX();
-
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_pageRank_hasXpageRankX() {
@@ -79,8 +77,8 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_valueMapXname_projectRankX() {
-        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX();
+    public void g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankXwithXtimes_0X_valueMapXname_projectRankX() {
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankXwithXtimes_0X_valueMapXname_projectRankX();
         printTraversalForm(traversal);
         final List<Map<Object, List<Object>>> result = traversal.toList();
         assertEquals(4, result.size());
@@ -112,8 +110,8 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX() {
-        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX();
+    public void g_V_pageRank_withXedges_outEXknowsXX_withXpropertyName_friendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX() {
+        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_pageRank_withXedges_outEXknowsXX_withXpropertyName_friendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
@@ -144,8 +142,8 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasLabelXpersonX_pageRank_byXpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX() {
-        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_hasLabelXpersonX_pageRank_byXpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX();
+    public void g_V_hasLabelXpersonX_pageRank_withXpropertyName_pageRankX_project_byXnameX_byXvaluesXpageRankX_mathX() {
+        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_hasLabelXpersonX_pageRank_withXpropertyName_pageRankX_project_byXnameX_byXvaluesXpageRankX_mathX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
@@ -165,8 +163,8 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX() {
-        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX();
+    public void g_V_pageRank_withXpropertyName_pageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX() {
+        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_pageRank_withXpropertyName_pageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
@@ -183,8 +181,8 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
-        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
+    public void g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_withXedges_inEXcreatedXX_withXtimes_1X_withXpropertyName_priorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_withXedges_inEXcreatedXX_withXtimes_1X_withXpropertyName_priorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
@@ -202,39 +200,6 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_byXpageRankX_byXinEX_timesX1X_inXcreatedX_groupXmX_byXpageRankX_capXmX() {
-        // [{2.0=[v[4], v[4], v[4], v[4]], 1.0=[v[6], v[6], v[6], v[1], v[1], v[1]], software=[v[5], v[3], v[3], v[3]]}]
-        final Traversal<Vertex, Map<Object, List<Vertex>>> traversal = get_g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_byXpageRankX_byXinEX_timesX1X_inXcreatedX_groupXmX_byXpageRankX_capXmX();
-        printTraversalForm(traversal);
-        final Map<Object, List<Vertex>> map = traversal.next();
-        assertFalse(traversal.hasNext());
-        assertEquals(3, map.size());
-        assertTrue(map.containsKey("software"));
-        map.forEach((k, v) -> {
-            boolean found = false;
-            if (!k.equals("software") && v.size() == 4) {
-                assertEquals(2.0d, ((Number) k).doubleValue(), 0.01d);
-                assertEquals(4, v.stream().filter(vertex -> vertex.id().equals(convertToVertexId(graph, "josh"))).count());
-                found = true;
-            } else if (v.size() == 6) {
-                assertEquals(1.0d, ((Number) k).doubleValue(), 0.01d);
-                assertEquals(3, v.stream().filter(vertex -> vertex.id().equals(convertToVertexId(graph, "peter"))).count());
-                assertEquals(3, v.stream().filter(vertex -> vertex.id().equals(convertToVertexId(graph, "marko"))).count());
-                found = true;
-            } else if (v.size() == 4) {
-                assertEquals("software", k);
-                assertEquals(3, v.stream().filter(vertex -> vertex.id().equals(convertToVertexId(graph, "lop"))).count());
-                assertEquals(1, v.stream().filter(vertex -> vertex.id().equals(convertToVertexId(graph, "ripple"))).count());
-                found = true;
-            }
-
-            if (!found)
-                fail("There are too many key/values: " + k + "--" + v);
-        });
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
     public void g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_withXPROPERTY_NAME_pageRankXX_withXEDGES_inEXX_withXTIMES_1X_inXcreatedX_groupXmX_byXpageRankX_capXmX() {
         // [{2.0=[v[4], v[4], v[4], v[4]], 1.0=[v[6], v[6], v[6], v[1], v[1], v[1]], software=[v[5], v[3], v[3], v[3]]}]
         final Traversal<Vertex, Map<Object, List<Vertex>>> traversal = get_g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_withXpropertyName_pageRankXX_withXedges_inEXX_withXtimes_1X_inXcreatedX_groupXmX_byXpageRankX_capXmX();
@@ -274,13 +239,13 @@
         }
 
         @Override
-        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX() {
-            return g.V().out("created").pageRank().by(__.bothE()).by("projectRank").times(0).valueMap("name", "projectRank");
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankXwithXtimes_0X_valueMapXname_projectRankX() {
+            return g.V().out("created").pageRank().with(PageRank.edges, __.bothE()).with(PageRank.propertyName, "projectRank").with(PageRank.times, 0).valueMap("name", "projectRank");
         }
 
         @Override
-        public Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX() {
-            return g.V().pageRank().by(__.outE("knows")).by("friendRank").project("name", "friendRank").by("name").by(__.values("friendRank").math("ceil(_ * 100)"));
+        public Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_withXedges_outEXknowsXX_withXpropertyName_friendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX() {
+            return g.V().pageRank().with(PageRank.edges, __.outE("knows")).with(PageRank.propertyName, "friendRank").project("name", "friendRank").by("name").by(__.values("friendRank").math("ceil(_ * 100)"));
         }
 
         @Override
@@ -294,23 +259,18 @@
         }
 
         @Override
-        public Traversal<Vertex, Map<String, Object>> get_g_V_hasLabelXpersonX_pageRank_byXpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX() {
-            return g.V().hasLabel("person").pageRank().by("pageRank").project("name", "pageRank").by("name").by(__.values("pageRank").math("ceil(_ * 100)"));
+        public Traversal<Vertex, Map<String, Object>> get_g_V_hasLabelXpersonX_pageRank_withXpropertyName_pageRankX_project_byXnameX_byXvaluesXpageRankX_mathX() {
+            return g.V().hasLabel("person").pageRank().with(PageRank.propertyName, "pageRank").project("name", "pageRank").by("name").by(__.values("pageRank").math("ceil(_ * 100)"));
         }
 
         @Override
-        public Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX() {
-            return g.V().pageRank().by("pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").by().by(__.math("ceil(_ * 100)"));
+        public Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_withXpropertyName_pageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX() {
+            return g.V().pageRank().with(PageRank.propertyName, "pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").by().by(__.math("ceil(_ * 100)"));
         }
 
         @Override
-        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
-            return g.V().hasLabel("software").has("name", "ripple").pageRank(1.0).by(__.inE("created")).times(1).by("priors").in("created").union(__.both(), __.identity()).valueMap("name", "priors");
-        }
-
-        @Override
-        public Traversal<Vertex, Map<Object, List<Vertex>>> get_g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_byXpageRankX_byXinEX_timesX1X_inXcreatedX_groupXmX_byXpageRankX_capXmX() {
-            return g.V().out("created").group("m").by(T.label).pageRank(1.0).by("pageRank").by(__.inE()).times(1).in("created").group("m").by("pageRank").cap("m");
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_withXedges_inEXcreatedXX_withXtimes_1X_withXpropertyName_priorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
+            return g.V().hasLabel("software").has("name", "ripple").pageRank(1.0).with(PageRank.edges, __.inE("created")).with(PageRank.times, 1).with(PageRank.propertyName, "priors").in("created").union(__.both(), __.identity()).valueMap("name", "priors");
         }
 
         @Override
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java
index 5087522..e834ecf 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java
@@ -24,6 +24,7 @@
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.PeerPressureVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressure;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
@@ -51,9 +52,7 @@
 
     public abstract Traversal<Vertex, Vertex> get_g_V_peerPressure_hasXclusterX();
 
-    public abstract Traversal<Vertex, Map<Object, Number>> get_g_V_peerPressure_byXclusterX_byXoutEXknowsXX_pageRankX1X_byXrankX_byXoutEXknowsXX_timesX2X_group_byXclusterX_byXrank_sumX_limitX100X();
-
-    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
+    public abstract Traversal<Vertex, Map<Object, Number>> get_g_V_peerPressure_withXpropertyName_clusterX_withXedges_outEXknowsXX_pageRankX1X_withXpropertyName_rankX_withXedges_outEXknowsXX_withXtimes_2X_group_byXclusterX_byXrank_sumX_limitX100X();
 
     public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
 
@@ -67,8 +66,8 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_peerPressure_byXclusterX_byXoutEXknowsXX_pageRankX1X_byXrankX_byXoutEXknowsXX_timesX2X_group_byXclusterX_byXrank_sumX() {
-        final Traversal<Vertex, Map<Object, Number>> traversal = get_g_V_peerPressure_byXclusterX_byXoutEXknowsXX_pageRankX1X_byXrankX_byXoutEXknowsXX_timesX2X_group_byXclusterX_byXrank_sumX_limitX100X();
+    public void g_V_peerPressure_withXpropertyName_clusterX_withXedges_outEXknowsXX_pageRankX1X_withXpropertyName_rankX_withXedges_outEXknowsXX_withXtimes_2X_group_byXclusterX_byXrank_sumX_limitX100X() {
+        final Traversal<Vertex, Map<Object, Number>> traversal = get_g_V_peerPressure_withXpropertyName_clusterX_withXedges_outEXknowsXX_pageRankX1X_withXpropertyName_rankX_withXedges_outEXknowsXX_withXtimes_2X_group_byXclusterX_byXrank_sumX_limitX100X();
         printTraversalForm(traversal);
         final Map<Object, Number> map = traversal.next();
         assertFalse(traversal.hasNext());
@@ -81,29 +80,7 @@
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
-        TestHelper.assumeNonDeterministic();
-        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
-        printTraversalForm(traversal);
-        final List<Map<Object, List<Object>>> results = traversal.toList();
-        assertEquals(6, results.size());
-        final Map<String, Object> clusters = new HashMap<>();
-        results.forEach(m -> clusters.put((String) m.get("name").get(0), m.get("cluster").get(0)));
-        assertEquals(2, results.get(0).size());
-        assertEquals(6, clusters.size());
-        assertEquals(clusters.get("josh"), clusters.get("ripple"));
-        assertEquals(clusters.get("josh"), clusters.get("lop"));
-        final Set<Object> ids = new HashSet<>(clusters.values());
-        assertEquals(4, ids.size());
-        assertTrue(ids.contains(convertToVertexId("marko")));
-        assertTrue(ids.contains(convertToVertexId("vadas")));
-        assertTrue(ids.contains(convertToVertexId("josh")));
-        assertTrue(ids.contains(convertToVertexId("peter")));
-    }
-
-    @Test
-    @LoadGraphWith(MODERN)
-    public void g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXEDGES_outEX_withXPROPERTY_NAME_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
+    public void g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
         TestHelper.assumeNonDeterministic();
         final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
         printTraversalForm(traversal);
@@ -131,13 +108,8 @@
         }
 
         @Override
-        public Traversal<Vertex, Map<Object, Number>> get_g_V_peerPressure_byXclusterX_byXoutEXknowsXX_pageRankX1X_byXrankX_byXoutEXknowsXX_timesX2X_group_byXclusterX_byXrank_sumX_limitX100X() {
-            return g.V().peerPressure().by("cluster").by(__.outE("knows")).pageRank(1.0d).by("rank").by(__.outE("knows")).times(1).<Object, Number>group().by("cluster").by(__.values("rank").sum()).limit(100);
-        }
-
-        @Override
-        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
-            return g.V().has("name", "ripple").in("created").peerPressure().by(__.outE()).by("cluster").repeat(__.union(__.identity(), __.both())).times(2).dedup().valueMap("name", "cluster");
+        public Traversal<Vertex, Map<Object, Number>> get_g_V_peerPressure_withXpropertyName_clusterX_withXedges_outEXknowsXX_pageRankX1X_withXpropertyName_rankX_withXedges_outEXknowsXX_withXtimes_2X_group_byXclusterX_byXrank_sumX_limitX100X() {
+            return g.V().peerPressure().with(PeerPressure.propertyName, "cluster").with(PeerPressure.edges, __.outE("knows")).pageRank(1.0d).with(PageRank.propertyName, "rank").with(PageRank.edges, __.outE("knows")).with(PageRank.times, 1).<Object, Number>group().by("cluster").by(__.values("rank").sum()).limit(100);
         }
 
         @Override
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
index b7985e6..9747fc0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
@@ -23,6 +23,7 @@
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.IgnoreEngine;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.TraversalVertexProgramStep;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
@@ -92,7 +93,7 @@
 
     public abstract Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_b__b_in_count_isXeqX1XXX_selectXa_bX_profileXmetricsX();
 
-    public abstract Traversal<Vertex, TraversalMetrics> get_g_V_hasLabelXpersonX_pageRank_byXrankX_byXbothEX_rank_profile();
+    public abstract Traversal<Vertex, TraversalMetrics> get_g_V_hasLabelXpersonX_pageRank_withXpropertyName_rankX_withXedges_bothEX_rank_profile();
 
     public abstract Traversal<Vertex, TraversalMetrics> get_g_V_groupXmX_profile();
 
@@ -265,8 +266,8 @@
 
         final TraversalMetrics traversalMetrics = traversal.next();
         validate_g_V_repeat_both_modern_profile(traversalMetrics,
-                traversal.asAdmin().getStrategies().toList().contains(RepeatUnrollStrategy.instance()) &&
-                        !traversal.asAdmin().getStrategies().toList().contains(ComputerVerificationStrategy.instance()));
+                traversal.asAdmin().getStrategies().getStrategy(RepeatUnrollStrategy.class).isPresent() &&
+                        !traversal.asAdmin().getStrategies().getStrategy(ComputerVerificationStrategy.class).isPresent());
     }
 
     @Test
@@ -277,8 +278,8 @@
         traversal.iterate();
         final TraversalMetrics traversalMetrics = traversal.asAdmin().getSideEffects().get(METRICS_KEY);
         validate_g_V_repeat_both_modern_profile(traversalMetrics,
-                traversal.asAdmin().getStrategies().toList().contains(RepeatUnrollStrategy.instance()) &&
-                        !traversal.asAdmin().getStrategies().toList().contains(ComputerVerificationStrategy.instance()));
+                traversal.asAdmin().getStrategies().getStrategy(RepeatUnrollStrategy.class).isPresent() &&
+                        !traversal.asAdmin().getStrategies().getStrategy(ComputerVerificationStrategy.class).isPresent());
     }
 
     private void validate_g_V_repeat_both_modern_profile(final TraversalMetrics traversalMetrics, final boolean withRepeatUnrollStrategy) {
@@ -333,7 +334,7 @@
         assertEquals(1, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertEquals(1, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
 
-        if (traversal.asAdmin().getStrategies().toList().stream().anyMatch(s -> s instanceof CountStrategy)) {
+        if (traversal.asAdmin().getStrategies().getStrategy(CountStrategy.class).isPresent()) {
             assertEquals("Metrics 1 should have 4 nested metrics.", 4, metrics.getNested().size());
         } else {
             assertEquals("Metrics 1 should have 3 nested metrics.", 3, metrics.getNested().size());
@@ -435,8 +436,8 @@
     @Test
     @LoadGraphWith(MODERN)
     @IgnoreEngine(TraversalEngine.Type.STANDARD)
-    public void g_V_hasLabelXpersonX_pageRank_byXrankX_byXbothEX_rank_profile() {
-        final Traversal<Vertex, TraversalMetrics> traversal = get_g_V_hasLabelXpersonX_pageRank_byXrankX_byXbothEX_rank_profile();
+    public void g_V_hasLabelXpersonX_pageRank_withXpropertyName_rankX_withXedges_bothEX_rank_profile() {
+        final Traversal<Vertex, TraversalMetrics> traversal = get_g_V_hasLabelXpersonX_pageRank_withXpropertyName_rankX_withXedges_bothEX_rank_profile();
         //printTraversalForm(traversal);
         try {
             traversal.iterate();
@@ -539,8 +540,8 @@
         }
 
         @Override
-        public Traversal<Vertex, TraversalMetrics> get_g_V_hasLabelXpersonX_pageRank_byXrankX_byXbothEX_rank_profile() {
-            return g.V().hasLabel("person").pageRank().by("rank").by(__.bothE()).values("rank").profile();
+        public Traversal<Vertex, TraversalMetrics> get_g_V_hasLabelXpersonX_pageRank_withXpropertyName_rankX_withXedges_bothEX_rank_profile() {
+            return g.V().hasLabel("person").pageRank().with(PageRank.propertyName, "rank").with(PageRank.edges, __.bothE()).values("rank").profile();
         }
 
         @Override
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java
index a0c5b23..1439a7b 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
index 470513c..cd274d0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
@@ -26,6 +26,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -155,6 +156,10 @@
 
     public abstract Traversal<Vertex, Vertex> get_g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXlast_aX(final Object v1Id);
 
+    public abstract Traversal<Edge, Object> get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX(final Object e11Id);
+
+    public abstract Traversal<Edge, Object> get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX(final Object e11Id);
+
     // when labels don't exist
 
     public abstract Traversal<Vertex, String> get_g_V_untilXout_outX_repeatXin_asXaXX_selectXaX_byXtailXlocalX_nameX();
@@ -713,6 +718,22 @@
         assertEquals(Collections.emptyList(), traversal.toList());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX() {
+        final Traversal<Edge, Object> traversal = get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX(convertToEdgeId("josh", "created", "lop"));
+        printTraversalForm(traversal);
+        assertEquals("weight", traversal.next());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX() {
+        final Traversal<Edge, Object> traversal = get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX(convertToEdgeId("josh", "created", "lop"));
+        printTraversalForm(traversal);
+        assertEquals(0.4d, (double) traversal.next(), 0.0001d);
+    }
+
     // when labels don't exist
 
     @Test
@@ -1112,6 +1133,16 @@
             return g.V().as("a").where(__.out("knows")).<Vertex>select("a");
         }
 
+        @Override
+        public Traversal<Edge, Object> get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX(final Object e11Id) {
+            return g.E(e11Id).properties("weight").as("a").select("a").by(T.key);
+        }
+
+        @Override
+        public Traversal<Edge, Object> get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX(final Object e11Id) {
+            return g.E(e11Id).properties("weight").as("a").select("a").by(T.value);
+        }
+
         // select columns test
 
         @Override
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
index 5b0cf32..c7f86d7 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
@@ -59,6 +59,8 @@
 
     public abstract Traversal<Vertex, Map<String, Collection<Vertex>>> get_g_V_group_byXnameX();
 
+    public abstract Traversal<Vertex, Map<Integer, Collection<Vertex>>> get_g_V_group_byXageX();
+
     public abstract Traversal<Vertex, Map<String, Collection<Vertex>>> get_g_V_group_byXnameX_by();
 
     public abstract Traversal<Vertex, Map<String, Collection<Vertex>>> get_g_V_groupXaX_byXnameX_capXaX();
@@ -101,6 +103,10 @@
 
     public abstract Traversal<Vertex, Map<String, Number>> get_g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX();
 
+    public abstract Traversal<Vertex, Map<String, Long>> get_g_V_group_byXlabelX_byXlabel_countX();
+
+    public abstract Traversal<Vertex, Map<String, Long>> get_g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_group_byXnameX() {
@@ -110,6 +116,24 @@
         checkSideEffects(traversal.asAdmin().getSideEffects());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_group_byXageX() {
+        final Traversal<Vertex, Map<Integer, Collection<Vertex>>> traversal = get_g_V_group_byXageX();
+        printTraversalForm(traversal);
+
+        final Map<Integer, Collection<Vertex>> map = traversal.next();
+        assertEquals(5, map.size());
+        map.forEach((key, values) -> {
+            if (null == key)
+                assertEquals(2, values.size());
+            else
+                assertEquals(1, values.size());
+        });
+        assertFalse(traversal.hasNext());
+
+        checkSideEffects(traversal.asAdmin().getSideEffects());
+    }
 
     @Test
     @LoadGraphWith(MODERN)
@@ -129,7 +153,7 @@
         checkSideEffects(traversal.asAdmin().getSideEffects(), "a", HashMap.class);
     }
 
-    private void assertCommonA(Traversal<Vertex, Map<String, Collection<Vertex>>> traversal) {
+    private void assertCommonA(final Traversal<Vertex, Map<String, Collection<Vertex>>> traversal) {
         final Map<String, Collection<Vertex>> map = traversal.next();
         assertEquals(6, map.size());
         map.forEach((key, values) -> {
@@ -499,6 +523,32 @@
         assertFalse(traversal.hasNext());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_group_byXlabelX_byXlabel_countX() {
+        final Traversal<Vertex, Map<String, Long>> traversal = get_g_V_group_byXlabelX_byXlabel_countX();
+        printTraversalForm(traversal);
+        final Map<String, Long> map = traversal.next();
+        assertEquals(2, map.size());
+        assertTrue(map.containsKey("person"));
+        assertTrue(map.containsKey("software"));
+        assertEquals(4L, map.get("person").longValue());
+        assertEquals(2L, map.get("software").longValue());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX() {
+        final Traversal<Vertex, Map<String, Long>> traversal = get_g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX();
+        printTraversalForm(traversal);
+        final Map<String, Long> map = traversal.next();
+        assertEquals(2, map.size());
+        assertTrue(map.containsKey("person"));
+        assertTrue(map.containsKey("software"));
+        assertEquals(4L, map.get("person").longValue());
+        assertEquals(2L, map.get("software").longValue());
+    }
+
     public static class Traversals extends GroupTest {
 
         @Override
@@ -507,6 +557,11 @@
         }
 
         @Override
+        public Traversal<Vertex, Map<Integer, Collection<Vertex>>> get_g_V_group_byXageX() {
+            return g.V().<Integer, Collection<Vertex>>group().by("age");
+        }
+
+        @Override
         public Traversal<Vertex, Map<String, Collection<Vertex>>> get_g_V_group_byXnameX_by() {
             return g.V().<String, Collection<Vertex>>group().by("name").by();
         }
@@ -610,5 +665,15 @@
         public Traversal<Vertex, Map<String, Number>> get_g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX() {
             return g.V().hasLabel("person").as("p").out("created").<String, Number>group().by("name").by(__.select("p").values("age").sum());
         }
+
+        @Override
+        public Traversal<Vertex, Map<String, Long>> get_g_V_group_byXlabelX_byXlabel_countX() {
+            return g.V().<String, Long>group().by(__.label()).by(__.label().count());
+        }
+
+        @Override
+        public Traversal<Vertex, Map<String, Long>> get_g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX() {
+            return g.V().group("m").by(__.label()).by(__.label().count()).cap("m");
+        }
     }
 }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectTest.java
index d3fc1ed..fd752d2 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectTest.java
@@ -23,6 +23,7 @@
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
@@ -48,6 +49,12 @@
 
     public abstract Traversal<Vertex, String> get_g_VX1X_injectXg_VX4XX_out_name(final Object v1Id, final Object v4Id);
 
+    public abstract Traversal<Integer, Integer> get_g_injectXnull_1_3_nullX();
+
+    public abstract Traversal<Integer, Map<String, Object>> get_g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX();
+
+    public abstract Traversal<Map<String,Object>, Map<String, Object>> get_g_injectXname_marko_age_nullX_selectXname_ageX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_VX1X_out_injectXv2X_name() {
@@ -85,6 +92,30 @@
     }
 
     @Test
+    public void g_injectXnull_1_3_nullX() {
+        final Traversal<Integer, Integer> traversal = get_g_injectXnull_1_3_nullX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(null, 1, 3, null), traversal);
+    }
+
+    @Test
+    public void g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX() {
+        final Traversal<Integer, Map<String, Object>> traversal = get_g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX();
+        printTraversalForm(traversal);
+        checkResults(makeMapList(2,
+                "a", 10, "b", 3L,
+                    "a", 20, "b", 2L,
+                    "a", null, "b", 1L), traversal);
+    }
+
+    @Test
+    public void g_injectXname_marko_age_nullX_selectXname_ageX() {
+        final Traversal<Map<String, Object>, Map<String, Object>> traversal = get_g_injectXname_marko_age_nullX_selectXname_ageX();
+        printTraversalForm(traversal);
+        checkResults(makeMapList(2, "name", "marko", "age", null), traversal);
+    }
+
+    @Test
     @LoadGraphWith(MODERN)
     public void g_VX1X_injectXg_VX4XX_out_name() {
         final Traversal<Vertex, String> traversal = get_g_VX1X_injectXg_VX4XX_out_name(convertToVertexId("marko"), convertToVertexId("josh"));
@@ -108,5 +139,27 @@
         public Traversal<Vertex, String> get_g_VX1X_injectXg_VX4XX_out_name(final Object v1Id, final Object v4Id) {
             return g.V(v1Id).inject(g.V(v4Id).next()).out().values("name");
         }
+
+        @Override
+        public Traversal<Integer, Integer> get_g_injectXnull_1_3_nullX() {
+            return g.inject(null, 1, 3, null);
+        }
+
+        @Override
+        public Traversal<Integer, Map<String, Object>> get_g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX() {
+            return g.inject(10,20,null,20,10,10).groupCount("x").
+                     dedup().as("y").
+                     project("a","b").
+                       by().
+                       by(__.select("x").select(__.select("y")));
+        }
+
+        @Override
+        public Traversal<Map<String, Object>, Map<String, Object>> get_g_injectXname_marko_age_nullX_selectXname_ageX() {
+            final Map<String,Object> m = new HashMap<>();
+            m.put("name", "marko");
+            m.put("age", null);
+            return g.inject(m).select("name","age");
+        }
     }
 }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SubgraphTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SubgraphTest.java
index 51d8870..9f14d15 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SubgraphTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SubgraphTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java
index f552022..c0af2d9 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SeedStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SeedStrategyProcessTest.java
new file mode 100644
index 0000000..0f0c069
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SeedStrategyProcessTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.strategy.decoration;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.GRATEFUL;
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.apache.tinkerpop.gremlin.process.traversal.Order.shuffle;
+import static org.apache.tinkerpop.gremlin.process.traversal.Scope.local;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(GremlinProcessRunner.class)
+public class SeedStrategyProcessTest extends AbstractGremlinProcessTest {
+    private static final SeedStrategy seedStrategy = new SeedStrategy(1235L);
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void shouldSeedCoin() {
+        final GraphTraversalSource gSeeded = create();
+        final List<Object> names = gSeeded.V().order().by("name").values("name").coin(0.31).order().toList();
+        repeatAssert(() -> {
+            assertEquals(names, gSeeded.V().order().by("name").values("name").coin(0.31).order().toList());
+            return null;
+        });
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void shouldSeedGlobalOrderShuffle() {
+        final GraphTraversalSource gSeeded = create();
+        final List<Object> names = gSeeded.V().order().by("name").values("name").order().by(shuffle).toList();
+        repeatAssert(() -> {
+            assertEquals(names, gSeeded.V().order().by("name").values("name").order().by(shuffle).toList());
+            return null;
+        });
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void shouldSeedLocalOrderShuffle() {
+        final GraphTraversalSource gSeeded = create();
+        final List<Object> names = gSeeded.V().order().by("name").values("name").fold().order(local).by(shuffle).next();
+        repeatAssert(() -> {
+            assertEquals(names, gSeeded.V().order().by("name").values("name").fold().order(local).by(shuffle).next());
+            return null;
+        });
+    }
+
+    @Test
+    @LoadGraphWith(GRATEFUL)
+    public void shouldSeedGlobalSample() {
+        final GraphTraversalSource gSeeded = create();
+        final List<Object> names = gSeeded.V().order().by("name").values("name").sample(20).toList();
+        repeatAssert(() -> {
+            assertEquals(names, gSeeded.V().order().by("name").values("name").sample(20).toList());
+            return null;
+        });
+    }
+
+    @Test
+    @LoadGraphWith(GRATEFUL)
+    public void shouldSeedLocalSample() {
+        final GraphTraversalSource gSeeded = create();
+        final List<Object> names = gSeeded.V().order().by("name").values("name").fold().sample(local,20).next();
+        repeatAssert(() -> {
+            assertEquals(names, gSeeded.V().order().by("name").values("name").fold().sample(local,20).next());
+            return null;
+        });
+    }
+
+    private void repeatAssert(final Supplier<Void> assertion) {
+        for (int ix = 0; ix < 128; ix++) {
+            assertion.get();
+        }
+    }
+
+    private GraphTraversalSource create() {
+        return g.withStrategies(seedStrategy);
+    }
+}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java
index cf1c790..7bb4fa9 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java
index fcecf9e..5f3458e 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java
@@ -60,6 +60,7 @@
             PartitionStrategy.class,
             RequirementsStrategy.class,
             SackStrategy.class,
+            SeedStrategy.class,
             SideEffectStrategy.class,
             SubgraphStrategy.class,
             RemoteStrategy.class,
@@ -73,7 +74,7 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!(traversal.getParent() instanceof EmptyStep))
+        if (!(traversal.isRoot()) || traversal.getBytecode().isEmpty())
             return;
 
         final Traversal.Admin<?, ?> translatedTraversal;
@@ -134,7 +135,9 @@
             final Object[] newArgs = new Object[args.length];
 
             for (int i = 0; i < args.length; i++) {
-                if (args[i].equals("knows"))
+                if (args[i] == null)
+                    newArgs[i] = null;
+                else if (args[i].equals("knows"))
                     newArgs[i] = new Bytecode.Binding<>("a", "knows");
                 else if (args[i].equals("created"))
                     newArgs[i] = new Bytecode.Binding<>("b", "created");
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/EarlyLimitStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/EarlyLimitStrategyProcessTest.java
index 8a640e2..33d18c1 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/EarlyLimitStrategyProcessTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/EarlyLimitStrategyProcessTest.java
@@ -90,7 +90,7 @@
         assumeTrue("The following assertions apply to TinkerGraph only as provider strategies can alter the " +
                         "steps to not comply with expectations", graph.getClass().getSimpleName().equals("TinkerGraph"));
 
-        if (t.asAdmin().getStrategies().toList().stream().anyMatch(s -> s instanceof EarlyLimitStrategy)) {
+        if (t.asAdmin().getStrategies().getStrategy(EarlyLimitStrategy.class).isPresent()) {
             assertEquals(10, metrics.getMetrics().size());
             assertTrue(metrics.getMetrics(5).getName().endsWith("@[d]"));
             assertEquals("RangeGlobalStep(0,1)", metrics.getMetrics(6).getName());
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
new file mode 100644
index 0000000..aaa5e00
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
@@ -0,0 +1,183 @@
+/*
+ * 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.server;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbClient;
+import org.apache.kerby.kerberos.kerb.client.KrbConfig;
+import org.apache.kerby.kerberos.kerb.client.KrbConfigKey;
+import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.net.Inet4Address;
+
+
+/**
+ * This class is derived from the following classes from https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0-RC2:
+ *  - org.apache.kerby.kerberos.kerb.server.TestKdcServer
+ *  - org.apache.kerby.kerberos.kerb.server.KdcTestBase
+ *  - org.apache.kerby.kerberos.kerb.server.LoginTestBase
+ *
+ * See also: gremlin-server/src/main/static/NOTICE
+ *
+ * @author Marc de Lignie
+ */
+public class KdcFixture {
+
+    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KdcFixture.class);
+
+    final String clientPassword = "123456";
+    final String clientPassword2 = "1234562";
+    final String userPassword = "password";
+    final String clientPrincipalName = "drankye";
+    final String clientPrincipalName2 = "drankye2";
+    final String userPrincipalName = "stephen";
+    final String serverPrincipalName = "test-service";
+    final String ticketCacheFileName = "test-tkt.cc";
+    final String ticketCacheFileName2 = "test-tkt2.cc";
+    final String serviceKeytabFileName = "test-service.keytab";
+
+    final String clientPrincipal;
+    final String clientPrincipal2;
+    final String serverPrincipal;
+    final String userPrincipal;
+    final File testDir;
+    final File ticketCacheFile;
+    final File ticketCacheFile2;
+    final File serviceKeytabFile;
+
+    final String gremlinHostname;
+    final String kdcHostname;
+    private SimpleKdcServer kdcServer;
+
+    public KdcFixture(final String moduleBaseDir) {
+        this(moduleBaseDir, "localhost");
+    }
+
+    public KdcFixture(final String moduleBaseDir, final String kdcHostName) {
+        this.kdcHostname = kdcHostName;
+        gremlinHostname = findHostname();
+        serverPrincipal = serverPrincipalName + "/" + gremlinHostname + "@" + KdcFixture.TestKdcServer.KDC_REALM;
+        clientPrincipal = clientPrincipalName + "@" + KdcFixture.TestKdcServer.KDC_REALM;
+        clientPrincipal2 = clientPrincipalName2 + "@" + KdcFixture.TestKdcServer.KDC_REALM;
+        userPrincipal = userPrincipalName  + "@" + KdcFixture.TestKdcServer.KDC_REALM;
+
+        final File targetDir = new File(moduleBaseDir, "target");
+        testDir = new File(targetDir, "kdc");
+        testDir.mkdirs();
+        ticketCacheFile = new File(testDir, ticketCacheFileName);
+        ticketCacheFile2 = new File(testDir, ticketCacheFileName2);
+        serviceKeytabFile = new File(testDir, serviceKeytabFileName);
+    }
+
+    private String findHostname() {
+        // Hostname setting must be consistent with the way gremlin-console sets gremlin-server's hostname
+        // and derives gremlin-server's principal name. Also, the hostname needs to be lowercase for use
+        // in principal names.
+        String hostname = "";
+        try {
+            hostname = Inet4Address.getLocalHost().getCanonicalHostName().toLowerCase();
+        } catch (Exception e) {
+            logger.error("Hostname not found: " + e.getMessage());
+        }
+        return hostname;
+    }
+
+    private class TestKdcServer extends SimpleKdcServer {
+        public static final String KDC_REALM = "TEST.COM";
+        public final String HOSTNAME = kdcHostname;
+        public static final int KDC_PORT = 4588;
+
+        TestKdcServer() throws KrbException {
+            setKdcRealm(KDC_REALM);
+            setKdcHost(HOSTNAME);
+            setAllowTcp(true);
+            setAllowUdp(true);
+            setKdcTcpPort(KDC_PORT);
+            setKdcUdpPort(KDC_PORT);
+
+            final KrbClient krbClnt = getKrbClient();
+            final KrbConfig krbConfig = krbClnt.getKrbConfig();
+            krbConfig.setString(KrbConfigKey.PERMITTED_ENCTYPES,
+                    "aes128-cts-hmac-sha1-96 des-cbc-crc des-cbc-md5 des3-cbc-sha1");
+            krbConfig.setString(KrbConfigKey.DEFAULT_REALM, KDC_REALM);
+            krbClnt.setTimeout(10 * 1000);
+        }
+    }
+
+    public void setUp() throws Exception {
+        setUpKdcServer();
+        setUpPrincipals();
+    }
+
+    private void setUpKdcServer() throws Exception {
+        kdcServer = new TestKdcServer();
+        kdcServer.setWorkDir(testDir);
+        kdcServer.init();
+        kdcServer.start();
+    }
+
+    private void setUpPrincipals() throws KrbException {
+        kdcServer.createPrincipals(serverPrincipal);
+        kdcServer.exportPrincipal(serverPrincipal, serviceKeytabFile);
+
+        kdcServer.createPrincipal(clientPrincipal, clientPassword);
+        final TgtTicket tgt = kdcServer.getKrbClient().requestTgt(clientPrincipal, clientPassword);
+        kdcServer.getKrbClient().storeTicket(tgt, ticketCacheFile);
+
+        kdcServer.createPrincipal(clientPrincipal2, clientPassword2);
+        final TgtTicket tgt2 = kdcServer.getKrbClient().requestTgt(clientPrincipal2, clientPassword2);
+        kdcServer.getKrbClient().storeTicket(tgt2, ticketCacheFile2);
+
+        kdcServer.createPrincipal(userPrincipal, userPassword);
+    }
+
+    public void close() throws Exception {
+        deletePrincipals();
+        kdcServer.stop();
+        ticketCacheFile.delete();
+        ticketCacheFile2.delete();
+        serviceKeytabFile.delete();
+        testDir.delete();
+    }
+
+    private void deletePrincipals() throws KrbException {
+        kdcServer.getKadmin().deleteBuiltinPrincipals();
+        kdcServer.deletePrincipals(serverPrincipal);
+        kdcServer.deletePrincipal(clientPrincipal);
+        kdcServer.deletePrincipal(clientPrincipal2);
+    }
+
+    public void createPrincipal(final String principal) throws KrbException {
+        kdcServer.createPrincipal(principal);
+    }
+
+    public static void main(final String[] args) throws Exception{
+        final String projectBaseDir = args[0];
+        // The KDC in docker/gremlin-server.sh needs to be exposed to both the container and the host
+        final KdcFixture kdcFixture = new KdcFixture(projectBaseDir, "0.0.0.0");
+        kdcFixture.setUp();
+        logger.info("KDC started with configuration {}/target/kdc/krb5.conf", projectBaseDir);
+        while (true) {
+            Thread.sleep(1000);
+        }
+    }
+}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphConstructionTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphConstructionTest.java
index 8b3e046..576126a 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphConstructionTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphConstructionTest.java
@@ -20,7 +20,7 @@
 
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.junit.Test;
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
index 8b443fc..099b3a3 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
@@ -40,7 +40,9 @@
 
 import static org.apache.tinkerpop.gremlin.structure.Graph.Features.PropertyFeatures.FEATURE_PROPERTIES;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeThat;
 
@@ -141,6 +143,62 @@
                 fail("Removing an edge property that was already removed should not throw an exception");
             }
         }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES, supported = false)
+        public void shouldNotAllowNullAddVertex() throws Exception {
+            final Vertex v = this.graph.addVertex("name", null);
+            assertThat(v.properties("name").hasNext(), is(false));
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES, supported = false)
+        public void shouldNotAllowNullAddEdge() throws Exception {
+            final Vertex v = this.graph.addVertex();
+            final Edge e = v.addEdge("self", v, "name", null);
+            assertThat(e.properties("name").hasNext(), is(false));
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES)
+        public void shouldAllowNullAddVertex() throws Exception {
+            final Vertex v = this.graph.addVertex("name", null);
+            assertNull(v.value("name"));
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_NULL_PROPERTY_VALUES)
+        public void shouldAllowNullAddEdge() throws Exception {
+            final Vertex v = this.graph.addVertex();
+            final Edge e = v.addEdge("self", v, "name", null);
+            assertNull(e.value("name"));
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_NULL_PROPERTY_VALUES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES)
+        public void shouldAllowNullAddVertexProperty() throws Exception {
+            final Vertex v = this.graph.addVertex("person");
+            final VertexProperty vp = v.property("location", "santa fe", "startTime", 1995, "endTime", null);
+            assertEquals(1995, (int) vp.value("startTime"));
+            assertNull(vp.value("endTime"));
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_NULL_PROPERTY_VALUES, supported = false)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES)
+        public void shouldNotAllowNullAddVertexProperty() throws Exception {
+            final Vertex v = this.graph.addVertex("person");
+            final VertexProperty vp = v.property("location", "santa fe", "startTime", 1995, "endTime", null);
+            assertEquals(1995, (int) vp.value("startTime"));
+            assertThat(vp.properties("endTime").hasNext(), is(false));
+        }
     }
 
     /**
@@ -153,7 +211,6 @@
             "providedKeyValuesMustHaveALegalKeyOnEvenIndices"
     })
     @ExceptionCoverage(exceptionClass = Property.Exceptions.class, methods = {
-            "propertyValueCanNotBeNull",
             "propertyKeyCanNotBeEmpty"
     })
     public static class PropertyValidationOnAddExceptionConsistencyTest extends AbstractGremlinTest {
@@ -164,7 +221,6 @@
                     {"providedKeyValuesMustBeAMultipleOfTwo", new Object[]{"odd", "number", "arguments"}, Element.Exceptions.providedKeyValuesMustBeAMultipleOfTwo()},
                     {"providedKeyValuesMustBeAMultipleOfTwo", new Object[]{"odd"}, Element.Exceptions.providedKeyValuesMustBeAMultipleOfTwo()},
                     {"providedKeyValuesMustHaveALegalKeyOnEvenIndices", new Object[]{"odd", "number", 123, "test"}, Element.Exceptions.providedKeyValuesMustHaveALegalKeyOnEvenIndices()},
-                    {"propertyValueCanNotBeNull", new Object[]{"odd", null}, Property.Exceptions.propertyValueCanNotBeNull()},
                     {"providedKeyValuesMustHaveALegalKeyOnEvenIndices", new Object[]{null, "val"}, Element.Exceptions.providedKeyValuesMustHaveALegalKeyOnEvenIndices()},
                     {"propertyKeyCanNotBeEmpty", new Object[]{"", "val"}, Property.Exceptions.propertyKeyCanNotBeEmpty()}});
         }
@@ -245,13 +301,11 @@
 
 
     /**
-     * Checks that properties added to an {@link Element} are validated in a
-     * consistent way when they are set after {@link Vertex} or {@link Edge} construction by throwing an
-     * appropriate exception.
+     * Checks that properties added to an {@link Element} are validated in a consistent way when they are set after
+     * {@link Vertex} or {@link Edge} construction by throwing an appropriate exception.
      */
     @RunWith(Parameterized.class)
     @ExceptionCoverage(exceptionClass = Property.Exceptions.class, methods = {
-            "propertyValueCanNotBeNull",
             "propertyKeyCanNotBeNull",
             "propertyKeyCanNotBeEmpty",
             "propertyKeyCanNotBeAHiddenKey"
@@ -261,7 +315,6 @@
         @Parameterized.Parameters(name = "expect({0})")
         public static Iterable<Object[]> data() {
             return Arrays.asList(new Object[][]{
-                    {"propertyValueCanNotBeNull", "k", null, Property.Exceptions.propertyValueCanNotBeNull()},
                     {"propertyKeyCanNotBeNull", null, "v", Property.Exceptions.propertyKeyCanNotBeNull()},
                     {"propertyKeyCanNotBeEmpty", "", "v", Property.Exceptions.propertyKeyCanNotBeEmpty()},
                     {"propertyKeyCanNotBeAHiddenKey", Graph.Hidden.hide("systemKey"), "value", Property.Exceptions.propertyKeyCanNotBeAHiddenKey(Graph.Hidden.hide("systemKey"))}});
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/RemoteGraph.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/RemoteGraph.java
index 954118b..0498dc0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/RemoteGraph.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/RemoteGraph.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
 import org.apache.tinkerpop.gremlin.GraphProvider;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
@@ -79,14 +79,6 @@
         method = "*",
         reason = "RemoteGraph does not support direct Graph.compute() access")
 @Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgramTest",
-        method = "*",
-        reason = "RemoteGraph does not support direct Graph.compute() access")
-@Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.computer.bulkdumping.BulkDumperVertexProgramTest",
-        method = "*",
-        reason = "RemoteGraph does not support direct Graph.compute() access")
-@Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgramTest",
         method = "*",
         reason = "RemoteGraph does not support direct Graph.compute() access")
@@ -102,6 +94,14 @@
         test = "org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionComputerTest",
         method = "*",
         reason = "The interruption model in the test can't guarantee interruption at the right time with RemoteGraph.")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.ComplexTest",
+        method = "classicRecommendation",
+        reason = "Test asserts traversal side-effects which are not supported by remote traversals.")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX",
+        reason = "Test asserts traversal side-effects which are not supported by remote traversals.")
 public class RemoteGraph implements Graph {
 
     private final RemoteConnection connection;
@@ -136,7 +136,8 @@
     }
 
     public static RemoteGraph open(final String configFile) throws Exception {
-        return open(new PropertiesConfiguration(configFile));
+        final Configurations configs = new Configurations();
+        return open(configs.properties((configFile)));
     }
 
     /**
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionTest.java
index d7a651b..bad692d 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionTest.java
@@ -22,7 +22,7 @@
 import org.apache.tinkerpop.gremlin.ExceptionCoverage;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.junit.Test;
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexPropertyTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexPropertyTest.java
index 04b431d..c8b3c66 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexPropertyTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexPropertyTest.java
@@ -111,7 +111,8 @@
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES)
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES)
         @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_INTEGER_VALUES)
-        public void shouldHandleListVertexProperties() {
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES, supported = false)
+        public void shouldHandleListVertexPropertiesWithoutNullPropertyValues() {
             final Vertex v = graph.addVertex("name", "marko", "age", 34);
             tryCommit(graph, g -> {
                 assertEquals("marko", v.property("name").value());
@@ -169,6 +170,95 @@
 
                 assertVertexEdgeCounts(graph, 1, 0);
             });
+
+            // null property values are not supported so the value should not be added as set or list cardinality,
+            // but single will remove it
+            assertEquals(VertexProperty.empty(), v.property(VertexProperty.Cardinality.list, "name", null));
+            tryCommit(graph, g -> {
+                assertEquals(3, IteratorUtils.count(v.properties("name")));
+                assertEquals(4, IteratorUtils.count(v.properties()));
+                assertVertexEdgeCounts(graph, 1, 0);
+            });
+            assertEquals(VertexProperty.empty(), v.property(VertexProperty.Cardinality.single, "name", null));
+            tryCommit(graph, g -> {
+                assertEquals(0, IteratorUtils.count(v.properties("name")));
+                assertEquals(1, IteratorUtils.count(v.properties()));
+                assertVertexEdgeCounts(graph, 1, 0);
+            });
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_INTEGER_VALUES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NULL_PROPERTY_VALUES)
+        public void shouldHandleListVertexPropertiesWithNullPropertyValues() {
+            final Vertex v = graph.addVertex("name", "marko", "age", 34);
+            tryCommit(graph, g -> {
+                assertEquals("marko", v.property("name").value());
+                assertEquals("marko", v.value("name"));
+                assertEquals(34, v.property("age").value());
+                assertEquals(34, v.<Integer>value("age").intValue());
+                assertEquals(1, IteratorUtils.count(v.properties("name")));
+                assertEquals(2, IteratorUtils.count(v.properties()));
+                assertVertexEdgeCounts(graph, 1, 0);
+            });
+
+            final VertexProperty<String> property = v.property(VertexProperty.Cardinality.list, "name", "marko a. rodriguez");
+            tryCommit(graph, g -> assertEquals(v, property.element()));
+
+            try {
+                v.property("name");
+                fail("This should throw a: " + Vertex.Exceptions.multiplePropertiesExistForProvidedKey("name"));
+            } catch (final Exception e) {
+                validateException(Vertex.Exceptions.multiplePropertiesExistForProvidedKey("name"), e);
+            }
+
+            assertTrue(IteratorUtils.list(v.values("name")).contains("marko"));
+            assertTrue(IteratorUtils.list(v.values("name")).contains("marko a. rodriguez"));
+            assertEquals(3, IteratorUtils.count(v.properties()));
+            assertEquals(2, IteratorUtils.count(v.properties("name")));
+            assertVertexEdgeCounts(graph, 1, 0);
+
+            assertEquals(v, v.property(VertexProperty.Cardinality.list, "name", "mrodriguez").element());
+            tryCommit(graph, g -> {
+                assertEquals(3, IteratorUtils.count(v.properties("name")));
+                assertEquals(4, IteratorUtils.count(v.properties()));
+                assertVertexEdgeCounts(graph, 1, 0);
+            });
+
+            v.<String>properties("name").forEachRemaining(meta -> {
+                meta.property("counter", meta.value().length());
+            });
+
+            tryCommit(graph, g -> {
+                v.properties().forEachRemaining(meta -> {
+                    assertEquals(meta.key(), meta.label());
+                    assertTrue(meta.isPresent());
+                    assertEquals(v, meta.element());
+                    if (meta.key().equals("age")) {
+                        assertEquals(meta.value(), 34);
+                        assertEquals(0, IteratorUtils.count(meta.properties()));
+                    }
+                    if (meta.key().equals("name")) {
+                        assertEquals(((String) meta.value()).length(), meta.<Integer>value("counter").intValue());
+                        assertEquals(1, IteratorUtils.count(meta.properties()));
+                        assertEquals(1, meta.keys().size());
+                        assertTrue(meta.keys().contains("counter"));
+                    }
+                });
+
+                assertVertexEdgeCounts(graph, 1, 0);
+            });
+
+            // null property values are supported so the value should be added
+            assertEquals(v, v.property(VertexProperty.Cardinality.list, "name", null).element());
+            tryCommit(graph, g -> {
+                assertEquals(4, IteratorUtils.count(v.properties("name")));
+                assertEquals(5, IteratorUtils.count(v.properties()));
+                assertVertexEdgeCounts(graph, 1, 0);
+            });
         }
 
         @Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoCustomTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoCustomTest.java
index f4091e1..cb5f3c8 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoCustomTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoCustomTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.structure.Edge;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoGraphTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoGraphTest.java
index e882505..b3ef335 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoGraphTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoGraphTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoTest.java
index f4b23f2..8fc463d 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/IoTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphTest.java
index 47604c3..7d04d38 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.util.star;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
diff --git a/gremlin-tools/gremlin-benchmark/README.asciidoc b/gremlin-tools/gremlin-benchmark/README.asciidoc
new file mode 100644
index 0000000..84f8d5f
--- /dev/null
+++ b/gremlin-tools/gremlin-benchmark/README.asciidoc
@@ -0,0 +1,31 @@
+////
+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.
+////
+== Apache TinkerPop Benchmarks
+
+This module is for development and testing only and no convenience binaries are produced for it. The compilation
+of this module requires:
+
+[source,xml]
+----
+<dependency>
+    <groupId>javax.annotation</groupId>
+    <artifactId>javax.annotation-api</artifactId>
+    <scope>provided</scope>
+</dependency>
+----
+
+The source for this project can be found at link:javaee/javax.annotation:https://github.com/javaee/javax.annotation.
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-benchmark/pom.xml b/gremlin-tools/gremlin-benchmark/pom.xml
index cca15df..4dbc742 100644
--- a/gremlin-tools/gremlin-benchmark/pom.xml
+++ b/gremlin-tools/gremlin-benchmark/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>gremlin-tools</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-benchmark</artifactId>
@@ -60,6 +60,11 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>tinkergraph-gremlin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.openjdk.jmh</groupId>
             <artifactId>jmh-core</artifactId>
             <version>${jmh.version}</version>
@@ -73,7 +78,6 @@
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-log4j12</artifactId>
-            <optional>true</optional>
         </dependency>
     </dependencies>
     <build>
diff --git a/gremlin-tools/gremlin-coverage/pom.xml b/gremlin-tools/gremlin-coverage/pom.xml
index 6f63a1f..3df9f20 100644
--- a/gremlin-tools/gremlin-coverage/pom.xml
+++ b/gremlin-tools/gremlin-coverage/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>gremlin-tools</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-coverage</artifactId>
     <name>Apache TinkerPop :: Gremlin Coverage</name>
diff --git a/gremlin-tools/gremlin-io-test/pom.xml b/gremlin-tools/gremlin-io-test/pom.xml
index 6892f8f..d7606f4 100644
--- a/gremlin-tools/gremlin-io-test/pom.xml
+++ b/gremlin-tools/gremlin-io-test/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>gremlin-tools</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-io-test</artifactId>
     <name>Apache TinkerPop :: Gremlin IO Test</name>
diff --git a/gremlin-tools/gremlin-io-test/scripts/generate-graphbinary-resources.groovy b/gremlin-tools/gremlin-io-test/scripts/generate-graphbinary-resources.groovy
index bde5660..12ecadd 100644
--- a/gremlin-tools/gremlin-io-test/scripts/generate-graphbinary-resources.groovy
+++ b/gremlin-tools/gremlin-io-test/scripts/generate-graphbinary-resources.groovy
@@ -23,7 +23,7 @@
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.*
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.*
-import org.apache.commons.configuration.BaseConfiguration
+import org.apache.commons.configuration2.BaseConfiguration
 
 new File("${projectBuildDir}/test-case-data/io/graphbinary").mkdirs()
 
diff --git a/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy b/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
index 03112ed..1ea68e1 100644
--- a/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
+++ b/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
@@ -23,7 +23,7 @@
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.graphson.*
 import org.apache.tinkerpop.gremlin.structure.io.Model
-import org.apache.commons.configuration.BaseConfiguration
+import org.apache.commons.configuration2.BaseConfiguration
 
 new File("${projectBuildDir}/dev-docs/").mkdirs()
 new File("${projectBuildDir}/test-case-data/io/graphson/").mkdirs()
diff --git a/gremlin-tools/gremlin-io-test/scripts/generate-gryo-resources.groovy b/gremlin-tools/gremlin-io-test/scripts/generate-gryo-resources.groovy
index 97d9911..7301b44 100644
--- a/gremlin-tools/gremlin-io-test/scripts/generate-gryo-resources.groovy
+++ b/gremlin-tools/gremlin-io-test/scripts/generate-gryo-resources.groovy
@@ -22,7 +22,7 @@
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.gryo.*
 import org.apache.tinkerpop.gremlin.structure.io.*
-import org.apache.commons.configuration.BaseConfiguration
+import org.apache.commons.configuration2.BaseConfiguration
 
 new File("${projectBuildDir}/dev-docs/").mkdirs()
 new File("${projectBuildDir}/test-case-data/io/gryo").mkdirs()
diff --git a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
index aff0f1a..8959faa 100644
--- a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
+++ b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
@@ -120,6 +120,12 @@
                 .join(Compatibilities.with(GraphSONCompatibility.class).configuredAs(".*no-types|v1d0")
                 .join(Compatibilities.with(GraphSONCompatibility.class).beforeRelease("3.4.0"))).matchToArray();
 
+        // the inverse of this definition is basically 3.5.0 or better for both GraphSON and Gryo with no support for
+        // untyped GraphSON anywhere along the way
+        final Compatibility[] before3_5_0 = Compatibilities.with(GryoCompatibility.class).beforeRelease("3.5.0")
+                .join(Compatibilities.with(GraphSONCompatibility.class).configuredAs(".*no-types|v1d0")
+                        .join(Compatibilities.with(GraphSONCompatibility.class).beforeRelease("3.5.0"))).matchToArray();
+
         // there is no point to testing gryo for list/map/set as they are kryo primitives essentially
         final Compatibility[] noGraphSONBeforeV3AndNoGryo = Compatibilities.with(GraphSONCompatibility.class).configuredAs(".*v2d0-partial|v1d0|v2d0-no-types").join(Compatibilities.GRYO_ONLY).matchToArray();
 
@@ -169,7 +175,7 @@
         addGraphProcessEntry(Column.keys, "Column", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         addGraphProcessEntry(Direction.OUT, "Direction", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         addGraphProcessEntry(Operator.sum, "Operator", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
-        addGraphProcessEntry(Order.shuffle, "Order", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
+        addGraphProcessEntry(Order.shuffle, "Order", "", before3_5_0);
         addGraphProcessEntry(TraversalOptionParent.Pick.any, "Pick", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         addGraphProcessEntry(Pop.all, "Pop", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         addGraphProcessEntry(org.apache.tinkerpop.gremlin.util.function.Lambda.function("{ it.get() }"), "Lambda", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
diff --git a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibility.java b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibility.java
index fbe62be..8855871 100644
--- a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibility.java
+++ b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibility.java
@@ -50,7 +50,9 @@
     V1_3_4_6("3.4.6", "1.0", "v1"),
     V1_3_4_7("3.4.7", "1.0", "v1"),
     V1_3_4_8("3.4.8", "1.0", "v1"),
-    V1_3_4_9("3.4.9", "1.0", "v1");
+    V1_3_4_9("3.4.9", "1.0", "v1"),
+
+    V1_3_5_0("3.5.0", "1.0", "v1");
 
     private static final String SEP = File.separator;
 
diff --git a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONCompatibility.java b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONCompatibility.java
index 661b44c..03e4695 100644
--- a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONCompatibility.java
+++ b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONCompatibility.java
@@ -139,7 +139,12 @@
     V1D0_3_4_9("3.4.9", "1.0", "v1d0"),
     V2D0_PARTIAL_3_4_9("3.4.9", "2.0", "v2d0-partial"),
     V2D0_NO_TYPE_3_4_9("3.4.9", "2.0", "v2d0-no-types"),
-    V3D0_PARTIAL_3_4_9("3.4.9", "3.0", "v3d0");
+    V3D0_PARTIAL_3_4_9("3.4.9", "3.0", "v3d0"),
+
+    V1D0_3_5_0("3.5.0", "1.0", "v1d0"),
+    V2D0_PARTIAL_3_5_0("3.5.0", "2.0", "v2d0-partial"),
+    V2D0_NO_TYPE_3_5_0("3.5.0", "2.0", "v2d0-no-types"),
+    V3D0_PARTIAL_3_5_0("3.5.0", "3.0", "v3d0");
 
     private static final String SEP = File.separator;
 
diff --git a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibility.java b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibility.java
index f49df6f..1f69ecc 100644
--- a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibility.java
+++ b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibility.java
@@ -95,7 +95,10 @@
     V1D0_3_4_8("3.4.8", "1.0", "v1d0"),
     V3D0_3_4_8("3.4.8", "3.0", "v3d0"),
     V1D0_3_4_9("3.4.9", "1.0", "v1d0"),
-    V3D0_3_4_9("3.4.9", "3.0", "v3d0");
+    V3D0_3_4_9("3.4.9", "3.0", "v3d0"),
+
+    V1D0_3_5_0("3.5.0", "1.0", "v1d0"),
+    V3D0_3_5_0("3.5.0", "3.0", "v3d0");
 
     private static final String SEP = File.separator;
 
diff --git a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibilityTest.java
index 58996e8..0e5d47e 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphbinary/GraphBinaryCompatibilityTest.java
@@ -51,7 +51,9 @@
                 {GraphBinaryCompatibility.V1_3_4_6, readerV1, writerV1 },
                 {GraphBinaryCompatibility.V1_3_4_7, readerV1, writerV1 },
                 {GraphBinaryCompatibility.V1_3_4_8, readerV1, writerV1 },
-                {GraphBinaryCompatibility.V1_3_4_9, readerV1, writerV1 }
+                {GraphBinaryCompatibility.V1_3_4_9, readerV1, writerV1 },
+
+                {GraphBinaryCompatibility.V1_3_5_0, readerV1, writerV1 }
         });
     }
 
diff --git a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypedCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypedCompatibilityTest.java
index 6caf788..913b5ff 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypedCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypedCompatibilityTest.java
@@ -101,7 +101,10 @@
                 {GraphSONCompatibility.V2D0_PARTIAL_3_4_8, mapperV2 },
                 {GraphSONCompatibility.V3D0_PARTIAL_3_4_8, mapperV3 },
                 {GraphSONCompatibility.V2D0_PARTIAL_3_4_9, mapperV2 },
-                {GraphSONCompatibility.V3D0_PARTIAL_3_4_9, mapperV3 }
+                {GraphSONCompatibility.V3D0_PARTIAL_3_4_9, mapperV3 },
+
+                {GraphSONCompatibility.V2D0_PARTIAL_3_5_0, mapperV2 },
+                {GraphSONCompatibility.V3D0_PARTIAL_3_5_0, mapperV3 }
         });
     }
 
diff --git a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUntypedCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUntypedCompatibilityTest.java
index 7e90140..6356521 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUntypedCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUntypedCompatibilityTest.java
@@ -109,7 +109,10 @@
                 {GraphSONCompatibility.V1D0_3_4_8, mapperV1 },
                 {GraphSONCompatibility.V2D0_NO_TYPE_3_4_8, mapperV2 },
                 {GraphSONCompatibility.V1D0_3_4_9, mapperV1 },
-                {GraphSONCompatibility.V2D0_NO_TYPE_3_4_9, mapperV2 }
+                {GraphSONCompatibility.V2D0_NO_TYPE_3_4_9, mapperV2 },
+
+                {GraphSONCompatibility.V1D0_3_5_0, mapperV1 },
+                {GraphSONCompatibility.V2D0_NO_TYPE_3_5_0, mapperV2 }
         });
     }
 
diff --git a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibilityTest.java
index 48d0fdc..a953b9e 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoCompatibilityTest.java
@@ -98,7 +98,10 @@
                 {GryoCompatibility.V1D0_3_4_8, mapperV1 },
                 {GryoCompatibility.V3D0_3_4_8, mapperV3 },
                 {GryoCompatibility.V1D0_3_4_9, mapperV1 },
-                {GryoCompatibility.V3D0_3_4_9, mapperV3 }
+                {GryoCompatibility.V3D0_3_4_9, mapperV3 },
+
+                {GryoCompatibility.V1D0_3_5_0, mapperV1 },
+                {GryoCompatibility.V3D0_3_5_0, mapperV3 }
         });
     }
 
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/barrier-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/barrier-v1.gbin
new file mode 100644
index 0000000..f905861
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/barrier-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bigdecimal-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bigdecimal-v1.gbin
new file mode 100644
index 0000000..921d957
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bigdecimal-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/biginteger-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/biginteger-v1.gbin
new file mode 100644
index 0000000..d841fbe
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/biginteger-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/binding-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/binding-v1.gbin
new file mode 100644
index 0000000..79620eb
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/binding-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bulkset-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bulkset-v1.gbin
new file mode 100644
index 0000000..4542906
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bulkset-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/byte-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/byte-v1.gbin
new file mode 100644
index 0000000..af9544f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/byte-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bytebuffer-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bytebuffer-v1.gbin
new file mode 100644
index 0000000..39793d2
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bytebuffer-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bytecode-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bytecode-v1.gbin
new file mode 100644
index 0000000..bc76c2e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/bytecode-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/cardinality-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/cardinality-v1.gbin
new file mode 100644
index 0000000..3c875a5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/cardinality-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/char-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/char-v1.gbin
new file mode 100644
index 0000000..b9d97e6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/char-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/class-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/class-v1.gbin
new file mode 100644
index 0000000..6be272d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/class-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/column-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/column-v1.gbin
new file mode 100644
index 0000000..c6805c8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/column-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/date-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/date-v1.gbin
new file mode 100644
index 0000000..e68e17a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/date-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/direction-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/direction-v1.gbin
new file mode 100644
index 0000000..3caaba3
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/direction-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/double-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/double-v1.gbin
new file mode 100644
index 0000000..e538a62
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/double-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/duration-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/duration-v1.gbin
new file mode 100644
index 0000000..7ffa3ad
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/duration-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/edge-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/edge-v1.gbin
new file mode 100644
index 0000000..086e85d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/edge-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/float-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/float-v1.gbin
new file mode 100644
index 0000000..322772c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/float-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/inetaddress-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/inetaddress-v1.gbin
new file mode 100644
index 0000000..b613ddb
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/inetaddress-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/instant-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/instant-v1.gbin
new file mode 100644
index 0000000..3335532
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/instant-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/integer-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/integer-v1.gbin
new file mode 100644
index 0000000..7dc246a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/integer-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/lambda-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/lambda-v1.gbin
new file mode 100644
index 0000000..b0e98f9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/lambda-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/list-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/list-v1.gbin
new file mode 100644
index 0000000..1aa405d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/list-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localdate-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localdate-v1.gbin
new file mode 100644
index 0000000..2c9e211
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localdate-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localdatetime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localdatetime-v1.gbin
new file mode 100644
index 0000000..2e0c83c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localdatetime-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localtime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localtime-v1.gbin
new file mode 100644
index 0000000..05785c6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/localtime-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/long-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/long-v1.gbin
new file mode 100644
index 0000000..cee0083
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/long-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/map-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/map-v1.gbin
new file mode 100644
index 0000000..46cd9e2
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/map-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/metrics-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/metrics-v1.gbin
new file mode 100644
index 0000000..dea77a5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/metrics-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/monthday-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/monthday-v1.gbin
new file mode 100644
index 0000000..c128263
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/monthday-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/offsetdatetime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/offsetdatetime-v1.gbin
new file mode 100644
index 0000000..4b2aabb
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/offsetdatetime-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/offsettime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/offsettime-v1.gbin
new file mode 100644
index 0000000..a4c8c5b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/offsettime-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/operator-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/operator-v1.gbin
new file mode 100644
index 0000000..84717cc
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/operator-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/order-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/order-v1.gbin
new file mode 100644
index 0000000..311b6ad
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/order-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/p-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/p-v1.gbin
new file mode 100644
index 0000000..ac60799
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/p-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pand-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pand-v1.gbin
new file mode 100644
index 0000000..3237c94
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pand-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/path-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/path-v1.gbin
new file mode 100644
index 0000000..ba075ac
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/path-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/period-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/period-v1.gbin
new file mode 100644
index 0000000..f7dab35
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/period-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pick-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pick-v1.gbin
new file mode 100644
index 0000000..77aca2f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pick-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pop-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pop-v1.gbin
new file mode 100644
index 0000000..f698c94
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pop-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/por-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/por-v1.gbin
new file mode 100644
index 0000000..7c0b3ab
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/por-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/property-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/property-v1.gbin
new file mode 100644
index 0000000..ddc34e5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/property-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pwithin-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pwithin-v1.gbin
new file mode 100644
index 0000000..5ad30a9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pwithin-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pwithout-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pwithout-v1.gbin
new file mode 100644
index 0000000..5b195db
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/pwithout-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/scope-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/scope-v1.gbin
new file mode 100644
index 0000000..534b956
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/scope-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/set-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/set-v1.gbin
new file mode 100644
index 0000000..02df059
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/set-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/short-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/short-v1.gbin
new file mode 100644
index 0000000..e1d2d7d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/short-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/t-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/t-v1.gbin
new file mode 100644
index 0000000..a6376db
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/t-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/textp-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/textp-v1.gbin
new file mode 100644
index 0000000..c796468
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/textp-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/timestamp-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/timestamp-v1.gbin
new file mode 100644
index 0000000..4fc4e5e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/timestamp-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/tinkergraph-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/tinkergraph-v1.gbin
new file mode 100644
index 0000000..a0a76d1
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/tinkergraph-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/traversalmetrics-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/traversalmetrics-v1.gbin
new file mode 100644
index 0000000..c947e62
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/traversalmetrics-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/traverser-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/traverser-v1.gbin
new file mode 100644
index 0000000..8e47cc0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/traverser-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/uuid-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/uuid-v1.gbin
new file mode 100644
index 0000000..7f1775d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/uuid-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/vertex-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/vertex-v1.gbin
new file mode 100644
index 0000000..7fb9d65
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/vertex-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/vertexproperty-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/vertexproperty-v1.gbin
new file mode 100644
index 0000000..89f0329
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/vertexproperty-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/year-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/year-v1.gbin
new file mode 100644
index 0000000..1fe0c74
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/year-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/yearmonth-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/yearmonth-v1.gbin
new file mode 100644
index 0000000..481a121
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/yearmonth-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/zoneoffset-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/zoneoffset-v1.gbin
new file mode 100644
index 0000000..2867c97
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_5_0/zoneoffset-v1.gbin
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v1d0.json
new file mode 100644
index 0000000..8c5b82c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v1d0.json
@@ -0,0 +1,12 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 407,
+    "attributes" : { }
+  },
+  "result" : {
+    "data" : null,
+    "meta" : { }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v2d0-no-types.json
new file mode 100644
index 0000000..8c5b82c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v2d0-no-types.json
@@ -0,0 +1,12 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 407,
+    "attributes" : { }
+  },
+  "result" : {
+    "data" : null,
+    "meta" : { }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v2d0-partial.json
new file mode 100644
index 0000000..8c5b82c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v2d0-partial.json
@@ -0,0 +1,12 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 407,
+    "attributes" : { }
+  },
+  "result" : {
+    "data" : null,
+    "meta" : { }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v3d0.json
new file mode 100644
index 0000000..d1734c6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationchallenge-v3d0.json
@@ -0,0 +1,18 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 407,
+    "attributes" : {
+      "@type" : "g:Map",
+      "@value" : [ ]
+    }
+  },
+  "result" : {
+    "data" : null,
+    "meta" : {
+      "@type" : "g:Map",
+      "@value" : [ ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v1d0.json
new file mode 100644
index 0000000..838e1fd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v1d0.json
@@ -0,0 +1,9 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "authentication",
+  "processor" : "",
+  "args" : {
+    "saslMechanism" : "PLAIN",
+    "sasl" : "AHN0ZXBocGhlbgBwYXNzd29yZA=="
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v2d0-no-types.json
new file mode 100644
index 0000000..838e1fd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v2d0-no-types.json
@@ -0,0 +1,9 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "authentication",
+  "processor" : "",
+  "args" : {
+    "saslMechanism" : "PLAIN",
+    "sasl" : "AHN0ZXBocGhlbgBwYXNzd29yZA=="
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v2d0-partial.json
new file mode 100644
index 0000000..838e1fd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v2d0-partial.json
@@ -0,0 +1,9 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "authentication",
+  "processor" : "",
+  "args" : {
+    "saslMechanism" : "PLAIN",
+    "sasl" : "AHN0ZXBocGhlbgBwYXNzd29yZA=="
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v3d0.json
new file mode 100644
index 0000000..daceca2
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/authenticationresponse-v3d0.json
@@ -0,0 +1,9 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "authentication",
+  "processor" : "",
+  "args" : {
+    "@type" : "g:Map",
+    "@value" : [ "saslMechanism", "PLAIN", "sasl", "AHN0ZXBocGhlbgBwYXNzd29yZA==" ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/barrier-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/barrier-v2d0-partial.json
new file mode 100644
index 0000000..7ddccdd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/barrier-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Barrier",
+  "@value" : "normSack"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/barrier-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/barrier-v3d0.json
new file mode 100644
index 0000000..7ddccdd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/barrier-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Barrier",
+  "@value" : "normSack"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bigdecimal-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bigdecimal-v2d0-partial.json
new file mode 100644
index 0000000..475337c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bigdecimal-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:BigDecimal",
+  "@value" : 123456789987654321123456789987654321
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bigdecimal-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bigdecimal-v3d0.json
new file mode 100644
index 0000000..475337c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bigdecimal-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:BigDecimal",
+  "@value" : 123456789987654321123456789987654321
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/biginteger-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/biginteger-v2d0-partial.json
new file mode 100644
index 0000000..58e6114
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/biginteger-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:BigInteger",
+  "@value" : 123456789987654321123456789987654321
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/biginteger-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/biginteger-v3d0.json
new file mode 100644
index 0000000..58e6114
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/biginteger-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:BigInteger",
+  "@value" : 123456789987654321123456789987654321
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/binding-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/binding-v2d0-partial.json
new file mode 100644
index 0000000..579b8c7
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/binding-v2d0-partial.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:Binding",
+  "@value" : {
+    "key" : "x",
+    "value" : {
+      "@type" : "g:Int32",
+      "@value" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/binding-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/binding-v3d0.json
new file mode 100644
index 0000000..579b8c7
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/binding-v3d0.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:Binding",
+  "@value" : {
+    "key" : "x",
+    "value" : {
+      "@type" : "g:Int32",
+      "@value" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bulkset-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bulkset-v2d0-partial.json
new file mode 100644
index 0000000..c844975
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bulkset-v2d0-partial.json
@@ -0,0 +1 @@
+[ "marko", "josh", "josh" ]
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bulkset-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bulkset-v3d0.json
new file mode 100644
index 0000000..c216a36
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bulkset-v3d0.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:BulkSet",
+  "@value" : [ "marko", {
+    "@type" : "g:Int64",
+    "@value" : 1
+  }, "josh", {
+    "@type" : "g:Int64",
+    "@value" : 2
+  } ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/byte-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/byte-v2d0-partial.json
new file mode 100644
index 0000000..979625b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/byte-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Byte",
+  "@value" : 1
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/byte-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/byte-v3d0.json
new file mode 100644
index 0000000..979625b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/byte-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Byte",
+  "@value" : 1
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytebuffer-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytebuffer-v2d0-partial.json
new file mode 100644
index 0000000..5724115
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytebuffer-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:ByteBuffer",
+  "@value" : "c29tZSBieXRlcyBmb3IgeW91"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytebuffer-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytebuffer-v3d0.json
new file mode 100644
index 0000000..5724115
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytebuffer-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:ByteBuffer",
+  "@value" : "c29tZSBieXRlcyBmb3IgeW91"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytecode-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytecode-v2d0-partial.json
new file mode 100644
index 0000000..269d277
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytecode-v2d0-partial.json
@@ -0,0 +1,6 @@
+{
+  "@type" : "g:Bytecode",
+  "@value" : {
+    "step" : [ [ "V" ], [ "hasLabel", "person" ], [ "out" ], [ "in" ], [ "tree" ] ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytecode-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytecode-v3d0.json
new file mode 100644
index 0000000..269d277
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/bytecode-v3d0.json
@@ -0,0 +1,6 @@
+{
+  "@type" : "g:Bytecode",
+  "@value" : {
+    "step" : [ [ "V" ], [ "hasLabel", "person" ], [ "out" ], [ "in" ], [ "tree" ] ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/cardinality-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/cardinality-v2d0-partial.json
new file mode 100644
index 0000000..834e64e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/cardinality-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Cardinality",
+  "@value" : "list"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/cardinality-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/cardinality-v3d0.json
new file mode 100644
index 0000000..834e64e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/cardinality-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Cardinality",
+  "@value" : "list"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/char-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/char-v2d0-partial.json
new file mode 100644
index 0000000..8f27e9d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/char-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Char",
+  "@value" : "x"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/char-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/char-v3d0.json
new file mode 100644
index 0000000..8f27e9d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/char-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Char",
+  "@value" : "x"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/class-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/class-v2d0-partial.json
new file mode 100644
index 0000000..80f15a2
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/class-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Class",
+  "@value" : "java.io.File"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/class-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/class-v3d0.json
new file mode 100644
index 0000000..80f15a2
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/class-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Class",
+  "@value" : "java.io.File"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/column-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/column-v2d0-partial.json
new file mode 100644
index 0000000..0b3a56e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/column-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Column",
+  "@value" : "keys"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/column-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/column-v3d0.json
new file mode 100644
index 0000000..0b3a56e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/column-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Column",
+  "@value" : "keys"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v2d0-no-types.json
new file mode 100644
index 0000000..03b71a0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v2d0-no-types.json
@@ -0,0 +1 @@
+1481750076295
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v2d0-partial.json
new file mode 100644
index 0000000..cf4007a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Date",
+  "@value" : 1481750076295
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v3d0.json
new file mode 100644
index 0000000..cf4007a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/date-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Date",
+  "@value" : 1481750076295
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/direction-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/direction-v2d0-partial.json
new file mode 100644
index 0000000..78cb7e4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/direction-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Direction",
+  "@value" : "OUT"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/direction-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/direction-v3d0.json
new file mode 100644
index 0000000..78cb7e4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/direction-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Direction",
+  "@value" : "OUT"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v2d0-no-types.json
new file mode 100644
index 0000000..e772e62
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v2d0-no-types.json
@@ -0,0 +1 @@
+100.0
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v2d0-partial.json
new file mode 100644
index 0000000..9ae4964
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Double",
+  "@value" : 100.0
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v3d0.json
new file mode 100644
index 0000000..9ae4964
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/double-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Double",
+  "@value" : 100.0
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/duration-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/duration-v2d0-partial.json
new file mode 100644
index 0000000..05c0ce9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/duration-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Duration",
+  "@value" : "PT120H"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/duration-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/duration-v3d0.json
new file mode 100644
index 0000000..05c0ce9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/duration-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Duration",
+  "@value" : "PT120H"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v1d0.json
new file mode 100644
index 0000000..0f7f168
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v1d0.json
@@ -0,0 +1,12 @@
+{
+  "id" : 13,
+  "label" : "develops",
+  "type" : "edge",
+  "inVLabel" : "software",
+  "outVLabel" : "person",
+  "inV" : 10,
+  "outV" : 1,
+  "properties" : {
+    "since" : 2009
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v2d0-no-types.json
new file mode 100644
index 0000000..a8e73db
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v2d0-no-types.json
@@ -0,0 +1,14 @@
+{
+  "id" : 13,
+  "label" : "develops",
+  "inVLabel" : "software",
+  "outVLabel" : "person",
+  "inV" : 10,
+  "outV" : 1,
+  "properties" : {
+    "since" : {
+      "key" : "since",
+      "value" : 2009
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v2d0-partial.json
new file mode 100644
index 0000000..ba1c52e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v2d0-partial.json
@@ -0,0 +1,32 @@
+{
+  "@type" : "g:Edge",
+  "@value" : {
+    "id" : {
+      "@type" : "g:Int32",
+      "@value" : 13
+    },
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : {
+      "@type" : "g:Int32",
+      "@value" : 10
+    },
+    "outV" : {
+      "@type" : "g:Int32",
+      "@value" : 1
+    },
+    "properties" : {
+      "since" : {
+        "@type" : "g:Property",
+        "@value" : {
+          "key" : "since",
+          "value" : {
+            "@type" : "g:Int32",
+            "@value" : 2009
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v3d0.json
new file mode 100644
index 0000000..ba1c52e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/edge-v3d0.json
@@ -0,0 +1,32 @@
+{
+  "@type" : "g:Edge",
+  "@value" : {
+    "id" : {
+      "@type" : "g:Int32",
+      "@value" : 13
+    },
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : {
+      "@type" : "g:Int32",
+      "@value" : 10
+    },
+    "outV" : {
+      "@type" : "g:Int32",
+      "@value" : 1
+    },
+    "properties" : {
+      "since" : {
+        "@type" : "g:Property",
+        "@value" : {
+          "key" : "since",
+          "value" : {
+            "@type" : "g:Int32",
+            "@value" : 2009
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/float-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/float-v2d0-partial.json
new file mode 100644
index 0000000..7179aaf
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/float-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Float",
+  "@value" : 100.0
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/float-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/float-v3d0.json
new file mode 100644
index 0000000..7179aaf
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/float-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Float",
+  "@value" : 100.0
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/inetaddress-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/inetaddress-v2d0-partial.json
new file mode 100644
index 0000000..fba98c0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/inetaddress-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:InetAddress",
+  "@value" : "localhost"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/inetaddress-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/inetaddress-v3d0.json
new file mode 100644
index 0000000..fba98c0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/inetaddress-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:InetAddress",
+  "@value" : "localhost"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/instant-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/instant-v2d0-partial.json
new file mode 100644
index 0000000..3749741
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/instant-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Instant",
+  "@value" : "2016-12-14T16:39:19.349Z"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/instant-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/instant-v3d0.json
new file mode 100644
index 0000000..3749741
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/instant-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Instant",
+  "@value" : "2016-12-14T16:39:19.349Z"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v2d0-no-types.json
new file mode 100644
index 0000000..105d7d9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v2d0-no-types.json
@@ -0,0 +1 @@
+100
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v2d0-partial.json
new file mode 100644
index 0000000..750ce7a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Int32",
+  "@value" : 100
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v3d0.json
new file mode 100644
index 0000000..750ce7a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/integer-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Int32",
+  "@value" : 100
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/lambda-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/lambda-v2d0-partial.json
new file mode 100644
index 0000000..5be179b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/lambda-v2d0-partial.json
@@ -0,0 +1,8 @@
+{
+  "@type" : "g:Lambda",
+  "@value" : {
+    "script" : "{ it.get() }",
+    "language" : "gremlin-groovy",
+    "arguments" : 1
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/lambda-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/lambda-v3d0.json
new file mode 100644
index 0000000..5be179b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/lambda-v3d0.json
@@ -0,0 +1,8 @@
+{
+  "@type" : "g:Lambda",
+  "@value" : {
+    "script" : "{ it.get() }",
+    "language" : "gremlin-groovy",
+    "arguments" : 1
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/list-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/list-v3d0.json
new file mode 100644
index 0000000..b714e2d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/list-v3d0.json
@@ -0,0 +1,7 @@
+{
+  "@type" : "g:List",
+  "@value" : [ {
+    "@type" : "g:Int32",
+    "@value" : 1
+  }, "person", true ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdate-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdate-v2d0-partial.json
new file mode 100644
index 0000000..36fb81d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdate-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:LocalDate",
+  "@value" : "2016-01-01"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdate-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdate-v3d0.json
new file mode 100644
index 0000000..36fb81d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdate-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:LocalDate",
+  "@value" : "2016-01-01"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdatetime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdatetime-v2d0-partial.json
new file mode 100644
index 0000000..2d83668
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdatetime-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:LocalDateTime",
+  "@value" : "2016-01-01T12:30"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdatetime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdatetime-v3d0.json
new file mode 100644
index 0000000..2d83668
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localdatetime-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:LocalDateTime",
+  "@value" : "2016-01-01T12:30"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localtime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localtime-v2d0-partial.json
new file mode 100644
index 0000000..eff65a7
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localtime-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:LocalTime",
+  "@value" : "12:30:45"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localtime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localtime-v3d0.json
new file mode 100644
index 0000000..eff65a7
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/localtime-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:LocalTime",
+  "@value" : "12:30:45"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/long-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/long-v2d0-partial.json
new file mode 100644
index 0000000..84b9a23
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/long-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Int64",
+  "@value" : 100
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/long-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/long-v3d0.json
new file mode 100644
index 0000000..84b9a23
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/long-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Int64",
+  "@value" : 100
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/map-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/map-v3d0.json
new file mode 100644
index 0000000..7ad59c9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/map-v3d0.json
@@ -0,0 +1,25 @@
+{
+  "@type" : "g:Map",
+  "@value" : [ {
+    "@type" : "g:Date",
+    "@value" : 1481750076295
+  }, "red", {
+    "@type" : "g:List",
+    "@value" : [ {
+      "@type" : "g:Int32",
+      "@value" : 1
+    }, {
+      "@type" : "g:Int32",
+      "@value" : 2
+    }, {
+      "@type" : "g:Int32",
+      "@value" : 3
+    } ]
+  }, {
+    "@type" : "g:Date",
+    "@value" : 1481750076295
+  }, "test", {
+    "@type" : "g:Int32",
+    "@value" : 123
+  } ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/metrics-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/metrics-v2d0-partial.json
new file mode 100644
index 0000000..7b1e964
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/metrics-v2d0-partial.json
@@ -0,0 +1,54 @@
+{
+  "@type" : "g:Metrics",
+  "@value" : {
+    "dur" : {
+      "@type" : "g:Double",
+      "@value" : 100.0
+    },
+    "counts" : {
+      "traverserCount" : {
+        "@type" : "g:Int64",
+        "@value" : 4
+      },
+      "elementCount" : {
+        "@type" : "g:Int64",
+        "@value" : 4
+      }
+    },
+    "name" : "TinkerGraphStep(vertex,[~label.eq(person)])",
+    "annotations" : {
+      "percentDur" : {
+        "@type" : "g:Double",
+        "@value" : 25.0
+      }
+    },
+    "id" : "7.0.0()",
+    "metrics" : [ {
+      "@type" : "g:Metrics",
+      "@value" : {
+        "dur" : {
+          "@type" : "g:Double",
+          "@value" : 100.0
+        },
+        "counts" : {
+          "traverserCount" : {
+            "@type" : "g:Int64",
+            "@value" : 7
+          },
+          "elementCount" : {
+            "@type" : "g:Int64",
+            "@value" : 7
+          }
+        },
+        "name" : "VertexStep(OUT,vertex)",
+        "annotations" : {
+          "percentDur" : {
+            "@type" : "g:Double",
+            "@value" : 25.0
+          }
+        },
+        "id" : "3.0.0()"
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/metrics-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/metrics-v3d0.json
new file mode 100644
index 0000000..f6e678b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/metrics-v3d0.json
@@ -0,0 +1,52 @@
+{
+  "@type" : "g:Metrics",
+  "@value" : {
+    "@type" : "g:Map",
+    "@value" : [ "dur", {
+      "@type" : "g:Double",
+      "@value" : 100.0
+    }, "counts", {
+      "@type" : "g:Map",
+      "@value" : [ "traverserCount", {
+        "@type" : "g:Int64",
+        "@value" : 4
+      }, "elementCount", {
+        "@type" : "g:Int64",
+        "@value" : 4
+      } ]
+    }, "name", "TinkerGraphStep(vertex,[~label.eq(person)])", "annotations", {
+      "@type" : "g:Map",
+      "@value" : [ "percentDur", {
+        "@type" : "g:Double",
+        "@value" : 25.0
+      } ]
+    }, "id", "7.0.0()", "metrics", {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Metrics",
+        "@value" : {
+          "@type" : "g:Map",
+          "@value" : [ "dur", {
+            "@type" : "g:Double",
+            "@value" : 100.0
+          }, "counts", {
+            "@type" : "g:Map",
+            "@value" : [ "traverserCount", {
+              "@type" : "g:Int64",
+              "@value" : 7
+            }, "elementCount", {
+              "@type" : "g:Int64",
+              "@value" : 7
+            } ]
+          }, "name", "VertexStep(OUT,vertex)", "annotations", {
+            "@type" : "g:Map",
+            "@value" : [ "percentDur", {
+              "@type" : "g:Double",
+              "@value" : 25.0
+            } ]
+          }, "id", "3.0.0()" ]
+        }
+      } ]
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/monthday-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/monthday-v2d0-partial.json
new file mode 100644
index 0000000..5da5914
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/monthday-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:MonthDay",
+  "@value" : "--01-01"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/monthday-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/monthday-v3d0.json
new file mode 100644
index 0000000..5da5914
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/monthday-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:MonthDay",
+  "@value" : "--01-01"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsetdatetime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsetdatetime-v2d0-partial.json
new file mode 100644
index 0000000..03f45cd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsetdatetime-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:OffsetDateTime",
+  "@value" : "2007-12-03T10:15:30+01:00"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsetdatetime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsetdatetime-v3d0.json
new file mode 100644
index 0000000..03f45cd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsetdatetime-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:OffsetDateTime",
+  "@value" : "2007-12-03T10:15:30+01:00"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsettime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsettime-v2d0-partial.json
new file mode 100644
index 0000000..b124953
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsettime-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:OffsetTime",
+  "@value" : "10:15:30+01:00"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsettime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsettime-v3d0.json
new file mode 100644
index 0000000..b124953
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/offsettime-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:OffsetTime",
+  "@value" : "10:15:30+01:00"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/operator-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/operator-v2d0-partial.json
new file mode 100644
index 0000000..14c1400
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/operator-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Operator",
+  "@value" : "sum"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/operator-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/operator-v3d0.json
new file mode 100644
index 0000000..14c1400
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/operator-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Operator",
+  "@value" : "sum"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/order-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/order-v2d0-partial.json
new file mode 100644
index 0000000..4be0432
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/order-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Order",
+  "@value" : "shuffle"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/order-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/order-v3d0.json
new file mode 100644
index 0000000..4be0432
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/order-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Order",
+  "@value" : "shuffle"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/p-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/p-v2d0-partial.json
new file mode 100644
index 0000000..5bdfb3b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/p-v2d0-partial.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "gt",
+    "value" : {
+      "@type" : "g:Int32",
+      "@value" : 0
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/p-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/p-v3d0.json
new file mode 100644
index 0000000..5bdfb3b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/p-v3d0.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "gt",
+    "value" : {
+      "@type" : "g:Int32",
+      "@value" : 0
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pand-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pand-v2d0-partial.json
new file mode 100644
index 0000000..c271958
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pand-v2d0-partial.json
@@ -0,0 +1,25 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "and",
+    "value" : [ {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "gt",
+        "value" : {
+          "@type" : "g:Int32",
+          "@value" : 0
+        }
+      }
+    }, {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "lt",
+        "value" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        }
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pand-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pand-v3d0.json
new file mode 100644
index 0000000..c271958
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pand-v3d0.json
@@ -0,0 +1,25 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "and",
+    "value" : [ {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "gt",
+        "value" : {
+          "@type" : "g:Int32",
+          "@value" : 0
+        }
+      }
+    }, {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "lt",
+        "value" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        }
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v1d0.json
new file mode 100644
index 0000000..2eee883
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v1d0.json
@@ -0,0 +1,62 @@
+{
+  "labels" : [ [ ], [ ], [ ] ],
+  "objects" : [ {
+    "id" : 1,
+    "label" : "person",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 0,
+        "value" : "marko"
+      } ],
+      "location" : [ {
+        "id" : 6,
+        "value" : "san diego",
+        "properties" : {
+          "startTime" : 1997,
+          "endTime" : 2001
+        }
+      }, {
+        "id" : 7,
+        "value" : "santa cruz",
+        "properties" : {
+          "startTime" : 2001,
+          "endTime" : 2004
+        }
+      }, {
+        "id" : 8,
+        "value" : "brussels",
+        "properties" : {
+          "startTime" : 2004,
+          "endTime" : 2005
+        }
+      }, {
+        "id" : 9,
+        "value" : "santa fe",
+        "properties" : {
+          "startTime" : 2005
+        }
+      } ]
+    }
+  }, {
+    "id" : 10,
+    "label" : "software",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 4,
+        "value" : "gremlin"
+      } ]
+    }
+  }, {
+    "id" : 11,
+    "label" : "software",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 5,
+        "value" : "tinkergraph"
+      } ]
+    }
+  } ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v2d0-no-types.json
new file mode 100644
index 0000000..a592d2f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v2d0-no-types.json
@@ -0,0 +1,13 @@
+{
+  "labels" : [ [ ], [ ], [ ] ],
+  "objects" : [ {
+    "id" : 1,
+    "label" : "person"
+  }, {
+    "id" : 10,
+    "label" : "software"
+  }, {
+    "id" : 11,
+    "label" : "software"
+  } ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v2d0-partial.json
new file mode 100644
index 0000000..9ccaa00
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v2d0-partial.json
@@ -0,0 +1,34 @@
+{
+  "@type" : "g:Path",
+  "@value" : {
+    "labels" : [ [ ], [ ], [ ] ],
+    "objects" : [ {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "label" : "person"
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "label" : "software"
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "label" : "software"
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v3d0.json
new file mode 100644
index 0000000..216b393
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/path-v3d0.json
@@ -0,0 +1,49 @@
+{
+  "@type" : "g:Path",
+  "@value" : {
+    "labels" : {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Set",
+        "@value" : [ ]
+      }, {
+        "@type" : "g:Set",
+        "@value" : [ ]
+      }, {
+        "@type" : "g:Set",
+        "@value" : [ ]
+      } ]
+    },
+    "objects" : {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Vertex",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int32",
+            "@value" : 1
+          },
+          "label" : "person"
+        }
+      }, {
+        "@type" : "g:Vertex",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int32",
+            "@value" : 10
+          },
+          "label" : "software"
+        }
+      }, {
+        "@type" : "g:Vertex",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int32",
+            "@value" : 11
+          },
+          "label" : "software"
+        }
+      } ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/period-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/period-v2d0-partial.json
new file mode 100644
index 0000000..20438a1
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/period-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Period",
+  "@value" : "P1Y6M15D"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/period-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/period-v3d0.json
new file mode 100644
index 0000000..20438a1
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/period-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Period",
+  "@value" : "P1Y6M15D"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pick-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pick-v2d0-partial.json
new file mode 100644
index 0000000..3ca2f2e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pick-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Pick",
+  "@value" : "any"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pick-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pick-v3d0.json
new file mode 100644
index 0000000..3ca2f2e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pick-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Pick",
+  "@value" : "any"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pop-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pop-v2d0-partial.json
new file mode 100644
index 0000000..271515f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pop-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Pop",
+  "@value" : "all"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pop-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pop-v3d0.json
new file mode 100644
index 0000000..271515f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pop-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Pop",
+  "@value" : "all"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/por-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/por-v2d0-partial.json
new file mode 100644
index 0000000..71fcb7d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/por-v2d0-partial.json
@@ -0,0 +1,31 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "or",
+    "value" : [ {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "gt",
+        "value" : {
+          "@type" : "g:Int32",
+          "@value" : 0
+        }
+      }
+    }, {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "within",
+        "value" : [ {
+          "@type" : "g:Int32",
+          "@value" : -1
+        }, {
+          "@type" : "g:Int32",
+          "@value" : -10
+        }, {
+          "@type" : "g:Int32",
+          "@value" : -100
+        } ]
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/por-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/por-v3d0.json
new file mode 100644
index 0000000..a71b1cf
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/por-v3d0.json
@@ -0,0 +1,34 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "or",
+    "value" : [ {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "gt",
+        "value" : {
+          "@type" : "g:Int32",
+          "@value" : 0
+        }
+      }
+    }, {
+      "@type" : "g:P",
+      "@value" : {
+        "predicate" : "within",
+        "value" : {
+          "@type" : "g:List",
+          "@value" : [ {
+            "@type" : "g:Int32",
+            "@value" : -1
+          }, {
+            "@type" : "g:Int32",
+            "@value" : -10
+          }, {
+            "@type" : "g:Int32",
+            "@value" : -100
+          } ]
+        }
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v1d0.json
new file mode 100644
index 0000000..c051c0a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v1d0.json
@@ -0,0 +1,4 @@
+{
+  "key" : "since",
+  "value" : 2009
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v2d0-no-types.json
new file mode 100644
index 0000000..c051c0a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v2d0-no-types.json
@@ -0,0 +1,4 @@
+{
+  "key" : "since",
+  "value" : 2009
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v2d0-partial.json
new file mode 100644
index 0000000..296fe32
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v2d0-partial.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:Property",
+  "@value" : {
+    "key" : "since",
+    "value" : {
+      "@type" : "g:Int32",
+      "@value" : 2009
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v3d0.json
new file mode 100644
index 0000000..296fe32
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/property-v3d0.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:Property",
+  "@value" : {
+    "key" : "since",
+    "value" : {
+      "@type" : "g:Int32",
+      "@value" : 2009
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithin-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithin-v2d0-partial.json
new file mode 100644
index 0000000..afa3826
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithin-v2d0-partial.json
@@ -0,0 +1,10 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "within",
+    "value" : [ {
+      "@type" : "g:Int32",
+      "@value" : 1
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithin-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithin-v3d0.json
new file mode 100644
index 0000000..83f99cc
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithin-v3d0.json
@@ -0,0 +1,13 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "within",
+    "value" : {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Int32",
+        "@value" : 1
+      } ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithout-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithout-v2d0-partial.json
new file mode 100644
index 0000000..8c2291b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithout-v2d0-partial.json
@@ -0,0 +1,13 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "without",
+    "value" : [ {
+      "@type" : "g:Int32",
+      "@value" : 1
+    }, {
+      "@type" : "g:Int32",
+      "@value" : 2
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithout-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithout-v3d0.json
new file mode 100644
index 0000000..9a16890
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/pwithout-v3d0.json
@@ -0,0 +1,16 @@
+{
+  "@type" : "g:P",
+  "@value" : {
+    "predicate" : "without",
+    "value" : {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Int32",
+        "@value" : 1
+      }, {
+        "@type" : "g:Int32",
+        "@value" : 2
+      } ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/scope-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/scope-v2d0-partial.json
new file mode 100644
index 0000000..4a74af0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/scope-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Scope",
+  "@value" : "local"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/scope-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/scope-v3d0.json
new file mode 100644
index 0000000..4a74af0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/scope-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Scope",
+  "@value" : "local"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v1d0.json
new file mode 100644
index 0000000..ac825e8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v1d0.json
@@ -0,0 +1,8 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "close",
+  "processor" : "session",
+  "args" : {
+    "session" : "unique-session-identifier"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v2d0-no-types.json
new file mode 100644
index 0000000..ac825e8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v2d0-no-types.json
@@ -0,0 +1,8 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "close",
+  "processor" : "session",
+  "args" : {
+    "session" : "unique-session-identifier"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v2d0-partial.json
new file mode 100644
index 0000000..ac825e8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v2d0-partial.json
@@ -0,0 +1,8 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "close",
+  "processor" : "session",
+  "args" : {
+    "session" : "unique-session-identifier"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v3d0.json
new file mode 100644
index 0000000..4be1ccd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionclose-v3d0.json
@@ -0,0 +1,9 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "close",
+  "processor" : "session",
+  "args" : {
+    "@type" : "g:Map",
+    "@value" : [ "session", "unique-session-identifier" ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v1d0.json
new file mode 100644
index 0000000..8bce82f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v1d0.json
@@ -0,0 +1,13 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "gremlin" : "g.V(x)",
+    "language" : "gremlin-groovy",
+    "session" : "unique-session-identifier",
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v2d0-no-types.json
new file mode 100644
index 0000000..8bce82f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v2d0-no-types.json
@@ -0,0 +1,13 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "gremlin" : "g.V(x)",
+    "language" : "gremlin-groovy",
+    "session" : "unique-session-identifier",
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v2d0-partial.json
new file mode 100644
index 0000000..8ff8b96
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v2d0-partial.json
@@ -0,0 +1,16 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "gremlin" : "g.V(x)",
+    "language" : "gremlin-groovy",
+    "session" : "unique-session-identifier",
+    "bindings" : {
+      "x" : {
+        "@type" : "g:Int32",
+        "@value" : 1
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v3d0.json
new file mode 100644
index 0000000..301c393
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessioneval-v3d0.json
@@ -0,0 +1,15 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "@type" : "g:Map",
+    "@value" : [ "gremlin", "g.V(x)", "language", "gremlin-groovy", "session", "unique-session-identifier", "bindings", {
+      "@type" : "g:Map",
+      "@value" : [ "x", {
+        "@type" : "g:Int32",
+        "@value" : 1
+      } ]
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v1d0.json
new file mode 100644
index 0000000..5f4ef46
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v1d0.json
@@ -0,0 +1,16 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "gremlin" : "social.V(x)",
+    "language" : "gremlin-groovy",
+    "aliases" : {
+      "g" : "social"
+    },
+    "session" : "unique-session-identifier",
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v2d0-no-types.json
new file mode 100644
index 0000000..5f4ef46
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v2d0-no-types.json
@@ -0,0 +1,16 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "gremlin" : "social.V(x)",
+    "language" : "gremlin-groovy",
+    "aliases" : {
+      "g" : "social"
+    },
+    "session" : "unique-session-identifier",
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v2d0-partial.json
new file mode 100644
index 0000000..394e5d3
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v2d0-partial.json
@@ -0,0 +1,19 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "gremlin" : "social.V(x)",
+    "language" : "gremlin-groovy",
+    "aliases" : {
+      "g" : "social"
+    },
+    "session" : "unique-session-identifier",
+    "bindings" : {
+      "x" : {
+        "@type" : "g:Int32",
+        "@value" : 1
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v3d0.json
new file mode 100644
index 0000000..7448160
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionevalaliased-v3d0.json
@@ -0,0 +1,18 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "session",
+  "args" : {
+    "@type" : "g:Map",
+    "@value" : [ "gremlin", "social.V(x)", "language", "gremlin-groovy", "aliases", {
+      "@type" : "g:Map",
+      "@value" : [ "g", "social" ]
+    }, "session", "unique-session-identifier", "bindings", {
+      "@type" : "g:Map",
+      "@value" : [ "x", {
+        "@type" : "g:Int32",
+        "@value" : 1
+      } ]
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v1d0.json
new file mode 100644
index 0000000..8c9a807
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v1d0.json
@@ -0,0 +1,12 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "gremlin" : "g.V(x)",
+    "language" : "gremlin-groovy",
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v2d0-no-types.json
new file mode 100644
index 0000000..8c9a807
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v2d0-no-types.json
@@ -0,0 +1,12 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "gremlin" : "g.V(x)",
+    "language" : "gremlin-groovy",
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v2d0-partial.json
new file mode 100644
index 0000000..81e2f6c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v2d0-partial.json
@@ -0,0 +1,15 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "gremlin" : "g.V(x)",
+    "language" : "gremlin-groovy",
+    "bindings" : {
+      "x" : {
+        "@type" : "g:Int32",
+        "@value" : 1
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v3d0.json
new file mode 100644
index 0000000..dc8c8e6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlesseval-v3d0.json
@@ -0,0 +1,15 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "@type" : "g:Map",
+    "@value" : [ "gremlin", "g.V(x)", "language", "gremlin-groovy", "bindings", {
+      "@type" : "g:Map",
+      "@value" : [ "x", {
+        "@type" : "g:Int32",
+        "@value" : 1
+      } ]
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v1d0.json
new file mode 100644
index 0000000..59f0c6c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v1d0.json
@@ -0,0 +1,15 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "gremlin" : "social.V(x)",
+    "language" : "gremlin-groovy",
+    "aliases" : {
+      "g" : "social"
+    },
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v2d0-no-types.json
new file mode 100644
index 0000000..59f0c6c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v2d0-no-types.json
@@ -0,0 +1,15 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "gremlin" : "social.V(x)",
+    "language" : "gremlin-groovy",
+    "aliases" : {
+      "g" : "social"
+    },
+    "bindings" : {
+      "x" : 1
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v2d0-partial.json
new file mode 100644
index 0000000..0f6a54e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v2d0-partial.json
@@ -0,0 +1,18 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "gremlin" : "social.V(x)",
+    "language" : "gremlin-groovy",
+    "aliases" : {
+      "g" : "social"
+    },
+    "bindings" : {
+      "x" : {
+        "@type" : "g:Int32",
+        "@value" : 1
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v3d0.json
new file mode 100644
index 0000000..fc03a37
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/sessionlessevalaliased-v3d0.json
@@ -0,0 +1,18 @@
+{
+  "requestId" : "cb682578-9d92-4499-9ebc-5c6aa73c5397",
+  "op" : "eval",
+  "processor" : "",
+  "args" : {
+    "@type" : "g:Map",
+    "@value" : [ "gremlin", "social.V(x)", "language", "gremlin-groovy", "aliases", {
+      "@type" : "g:Map",
+      "@value" : [ "g", "social" ]
+    }, "bindings", {
+      "@type" : "g:Map",
+      "@value" : [ "x", {
+        "@type" : "g:Int32",
+        "@value" : 1
+      } ]
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/set-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/set-v3d0.json
new file mode 100644
index 0000000..32deea2
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/set-v3d0.json
@@ -0,0 +1,7 @@
+{
+  "@type" : "g:Set",
+  "@value" : [ {
+    "@type" : "g:Int32",
+    "@value" : 1
+  }, "person", true ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/short-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/short-v2d0-partial.json
new file mode 100644
index 0000000..c68f5cd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/short-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Int16",
+  "@value" : 100
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/short-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/short-v3d0.json
new file mode 100644
index 0000000..c68f5cd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/short-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Int16",
+  "@value" : 100
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v1d0.json
new file mode 100644
index 0000000..9b93727
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v1d0.json
@@ -0,0 +1,50 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 200,
+    "attributes" : { }
+  },
+  "result" : {
+    "data" : [ {
+      "id" : 1,
+      "label" : "person",
+      "type" : "vertex",
+      "properties" : {
+        "name" : [ {
+          "id" : 0,
+          "value" : "marko"
+        } ],
+        "location" : [ {
+          "id" : 6,
+          "value" : "san diego",
+          "properties" : {
+            "startTime" : 1997,
+            "endTime" : 2001
+          }
+        }, {
+          "id" : 7,
+          "value" : "santa cruz",
+          "properties" : {
+            "startTime" : 2001,
+            "endTime" : 2004
+          }
+        }, {
+          "id" : 8,
+          "value" : "brussels",
+          "properties" : {
+            "startTime" : 2004,
+            "endTime" : 2005
+          }
+        }, {
+          "id" : 9,
+          "value" : "santa fe",
+          "properties" : {
+            "startTime" : 2005
+          }
+        } ]
+      }
+    } ],
+    "meta" : { }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v2d0-partial.json
new file mode 100644
index 0000000..857c6db
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v2d0-partial.json
@@ -0,0 +1,111 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 200,
+    "attributes" : { }
+  },
+  "result" : {
+    "data" : [ {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 0
+              },
+              "value" : "marko",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 6
+              },
+              "value" : "san diego",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1997
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 7
+              },
+              "value" : "santa cruz",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 8
+              },
+              "value" : "brussels",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 9
+              },
+              "value" : "santa fe",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          } ]
+        }
+      }
+    } ],
+    "meta" : { }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v3d0.json
new file mode 100644
index 0000000..dfca400
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/standardresult-v3d0.json
@@ -0,0 +1,120 @@
+{
+  "requestId" : "41d2e28a-20a4-4ab0-b379-d810dede3786",
+  "status" : {
+    "message" : "",
+    "code" : 200,
+    "attributes" : {
+      "@type" : "g:Map",
+      "@value" : [ ]
+    }
+  },
+  "result" : {
+    "data" : {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Vertex",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int32",
+            "@value" : 1
+          },
+          "label" : "person",
+          "properties" : {
+            "name" : [ {
+              "@type" : "g:VertexProperty",
+              "@value" : {
+                "id" : {
+                  "@type" : "g:Int64",
+                  "@value" : 0
+                },
+                "value" : "marko",
+                "label" : "name"
+              }
+            } ],
+            "location" : [ {
+              "@type" : "g:VertexProperty",
+              "@value" : {
+                "id" : {
+                  "@type" : "g:Int64",
+                  "@value" : 6
+                },
+                "value" : "san diego",
+                "label" : "location",
+                "properties" : {
+                  "startTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 1997
+                  },
+                  "endTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 2001
+                  }
+                }
+              }
+            }, {
+              "@type" : "g:VertexProperty",
+              "@value" : {
+                "id" : {
+                  "@type" : "g:Int64",
+                  "@value" : 7
+                },
+                "value" : "santa cruz",
+                "label" : "location",
+                "properties" : {
+                  "startTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 2001
+                  },
+                  "endTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 2004
+                  }
+                }
+              }
+            }, {
+              "@type" : "g:VertexProperty",
+              "@value" : {
+                "id" : {
+                  "@type" : "g:Int64",
+                  "@value" : 8
+                },
+                "value" : "brussels",
+                "label" : "location",
+                "properties" : {
+                  "startTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 2004
+                  },
+                  "endTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 2005
+                  }
+                }
+              }
+            }, {
+              "@type" : "g:VertexProperty",
+              "@value" : {
+                "id" : {
+                  "@type" : "g:Int64",
+                  "@value" : 9
+                },
+                "value" : "santa fe",
+                "label" : "location",
+                "properties" : {
+                  "startTime" : {
+                    "@type" : "g:Int32",
+                    "@value" : 2005
+                  }
+                }
+              }
+            } ]
+          }
+        }
+      } ]
+    },
+    "meta" : {
+      "@type" : "g:Map",
+      "@value" : [ ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/t-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/t-v2d0-partial.json
new file mode 100644
index 0000000..9693983
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/t-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:T",
+  "@value" : "label"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/t-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/t-v3d0.json
new file mode 100644
index 0000000..9693983
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/t-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:T",
+  "@value" : "label"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/textp-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/textp-v2d0-partial.json
new file mode 100644
index 0000000..2820989
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/textp-v2d0-partial.json
@@ -0,0 +1,7 @@
+{
+  "@type" : "g:TextP",
+  "@value" : {
+    "predicate" : "containing",
+    "value" : "ark"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/textp-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/textp-v3d0.json
new file mode 100644
index 0000000..2820989
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/textp-v3d0.json
@@ -0,0 +1,7 @@
+{
+  "@type" : "g:TextP",
+  "@value" : {
+    "predicate" : "containing",
+    "value" : "ark"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/timestamp-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/timestamp-v2d0-partial.json
new file mode 100644
index 0000000..1ca0e17
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/timestamp-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Timestamp",
+  "@value" : 1481750076295
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/timestamp-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/timestamp-v3d0.json
new file mode 100644
index 0000000..1ca0e17
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/timestamp-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:Timestamp",
+  "@value" : 1481750076295
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v1d0.json
new file mode 100644
index 0000000..13719f6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v1d0.json
@@ -0,0 +1,313 @@
+{
+  "vertices" : [ {
+    "id" : 1,
+    "label" : "person",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 0,
+        "value" : "marko"
+      } ],
+      "location" : [ {
+        "id" : 6,
+        "value" : "san diego",
+        "properties" : {
+          "startTime" : 1997,
+          "endTime" : 2001
+        }
+      }, {
+        "id" : 7,
+        "value" : "santa cruz",
+        "properties" : {
+          "startTime" : 2001,
+          "endTime" : 2004
+        }
+      }, {
+        "id" : 8,
+        "value" : "brussels",
+        "properties" : {
+          "startTime" : 2004,
+          "endTime" : 2005
+        }
+      }, {
+        "id" : 9,
+        "value" : "santa fe",
+        "properties" : {
+          "startTime" : 2005
+        }
+      } ]
+    }
+  }, {
+    "id" : 7,
+    "label" : "person",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 1,
+        "value" : "stephen"
+      } ],
+      "location" : [ {
+        "id" : 10,
+        "value" : "centreville",
+        "properties" : {
+          "startTime" : 1990,
+          "endTime" : 2000
+        }
+      }, {
+        "id" : 11,
+        "value" : "dulles",
+        "properties" : {
+          "startTime" : 2000,
+          "endTime" : 2006
+        }
+      }, {
+        "id" : 12,
+        "value" : "purcellville",
+        "properties" : {
+          "startTime" : 2006
+        }
+      } ]
+    }
+  }, {
+    "id" : 8,
+    "label" : "person",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 2,
+        "value" : "matthias"
+      } ],
+      "location" : [ {
+        "id" : 13,
+        "value" : "bremen",
+        "properties" : {
+          "startTime" : 2004,
+          "endTime" : 2007
+        }
+      }, {
+        "id" : 14,
+        "value" : "baltimore",
+        "properties" : {
+          "startTime" : 2007,
+          "endTime" : 2011
+        }
+      }, {
+        "id" : 15,
+        "value" : "oakland",
+        "properties" : {
+          "startTime" : 2011,
+          "endTime" : 2014
+        }
+      }, {
+        "id" : 16,
+        "value" : "seattle",
+        "properties" : {
+          "startTime" : 2014
+        }
+      } ]
+    }
+  }, {
+    "id" : 9,
+    "label" : "person",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 3,
+        "value" : "daniel"
+      } ],
+      "location" : [ {
+        "id" : 17,
+        "value" : "spremberg",
+        "properties" : {
+          "startTime" : 1982,
+          "endTime" : 2005
+        }
+      }, {
+        "id" : 18,
+        "value" : "kaiserslautern",
+        "properties" : {
+          "startTime" : 2005,
+          "endTime" : 2009
+        }
+      }, {
+        "id" : 19,
+        "value" : "aachen",
+        "properties" : {
+          "startTime" : 2009
+        }
+      } ]
+    }
+  }, {
+    "id" : 10,
+    "label" : "software",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 4,
+        "value" : "gremlin"
+      } ]
+    }
+  }, {
+    "id" : 11,
+    "label" : "software",
+    "type" : "vertex",
+    "properties" : {
+      "name" : [ {
+        "id" : 5,
+        "value" : "tinkergraph"
+      } ]
+    }
+  } ],
+  "edges" : [ {
+    "id" : 13,
+    "label" : "develops",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 1,
+    "properties" : {
+      "since" : 2009
+    }
+  }, {
+    "id" : 14,
+    "label" : "develops",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 1,
+    "properties" : {
+      "since" : 2010
+    }
+  }, {
+    "id" : 15,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 1,
+    "properties" : {
+      "skill" : 4
+    }
+  }, {
+    "id" : 16,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 1,
+    "properties" : {
+      "skill" : 5
+    }
+  }, {
+    "id" : 17,
+    "label" : "develops",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 7,
+    "properties" : {
+      "since" : 2010
+    }
+  }, {
+    "id" : 18,
+    "label" : "develops",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 7,
+    "properties" : {
+      "since" : 2011
+    }
+  }, {
+    "id" : 19,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 7,
+    "properties" : {
+      "skill" : 5
+    }
+  }, {
+    "id" : 20,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 7,
+    "properties" : {
+      "skill" : 4
+    }
+  }, {
+    "id" : 21,
+    "label" : "develops",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 8,
+    "properties" : {
+      "since" : 2012
+    }
+  }, {
+    "id" : 22,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 8,
+    "properties" : {
+      "skill" : 3
+    }
+  }, {
+    "id" : 23,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 8,
+    "properties" : {
+      "skill" : 3
+    }
+  }, {
+    "id" : 24,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 9,
+    "properties" : {
+      "skill" : 5
+    }
+  }, {
+    "id" : 25,
+    "label" : "uses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 9,
+    "properties" : {
+      "skill" : 3
+    }
+  }, {
+    "id" : 26,
+    "label" : "traverses",
+    "type" : "edge",
+    "inVLabel" : "software",
+    "outVLabel" : "software",
+    "inV" : 11,
+    "outV" : 10
+  } ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v2d0-no-types.json
new file mode 100644
index 0000000..94ad061
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v2d0-no-types.json
@@ -0,0 +1,352 @@
+{
+  "vertices" : [ {
+    "id" : 1,
+    "label" : "person",
+    "properties" : {
+      "name" : [ {
+        "id" : 0,
+        "value" : "marko",
+        "label" : "name"
+      } ],
+      "location" : [ {
+        "id" : 6,
+        "value" : "san diego",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 1997,
+          "endTime" : 2001
+        }
+      }, {
+        "id" : 7,
+        "value" : "santa cruz",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2001,
+          "endTime" : 2004
+        }
+      }, {
+        "id" : 8,
+        "value" : "brussels",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2004,
+          "endTime" : 2005
+        }
+      }, {
+        "id" : 9,
+        "value" : "santa fe",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2005
+        }
+      } ]
+    }
+  }, {
+    "id" : 7,
+    "label" : "person",
+    "properties" : {
+      "name" : [ {
+        "id" : 1,
+        "value" : "stephen",
+        "label" : "name"
+      } ],
+      "location" : [ {
+        "id" : 10,
+        "value" : "centreville",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 1990,
+          "endTime" : 2000
+        }
+      }, {
+        "id" : 11,
+        "value" : "dulles",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2000,
+          "endTime" : 2006
+        }
+      }, {
+        "id" : 12,
+        "value" : "purcellville",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2006
+        }
+      } ]
+    }
+  }, {
+    "id" : 8,
+    "label" : "person",
+    "properties" : {
+      "name" : [ {
+        "id" : 2,
+        "value" : "matthias",
+        "label" : "name"
+      } ],
+      "location" : [ {
+        "id" : 13,
+        "value" : "bremen",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2004,
+          "endTime" : 2007
+        }
+      }, {
+        "id" : 14,
+        "value" : "baltimore",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2007,
+          "endTime" : 2011
+        }
+      }, {
+        "id" : 15,
+        "value" : "oakland",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2011,
+          "endTime" : 2014
+        }
+      }, {
+        "id" : 16,
+        "value" : "seattle",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2014
+        }
+      } ]
+    }
+  }, {
+    "id" : 9,
+    "label" : "person",
+    "properties" : {
+      "name" : [ {
+        "id" : 3,
+        "value" : "daniel",
+        "label" : "name"
+      } ],
+      "location" : [ {
+        "id" : 17,
+        "value" : "spremberg",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 1982,
+          "endTime" : 2005
+        }
+      }, {
+        "id" : 18,
+        "value" : "kaiserslautern",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2005,
+          "endTime" : 2009
+        }
+      }, {
+        "id" : 19,
+        "value" : "aachen",
+        "label" : "location",
+        "properties" : {
+          "startTime" : 2009
+        }
+      } ]
+    }
+  }, {
+    "id" : 10,
+    "label" : "software",
+    "properties" : {
+      "name" : [ {
+        "id" : 4,
+        "value" : "gremlin",
+        "label" : "name"
+      } ]
+    }
+  }, {
+    "id" : 11,
+    "label" : "software",
+    "properties" : {
+      "name" : [ {
+        "id" : 5,
+        "value" : "tinkergraph",
+        "label" : "name"
+      } ]
+    }
+  } ],
+  "edges" : [ {
+    "id" : 13,
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 1,
+    "properties" : {
+      "since" : {
+        "key" : "since",
+        "value" : 2009
+      }
+    }
+  }, {
+    "id" : 14,
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 1,
+    "properties" : {
+      "since" : {
+        "key" : "since",
+        "value" : 2010
+      }
+    }
+  }, {
+    "id" : 15,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 1,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 4
+      }
+    }
+  }, {
+    "id" : 16,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 1,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 5
+      }
+    }
+  }, {
+    "id" : 17,
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 7,
+    "properties" : {
+      "since" : {
+        "key" : "since",
+        "value" : 2010
+      }
+    }
+  }, {
+    "id" : 18,
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 7,
+    "properties" : {
+      "since" : {
+        "key" : "since",
+        "value" : 2011
+      }
+    }
+  }, {
+    "id" : 19,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 7,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 5
+      }
+    }
+  }, {
+    "id" : 20,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 7,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 4
+      }
+    }
+  }, {
+    "id" : 21,
+    "label" : "develops",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 8,
+    "properties" : {
+      "since" : {
+        "key" : "since",
+        "value" : 2012
+      }
+    }
+  }, {
+    "id" : 22,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 8,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 3
+      }
+    }
+  }, {
+    "id" : 23,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 8,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 3
+      }
+    }
+  }, {
+    "id" : 24,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 10,
+    "outV" : 9,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 5
+      }
+    }
+  }, {
+    "id" : 25,
+    "label" : "uses",
+    "inVLabel" : "software",
+    "outVLabel" : "person",
+    "inV" : 11,
+    "outV" : 9,
+    "properties" : {
+      "skill" : {
+        "key" : "skill",
+        "value" : 3
+      }
+    }
+  }, {
+    "id" : 26,
+    "label" : "traverses",
+    "inVLabel" : "software",
+    "outVLabel" : "software",
+    "inV" : 11,
+    "outV" : 10
+  } ]
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v2d0-partial.json
new file mode 100644
index 0000000..24e95ed
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v2d0-partial.json
@@ -0,0 +1,829 @@
+{
+  "@type" : "tinker:graph",
+  "@value" : {
+    "vertices" : [ {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 0
+              },
+              "value" : "marko",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 6
+              },
+              "value" : "san diego",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1997
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 7
+              },
+              "value" : "santa cruz",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 8
+              },
+              "value" : "brussels",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 9
+              },
+              "value" : "santa fe",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 1
+              },
+              "value" : "stephen",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 10
+              },
+              "value" : "centreville",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1990
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2000
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 11
+              },
+              "value" : "dulles",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2000
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2006
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 12
+              },
+              "value" : "purcellville",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2006
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 2
+              },
+              "value" : "matthias",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 13
+              },
+              "value" : "bremen",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2007
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 14
+              },
+              "value" : "baltimore",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2007
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2011
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 15
+              },
+              "value" : "oakland",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2011
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2014
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 16
+              },
+              "value" : "seattle",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2014
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 9
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 3
+              },
+              "value" : "daniel",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 17
+              },
+              "value" : "spremberg",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1982
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 18
+              },
+              "value" : "kaiserslautern",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2009
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 19
+              },
+              "value" : "aachen",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2009
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "label" : "software",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 4
+              },
+              "value" : "gremlin",
+              "label" : "name"
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "label" : "software",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 5
+              },
+              "value" : "tinkergraph",
+              "label" : "name"
+            }
+          } ]
+        }
+      }
+    } ],
+    "edges" : [ {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 13
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2009
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 14
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2010
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 15
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 4
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 16
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 5
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 17
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2010
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 18
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2011
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 19
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 5
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 20
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 4
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 21
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2012
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 22
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 3
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 23
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 3
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 24
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 9
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 5
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 25
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 9
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 3
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 26
+        },
+        "label" : "traverses",
+        "inVLabel" : "software",
+        "outVLabel" : "software",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        }
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v3d0.json
new file mode 100644
index 0000000..24e95ed
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/tinkergraph-v3d0.json
@@ -0,0 +1,829 @@
+{
+  "@type" : "tinker:graph",
+  "@value" : {
+    "vertices" : [ {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 0
+              },
+              "value" : "marko",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 6
+              },
+              "value" : "san diego",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1997
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 7
+              },
+              "value" : "santa cruz",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 8
+              },
+              "value" : "brussels",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 9
+              },
+              "value" : "santa fe",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 1
+              },
+              "value" : "stephen",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 10
+              },
+              "value" : "centreville",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1990
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2000
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 11
+              },
+              "value" : "dulles",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2000
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2006
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 12
+              },
+              "value" : "purcellville",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2006
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 2
+              },
+              "value" : "matthias",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 13
+              },
+              "value" : "bremen",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2007
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 14
+              },
+              "value" : "baltimore",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2007
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2011
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 15
+              },
+              "value" : "oakland",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2011
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2014
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 16
+              },
+              "value" : "seattle",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2014
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 9
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 3
+              },
+              "value" : "daniel",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 17
+              },
+              "value" : "spremberg",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1982
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 18
+              },
+              "value" : "kaiserslautern",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2009
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 19
+              },
+              "value" : "aachen",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2009
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "label" : "software",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 4
+              },
+              "value" : "gremlin",
+              "label" : "name"
+            }
+          } ]
+        }
+      }
+    }, {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "label" : "software",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 5
+              },
+              "value" : "tinkergraph",
+              "label" : "name"
+            }
+          } ]
+        }
+      }
+    } ],
+    "edges" : [ {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 13
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2009
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 14
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2010
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 15
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 4
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 16
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 5
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 17
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2010
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 18
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2011
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 19
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 5
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 20
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 7
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 4
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 21
+        },
+        "label" : "develops",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "properties" : {
+          "since" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "since",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 2012
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 22
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 3
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 23
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 8
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 3
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 24
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 9
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 5
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 25
+        },
+        "label" : "uses",
+        "inVLabel" : "software",
+        "outVLabel" : "person",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 9
+        },
+        "properties" : {
+          "skill" : {
+            "@type" : "g:Property",
+            "@value" : {
+              "key" : "skill",
+              "value" : {
+                "@type" : "g:Int32",
+                "@value" : 3
+              }
+            }
+          }
+        }
+      }
+    }, {
+      "@type" : "g:Edge",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 26
+        },
+        "label" : "traverses",
+        "inVLabel" : "software",
+        "outVLabel" : "software",
+        "inV" : {
+          "@type" : "g:Int32",
+          "@value" : 11
+        },
+        "outV" : {
+          "@type" : "g:Int32",
+          "@value" : 10
+        }
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traversalmetrics-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traversalmetrics-v2d0-partial.json
new file mode 100644
index 0000000..fdd18a4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traversalmetrics-v2d0-partial.json
@@ -0,0 +1,114 @@
+{
+  "@type" : "g:TraversalMetrics",
+  "@value" : {
+    "dur" : {
+      "@type" : "g:Double",
+      "@value" : 0.004
+    },
+    "metrics" : [ {
+      "@type" : "g:Metrics",
+      "@value" : {
+        "dur" : {
+          "@type" : "g:Double",
+          "@value" : 100.0
+        },
+        "counts" : {
+          "traverserCount" : {
+            "@type" : "g:Int64",
+            "@value" : 4
+          },
+          "elementCount" : {
+            "@type" : "g:Int64",
+            "@value" : 4
+          }
+        },
+        "name" : "TinkerGraphStep(vertex,[~label.eq(person)])",
+        "annotations" : {
+          "percentDur" : {
+            "@type" : "g:Double",
+            "@value" : 25.0
+          }
+        },
+        "id" : "7.0.0()"
+      }
+    }, {
+      "@type" : "g:Metrics",
+      "@value" : {
+        "dur" : {
+          "@type" : "g:Double",
+          "@value" : 100.0
+        },
+        "counts" : {
+          "traverserCount" : {
+            "@type" : "g:Int64",
+            "@value" : 13
+          },
+          "elementCount" : {
+            "@type" : "g:Int64",
+            "@value" : 13
+          }
+        },
+        "name" : "VertexStep(OUT,vertex)",
+        "annotations" : {
+          "percentDur" : {
+            "@type" : "g:Double",
+            "@value" : 25.0
+          }
+        },
+        "id" : "2.0.0()"
+      }
+    }, {
+      "@type" : "g:Metrics",
+      "@value" : {
+        "dur" : {
+          "@type" : "g:Double",
+          "@value" : 100.0
+        },
+        "counts" : {
+          "traverserCount" : {
+            "@type" : "g:Int64",
+            "@value" : 7
+          },
+          "elementCount" : {
+            "@type" : "g:Int64",
+            "@value" : 7
+          }
+        },
+        "name" : "VertexStep(OUT,vertex)",
+        "annotations" : {
+          "percentDur" : {
+            "@type" : "g:Double",
+            "@value" : 25.0
+          }
+        },
+        "id" : "3.0.0()"
+      }
+    }, {
+      "@type" : "g:Metrics",
+      "@value" : {
+        "dur" : {
+          "@type" : "g:Double",
+          "@value" : 100.0
+        },
+        "counts" : {
+          "traverserCount" : {
+            "@type" : "g:Int64",
+            "@value" : 1
+          },
+          "elementCount" : {
+            "@type" : "g:Int64",
+            "@value" : 1
+          }
+        },
+        "name" : "TreeStep",
+        "annotations" : {
+          "percentDur" : {
+            "@type" : "g:Double",
+            "@value" : 25.0
+          }
+        },
+        "id" : "4.0.0()"
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traversalmetrics-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traversalmetrics-v3d0.json
new file mode 100644
index 0000000..46f7636
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traversalmetrics-v3d0.json
@@ -0,0 +1,109 @@
+{
+  "@type" : "g:TraversalMetrics",
+  "@value" : {
+    "@type" : "g:Map",
+    "@value" : [ "dur", {
+      "@type" : "g:Double",
+      "@value" : 0.004
+    }, "metrics", {
+      "@type" : "g:List",
+      "@value" : [ {
+        "@type" : "g:Metrics",
+        "@value" : {
+          "@type" : "g:Map",
+          "@value" : [ "dur", {
+            "@type" : "g:Double",
+            "@value" : 100.0
+          }, "counts", {
+            "@type" : "g:Map",
+            "@value" : [ "traverserCount", {
+              "@type" : "g:Int64",
+              "@value" : 4
+            }, "elementCount", {
+              "@type" : "g:Int64",
+              "@value" : 4
+            } ]
+          }, "name", "TinkerGraphStep(vertex,[~label.eq(person)])", "annotations", {
+            "@type" : "g:Map",
+            "@value" : [ "percentDur", {
+              "@type" : "g:Double",
+              "@value" : 25.0
+            } ]
+          }, "id", "7.0.0()" ]
+        }
+      }, {
+        "@type" : "g:Metrics",
+        "@value" : {
+          "@type" : "g:Map",
+          "@value" : [ "dur", {
+            "@type" : "g:Double",
+            "@value" : 100.0
+          }, "counts", {
+            "@type" : "g:Map",
+            "@value" : [ "traverserCount", {
+              "@type" : "g:Int64",
+              "@value" : 13
+            }, "elementCount", {
+              "@type" : "g:Int64",
+              "@value" : 13
+            } ]
+          }, "name", "VertexStep(OUT,vertex)", "annotations", {
+            "@type" : "g:Map",
+            "@value" : [ "percentDur", {
+              "@type" : "g:Double",
+              "@value" : 25.0
+            } ]
+          }, "id", "2.0.0()" ]
+        }
+      }, {
+        "@type" : "g:Metrics",
+        "@value" : {
+          "@type" : "g:Map",
+          "@value" : [ "dur", {
+            "@type" : "g:Double",
+            "@value" : 100.0
+          }, "counts", {
+            "@type" : "g:Map",
+            "@value" : [ "traverserCount", {
+              "@type" : "g:Int64",
+              "@value" : 7
+            }, "elementCount", {
+              "@type" : "g:Int64",
+              "@value" : 7
+            } ]
+          }, "name", "VertexStep(OUT,vertex)", "annotations", {
+            "@type" : "g:Map",
+            "@value" : [ "percentDur", {
+              "@type" : "g:Double",
+              "@value" : 25.0
+            } ]
+          }, "id", "3.0.0()" ]
+        }
+      }, {
+        "@type" : "g:Metrics",
+        "@value" : {
+          "@type" : "g:Map",
+          "@value" : [ "dur", {
+            "@type" : "g:Double",
+            "@value" : 100.0
+          }, "counts", {
+            "@type" : "g:Map",
+            "@value" : [ "traverserCount", {
+              "@type" : "g:Int64",
+              "@value" : 1
+            }, "elementCount", {
+              "@type" : "g:Int64",
+              "@value" : 1
+            } ]
+          }, "name", "TreeStep", "annotations", {
+            "@type" : "g:Map",
+            "@value" : [ "percentDur", {
+              "@type" : "g:Double",
+              "@value" : 25.0
+            } ]
+          }, "id", "4.0.0()" ]
+        }
+      } ]
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traverser-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traverser-v2d0-partial.json
new file mode 100644
index 0000000..a59a29e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traverser-v2d0-partial.json
@@ -0,0 +1,109 @@
+{
+  "@type" : "g:Traverser",
+  "@value" : {
+    "bulk" : {
+      "@type" : "g:Int64",
+      "@value" : 1
+    },
+    "value" : {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 0
+              },
+              "value" : "marko",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 6
+              },
+              "value" : "san diego",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1997
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 7
+              },
+              "value" : "santa cruz",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 8
+              },
+              "value" : "brussels",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 9
+              },
+              "value" : "santa fe",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traverser-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traverser-v3d0.json
new file mode 100644
index 0000000..a59a29e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/traverser-v3d0.json
@@ -0,0 +1,109 @@
+{
+  "@type" : "g:Traverser",
+  "@value" : {
+    "bulk" : {
+      "@type" : "g:Int64",
+      "@value" : 1
+    },
+    "value" : {
+      "@type" : "g:Vertex",
+      "@value" : {
+        "id" : {
+          "@type" : "g:Int32",
+          "@value" : 1
+        },
+        "label" : "person",
+        "properties" : {
+          "name" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 0
+              },
+              "value" : "marko",
+              "label" : "name"
+            }
+          } ],
+          "location" : [ {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 6
+              },
+              "value" : "san diego",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 1997
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 7
+              },
+              "value" : "santa cruz",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2001
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 8
+              },
+              "value" : "brussels",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2004
+                },
+                "endTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          }, {
+            "@type" : "g:VertexProperty",
+            "@value" : {
+              "id" : {
+                "@type" : "g:Int64",
+                "@value" : 9
+              },
+              "value" : "santa fe",
+              "label" : "location",
+              "properties" : {
+                "startTime" : {
+                  "@type" : "g:Int32",
+                  "@value" : 2005
+                }
+              }
+            }
+          } ]
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v2d0-no-types.json
new file mode 100644
index 0000000..b36ff96
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v2d0-no-types.json
@@ -0,0 +1 @@
+"41d2e28a-20a4-4ab0-b379-d810dede3786"
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v2d0-partial.json
new file mode 100644
index 0000000..1cf09f0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:UUID",
+  "@value" : "41d2e28a-20a4-4ab0-b379-d810dede3786"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v3d0.json
new file mode 100644
index 0000000..1cf09f0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/uuid-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "g:UUID",
+  "@value" : "41d2e28a-20a4-4ab0-b379-d810dede3786"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v1d0.json
new file mode 100644
index 0000000..a885f58
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v1d0.json
@@ -0,0 +1,39 @@
+{
+  "id" : 1,
+  "label" : "person",
+  "type" : "vertex",
+  "properties" : {
+    "name" : [ {
+      "id" : 0,
+      "value" : "marko"
+    } ],
+    "location" : [ {
+      "id" : 6,
+      "value" : "san diego",
+      "properties" : {
+        "startTime" : 1997,
+        "endTime" : 2001
+      }
+    }, {
+      "id" : 7,
+      "value" : "santa cruz",
+      "properties" : {
+        "startTime" : 2001,
+        "endTime" : 2004
+      }
+    }, {
+      "id" : 8,
+      "value" : "brussels",
+      "properties" : {
+        "startTime" : 2004,
+        "endTime" : 2005
+      }
+    }, {
+      "id" : 9,
+      "value" : "santa fe",
+      "properties" : {
+        "startTime" : 2005
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v2d0-no-types.json
new file mode 100644
index 0000000..8e6155f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v2d0-no-types.json
@@ -0,0 +1,43 @@
+{
+  "id" : 1,
+  "label" : "person",
+  "properties" : {
+    "name" : [ {
+      "id" : 0,
+      "value" : "marko",
+      "label" : "name"
+    } ],
+    "location" : [ {
+      "id" : 6,
+      "value" : "san diego",
+      "label" : "location",
+      "properties" : {
+        "startTime" : 1997,
+        "endTime" : 2001
+      }
+    }, {
+      "id" : 7,
+      "value" : "santa cruz",
+      "label" : "location",
+      "properties" : {
+        "startTime" : 2001,
+        "endTime" : 2004
+      }
+    }, {
+      "id" : 8,
+      "value" : "brussels",
+      "label" : "location",
+      "properties" : {
+        "startTime" : 2004,
+        "endTime" : 2005
+      }
+    }, {
+      "id" : 9,
+      "value" : "santa fe",
+      "label" : "location",
+      "properties" : {
+        "startTime" : 2005
+      }
+    } ]
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v2d0-partial.json
new file mode 100644
index 0000000..f102230
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v2d0-partial.json
@@ -0,0 +1,100 @@
+{
+  "@type" : "g:Vertex",
+  "@value" : {
+    "id" : {
+      "@type" : "g:Int32",
+      "@value" : 1
+    },
+    "label" : "person",
+    "properties" : {
+      "name" : [ {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 0
+          },
+          "value" : "marko",
+          "label" : "name"
+        }
+      } ],
+      "location" : [ {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 6
+          },
+          "value" : "san diego",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 1997
+            },
+            "endTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2001
+            }
+          }
+        }
+      }, {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 7
+          },
+          "value" : "santa cruz",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2001
+            },
+            "endTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2004
+            }
+          }
+        }
+      }, {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 8
+          },
+          "value" : "brussels",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2004
+            },
+            "endTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2005
+            }
+          }
+        }
+      }, {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 9
+          },
+          "value" : "santa fe",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2005
+            }
+          }
+        }
+      } ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v3d0.json
new file mode 100644
index 0000000..f102230
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertex-v3d0.json
@@ -0,0 +1,100 @@
+{
+  "@type" : "g:Vertex",
+  "@value" : {
+    "id" : {
+      "@type" : "g:Int32",
+      "@value" : 1
+    },
+    "label" : "person",
+    "properties" : {
+      "name" : [ {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 0
+          },
+          "value" : "marko",
+          "label" : "name"
+        }
+      } ],
+      "location" : [ {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 6
+          },
+          "value" : "san diego",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 1997
+            },
+            "endTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2001
+            }
+          }
+        }
+      }, {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 7
+          },
+          "value" : "santa cruz",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2001
+            },
+            "endTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2004
+            }
+          }
+        }
+      }, {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 8
+          },
+          "value" : "brussels",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2004
+            },
+            "endTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2005
+            }
+          }
+        }
+      }, {
+        "@type" : "g:VertexProperty",
+        "@value" : {
+          "id" : {
+            "@type" : "g:Int64",
+            "@value" : 9
+          },
+          "value" : "santa fe",
+          "label" : "location",
+          "properties" : {
+            "startTime" : {
+              "@type" : "g:Int32",
+              "@value" : 2005
+            }
+          }
+        }
+      } ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v1d0.json
new file mode 100644
index 0000000..74025a8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v1d0.json
@@ -0,0 +1,5 @@
+{
+  "id" : 0,
+  "value" : "marko",
+  "label" : "name"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v2d0-no-types.json
new file mode 100644
index 0000000..74025a8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v2d0-no-types.json
@@ -0,0 +1,5 @@
+{
+  "id" : 0,
+  "value" : "marko",
+  "label" : "name"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v2d0-partial.json
new file mode 100644
index 0000000..af184b1
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v2d0-partial.json
@@ -0,0 +1,11 @@
+{
+  "@type" : "g:VertexProperty",
+  "@value" : {
+    "id" : {
+      "@type" : "g:Int64",
+      "@value" : 0
+    },
+    "value" : "marko",
+    "label" : "name"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v3d0.json
new file mode 100644
index 0000000..af184b1
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/vertexproperty-v3d0.json
@@ -0,0 +1,11 @@
+{
+  "@type" : "g:VertexProperty",
+  "@value" : {
+    "id" : {
+      "@type" : "g:Int64",
+      "@value" : 0
+    },
+    "value" : "marko",
+    "label" : "name"
+  }
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/year-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/year-v2d0-partial.json
new file mode 100644
index 0000000..ff420bc
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/year-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Year",
+  "@value" : "2016"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/year-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/year-v3d0.json
new file mode 100644
index 0000000..ff420bc
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/year-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:Year",
+  "@value" : "2016"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/yearmonth-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/yearmonth-v2d0-partial.json
new file mode 100644
index 0000000..98a5e27
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/yearmonth-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:YearMonth",
+  "@value" : "2016-06"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/yearmonth-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/yearmonth-v3d0.json
new file mode 100644
index 0000000..98a5e27
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/yearmonth-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:YearMonth",
+  "@value" : "2016-06"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneddatetime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneddatetime-v2d0-partial.json
new file mode 100644
index 0000000..367fc47
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneddatetime-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:ZonedDateTime",
+  "@value" : "2016-12-23T12:12:24.000000036+02:00[GMT+02:00]"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneddatetime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneddatetime-v3d0.json
new file mode 100644
index 0000000..367fc47
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneddatetime-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:ZonedDateTime",
+  "@value" : "2016-12-23T12:12:24.000000036+02:00[GMT+02:00]"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneoffset-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneoffset-v2d0-partial.json
new file mode 100644
index 0000000..8591794
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneoffset-v2d0-partial.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:ZoneOffset",
+  "@value" : "+03:06:09"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneoffset-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneoffset-v3d0.json
new file mode 100644
index 0000000..8591794
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_5_0/zoneoffset-v3d0.json
@@ -0,0 +1,4 @@
+{
+  "@type" : "gx:ZoneOffset",
+  "@value" : "+03:06:09"
+}
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/authenticationchallenge-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/authenticationchallenge-v3d0.kryo
new file mode 100644
index 0000000..baf91ac
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/authenticationchallenge-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/authenticationresponse-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/authenticationresponse-v3d0.kryo
new file mode 100644
index 0000000..1f99f2a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/authenticationresponse-v3d0.kryo
@@ -0,0 +1 @@
+Ëh%x’D™ž¼\j§<S—authenticatioîsaslMechanisíPLAIÎsasìAHN0ZXBocGhlbgBwYXNzd29yZA=½
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/barrier-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/barrier-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/barrier-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/barrier-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/barrier-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/barrier-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bigdecimal-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bigdecimal-v1d0.kryo
new file mode 100644
index 0000000..d4f40e0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bigdecimal-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bigdecimal-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bigdecimal-v3d0.kryo
new file mode 100644
index 0000000..d4f40e0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bigdecimal-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/biginteger-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/biginteger-v1d0.kryo
new file mode 100644
index 0000000..f424ac6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/biginteger-v1d0.kryo
@@ -0,0 +1 @@
+ÆãÂýтZÏ}Dvú±
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/biginteger-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/biginteger-v3d0.kryo
new file mode 100644
index 0000000..f424ac6
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/biginteger-v3d0.kryo
@@ -0,0 +1 @@
+ÆãÂýтZÏ}Dvú±
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/binding-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/binding-v1d0.kryo
new file mode 100644
index 0000000..103143b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/binding-v1d0.kryo
@@ -0,0 +1 @@
+‚x
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/binding-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/binding-v3d0.kryo
new file mode 100644
index 0000000..103143b
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/binding-v3d0.kryo
@@ -0,0 +1 @@
+‚x
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bulkset-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bulkset-v1d0.kryo
new file mode 100644
index 0000000..5fda27a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bulkset-v1d0.kryo
@@ -0,0 +1 @@
+markïjosè
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bulkset-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bulkset-v3d0.kryo
new file mode 100644
index 0000000..5fda27a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bulkset-v3d0.kryo
@@ -0,0 +1 @@
+markïjosè
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/byte-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/byte-v1d0.kryo
new file mode 100644
index 0000000..6b2aaa7
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/byte-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/byte-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/byte-v3d0.kryo
new file mode 100644
index 0000000..6b2aaa7
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/byte-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytebuffer-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytebuffer-v1d0.kryo
new file mode 100644
index 0000000..ba94b5d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytebuffer-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytebuffer-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytebuffer-v3d0.kryo
new file mode 100644
index 0000000..ba94b5d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytebuffer-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytecode-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytecode-v1d0.kryo
new file mode 100644
index 0000000..edf8dd4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytecode-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytecode-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytecode-v3d0.kryo
new file mode 100644
index 0000000..edf8dd4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/bytecode-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/cardinality-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/cardinality-v1d0.kryo
new file mode 100644
index 0000000..71bd63e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/cardinality-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/cardinality-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/cardinality-v3d0.kryo
new file mode 100644
index 0000000..71bd63e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/cardinality-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/char-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/char-v1d0.kryo
new file mode 100644
index 0000000..718882c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/char-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/char-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/char-v3d0.kryo
new file mode 100644
index 0000000..718882c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/char-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/class-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/class-v1d0.kryo
new file mode 100644
index 0000000..e8b65af
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/class-v1d0.kryo
@@ -0,0 +1 @@
+java.io.Filå
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/class-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/class-v3d0.kryo
new file mode 100644
index 0000000..e8b65af
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/class-v3d0.kryo
@@ -0,0 +1 @@
+java.io.Filå
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/column-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/column-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/column-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/column-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/column-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/column-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/date-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/date-v1d0.kryo
new file mode 100644
index 0000000..a86f98f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/date-v1d0.kryo
@@ -0,0 +1 @@
+‡·¿ù+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/date-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/date-v3d0.kryo
new file mode 100644
index 0000000..a86f98f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/date-v3d0.kryo
@@ -0,0 +1 @@
+‡·¿ù+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/direction-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/direction-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/direction-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/direction-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/direction-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/direction-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/double-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/double-v1d0.kryo
new file mode 100644
index 0000000..36506ac
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/double-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/double-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/double-v3d0.kryo
new file mode 100644
index 0000000..36506ac
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/double-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/duration-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/duration-v1d0.kryo
new file mode 100644
index 0000000..d640ae0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/duration-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/duration-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/duration-v3d0.kryo
new file mode 100644
index 0000000..d640ae0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/duration-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/edge-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/edge-v1d0.kryo
new file mode 100644
index 0000000..d2a2492
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/edge-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/edge-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/edge-v3d0.kryo
new file mode 100644
index 0000000..6dfbefb
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/edge-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/float-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/float-v1d0.kryo
new file mode 100644
index 0000000..19a8865
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/float-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/float-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/float-v3d0.kryo
new file mode 100644
index 0000000..19a8865
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/float-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/inetaddress-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/inetaddress-v1d0.kryo
new file mode 100644
index 0000000..af797a5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/inetaddress-v1d0.kryo
@@ -0,0 +1 @@
+localhosô
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/inetaddress-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/inetaddress-v3d0.kryo
new file mode 100644
index 0000000..af797a5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/inetaddress-v3d0.kryo
@@ -0,0 +1 @@
+localhosô
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/instant-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/instant-v1d0.kryo
new file mode 100644
index 0000000..d9466cd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/instant-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/instant-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/instant-v3d0.kryo
new file mode 100644
index 0000000..d9466cd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/instant-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/integer-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/integer-v1d0.kryo
new file mode 100644
index 0000000..ff28336
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/integer-v1d0.kryo
@@ -0,0 +1 @@
+È
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/integer-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/integer-v3d0.kryo
new file mode 100644
index 0000000..ff28336
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/integer-v3d0.kryo
@@ -0,0 +1 @@
+È
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/lambda-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/lambda-v1d0.kryo
new file mode 100644
index 0000000..463661d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/lambda-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/lambda-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/lambda-v3d0.kryo
new file mode 100644
index 0000000..463661d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/lambda-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdate-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdate-v1d0.kryo
new file mode 100644
index 0000000..f82dd16
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdate-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdate-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdate-v3d0.kryo
new file mode 100644
index 0000000..f82dd16
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdate-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdatetime-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdatetime-v1d0.kryo
new file mode 100644
index 0000000..97eae64
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdatetime-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdatetime-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdatetime-v3d0.kryo
new file mode 100644
index 0000000..97eae64
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localdatetime-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localtime-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localtime-v1d0.kryo
new file mode 100644
index 0000000..1b5bfa4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localtime-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localtime-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localtime-v3d0.kryo
new file mode 100644
index 0000000..1b5bfa4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/localtime-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/long-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/long-v1d0.kryo
new file mode 100644
index 0000000..ff28336
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/long-v1d0.kryo
@@ -0,0 +1 @@
+È
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/long-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/long-v3d0.kryo
new file mode 100644
index 0000000..ff28336
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/long-v3d0.kryo
@@ -0,0 +1 @@
+È
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/metrics-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/metrics-v1d0.kryo
new file mode 100644
index 0000000..d94cd24
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/metrics-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/metrics-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/metrics-v3d0.kryo
new file mode 100644
index 0000000..f65dd63
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/metrics-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/monthday-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/monthday-v1d0.kryo
new file mode 100644
index 0000000..5acab8f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/monthday-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/monthday-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/monthday-v3d0.kryo
new file mode 100644
index 0000000..5acab8f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/monthday-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsetdatetime-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsetdatetime-v1d0.kryo
new file mode 100644
index 0000000..6bb92d0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsetdatetime-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsetdatetime-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsetdatetime-v3d0.kryo
new file mode 100644
index 0000000..6bb92d0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsetdatetime-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsettime-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsettime-v1d0.kryo
new file mode 100644
index 0000000..d1621aa
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsettime-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsettime-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsettime-v3d0.kryo
new file mode 100644
index 0000000..d1621aa
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/offsettime-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/operator-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/operator-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/operator-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/operator-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/operator-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/operator-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/order-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/order-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/order-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/order-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/order-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/order-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/p-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/p-v1d0.kryo
new file mode 100644
index 0000000..3c676a8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/p-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/p-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/p-v3d0.kryo
new file mode 100644
index 0000000..3c676a8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/p-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pand-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pand-v1d0.kryo
new file mode 100644
index 0000000..5477e40
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pand-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pand-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pand-v3d0.kryo
new file mode 100644
index 0000000..5477e40
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pand-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/path-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/path-v1d0.kryo
new file mode 100644
index 0000000..bac203d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/path-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/path-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/path-v3d0.kryo
new file mode 100644
index 0000000..bac203d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/path-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/period-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/period-v1d0.kryo
new file mode 100644
index 0000000..f04e9c8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/period-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/period-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/period-v3d0.kryo
new file mode 100644
index 0000000..f04e9c8
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/period-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pick-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pick-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pick-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pick-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pick-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pick-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pop-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pop-v1d0.kryo
new file mode 100644
index 0000000..c8c7811
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pop-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pop-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pop-v3d0.kryo
new file mode 100644
index 0000000..c8c7811
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pop-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/por-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/por-v1d0.kryo
new file mode 100644
index 0000000..8b8ebb4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/por-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/por-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/por-v3d0.kryo
new file mode 100644
index 0000000..8b8ebb4
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/por-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/property-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/property-v1d0.kryo
new file mode 100644
index 0000000..133ac6f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/property-v1d0.kryo
@@ -0,0 +1 @@
+sincå²
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/property-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/property-v3d0.kryo
new file mode 100644
index 0000000..a7d9c27
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/property-v3d0.kryo
@@ -0,0 +1 @@
+sincå²developó
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithin-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithin-v1d0.kryo
new file mode 100644
index 0000000..35dfe21
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithin-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithin-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithin-v3d0.kryo
new file mode 100644
index 0000000..35dfe21
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithin-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithout-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithout-v1d0.kryo
new file mode 100644
index 0000000..50f14cf
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithout-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithout-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithout-v3d0.kryo
new file mode 100644
index 0000000..50f14cf
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/pwithout-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/scope-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/scope-v1d0.kryo
new file mode 100644
index 0000000..71bd63e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/scope-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/scope-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/scope-v3d0.kryo
new file mode 100644
index 0000000..71bd63e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/scope-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionclose-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionclose-v3d0.kryo
new file mode 100644
index 0000000..1bad6a1
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionclose-v3d0.kryo
@@ -0,0 +1 @@
+Ëh%x’D™ž¼\j§<S—sessioîclosåsessioîunique-session-identifieò
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessioneval-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessioneval-v3d0.kryo
new file mode 100644
index 0000000..f551b96
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessioneval-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionevalaliased-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionevalaliased-v3d0.kryo
new file mode 100644
index 0000000..8bb5889
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionevalaliased-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionlesseval-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionlesseval-v3d0.kryo
new file mode 100644
index 0000000..fd84e20
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionlesseval-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionlessevalaliased-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionlessevalaliased-v3d0.kryo
new file mode 100644
index 0000000..d3745be
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/sessionlessevalaliased-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/short-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/short-v1d0.kryo
new file mode 100644
index 0000000..6060b89
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/short-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/short-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/short-v3d0.kryo
new file mode 100644
index 0000000..6060b89
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/short-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/standardresult-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/standardresult-v3d0.kryo
new file mode 100644
index 0000000..06c5d8a
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/standardresult-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/stargraph-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/stargraph-v1d0.kryo
new file mode 100644
index 0000000..9947842
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/stargraph-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/stargraph-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/stargraph-v3d0.kryo
new file mode 100644
index 0000000..9947842
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/stargraph-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/t-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/t-v1d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/t-v1d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/t-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/t-v3d0.kryo
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/t-v3d0.kryo
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/textp-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/textp-v1d0.kryo
new file mode 100644
index 0000000..d71eb0f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/textp-v1d0.kryo
@@ -0,0 +1 @@
+containinçarë
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/textp-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/textp-v3d0.kryo
new file mode 100644
index 0000000..d71eb0f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/textp-v3d0.kryo
@@ -0,0 +1 @@
+containinçarë
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/timestamp-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/timestamp-v1d0.kryo
new file mode 100644
index 0000000..a86f98f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/timestamp-v1d0.kryo
@@ -0,0 +1 @@
+‡·¿ù+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/timestamp-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/timestamp-v3d0.kryo
new file mode 100644
index 0000000..a86f98f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/timestamp-v3d0.kryo
@@ -0,0 +1 @@
+‡·¿ù+
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tinkergraph-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tinkergraph-v1d0.kryo
new file mode 100644
index 0000000..5789986
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tinkergraph-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tinkergraph-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tinkergraph-v3d0.kryo
new file mode 100644
index 0000000..5789986
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tinkergraph-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traversalmetrics-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traversalmetrics-v1d0.kryo
new file mode 100644
index 0000000..eef8b5f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traversalmetrics-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traversalmetrics-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traversalmetrics-v3d0.kryo
new file mode 100644
index 0000000..5ec44fd
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traversalmetrics-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traverser-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traverser-v1d0.kryo
new file mode 100644
index 0000000..cc019f0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traverser-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traverser-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traverser-v3d0.kryo
new file mode 100644
index 0000000..7c1fb0d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/traverser-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tree-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tree-v1d0.kryo
new file mode 100644
index 0000000..682529f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tree-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tree-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tree-v3d0.kryo
new file mode 100644
index 0000000..d5a9dd9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/tree-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/uuid-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/uuid-v1d0.kryo
new file mode 100644
index 0000000..34fc35d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/uuid-v1d0.kryo
@@ -0,0 +1 @@
+AÒ⊠¤J°³yØÞÞ7†
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/uuid-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/uuid-v3d0.kryo
new file mode 100644
index 0000000..34fc35d
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/uuid-v3d0.kryo
@@ -0,0 +1 @@
+AÒ⊠¤J°³yØÞÞ7†
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertex-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertex-v1d0.kryo
new file mode 100644
index 0000000..c58ac46
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertex-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertex-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertex-v3d0.kryo
new file mode 100644
index 0000000..4464039
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertex-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertexproperty-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertexproperty-v1d0.kryo
new file mode 100644
index 0000000..3b74daa
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertexproperty-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertexproperty-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertexproperty-v3d0.kryo
new file mode 100644
index 0000000..95f8be0
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/vertexproperty-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/year-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/year-v1d0.kryo
new file mode 100644
index 0000000..2ec2ef9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/year-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/year-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/year-v3d0.kryo
new file mode 100644
index 0000000..2ec2ef9
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/year-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/yearmonth-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/yearmonth-v1d0.kryo
new file mode 100644
index 0000000..47e3a3e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/yearmonth-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/yearmonth-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/yearmonth-v3d0.kryo
new file mode 100644
index 0000000..47e3a3e
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/yearmonth-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneddatetime-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneddatetime-v1d0.kryo
new file mode 100644
index 0000000..3ebbce5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneddatetime-v1d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneddatetime-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneddatetime-v3d0.kryo
new file mode 100644
index 0000000..3ebbce5
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneddatetime-v3d0.kryo
Binary files differ
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneoffset-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneoffset-v1d0.kryo
new file mode 100644
index 0000000..4d34f9c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneoffset-v1d0.kryo
@@ -0,0 +1 @@
++03:06:0¹
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneoffset-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneoffset-v3d0.kryo
new file mode 100644
index 0000000..4d34f9c
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_5_0/zoneoffset-v3d0.kryo
@@ -0,0 +1 @@
++03:06:0¹
\ No newline at end of file
diff --git a/gremlin-tools/pom.xml b/gremlin-tools/pom.xml
index 1e8b1a7..76a4928 100644
--- a/gremlin-tools/pom.xml
+++ b/gremlin-tools/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-tools</artifactId>
diff --git a/hadoop-gremlin/pom.xml b/hadoop-gremlin/pom.xml
index 2d14f07..3e50091 100644
--- a/hadoop-gremlin/pom.xml
+++ b/hadoop-gremlin/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>hadoop-gremlin</artifactId>
     <name>Apache TinkerPop :: Hadoop Gremlin</name>
@@ -100,25 +100,47 @@
                     <artifactId>servlet-api</artifactId>
                 </exclusion>
                 <exclusion>
+                    <groupId>commons-lang</groupId>
+                    <artifactId>commons-lang</artifactId>
+                </exclusion>
+                <exclusion>
                     <groupId>org.apache.commons</groupId>
                     <artifactId>commons-compress</artifactId>
                 </exclusion>
+                <!--
+                spark 3.0/scala 2.12 uses paranamer 2.8 and hadoop is stuck with an older version. without 2.8 you get
+                SPARK-14220
+                -->
+                <exclusion>
+                    <groupId>com.thoughtworks.paranamer</groupId>
+                    <artifactId>paranamer</artifactId>
+                </exclusion>
             </exclusions>
             <!--<scope>provided</scope>-->
         </dependency>
         <!-- consistent dependencies -->
         <dependency>
+            <groupId>com.thoughtworks.paranamer</groupId>
+            <artifactId>paranamer</artifactId>
+            <version>2.8</version>
+        </dependency>
+        <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
         <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>
+        <dependency>
             <groupId>commons-codec</groupId>
             <artifactId>commons-codec</artifactId>
         </dependency>
         <dependency>
             <groupId>commons-logging</groupId>
             <artifactId>commons-logging</artifactId>
-            <version>1.1.3</version>
+            <version>1.2</version>
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopCombine.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopCombine.java
index 06778e6..052cae6 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopCombine.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopCombine.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.process.computer;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.mapreduce.Reducer;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.HadoopPools;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopMap.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopMap.java
index 5fc7026..93a86c0 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopMap.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopMap.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.process.computer;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.io.NullWritable;
 import org.apache.hadoop.mapreduce.Mapper;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopReduce.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopReduce.java
index 6ca7b8f..8b4eda5 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopReduce.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/HadoopReduce.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.process.computer;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.mapreduce.Reducer;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.HadoopPools;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/util/MapReduceHelper.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/util/MapReduceHelper.java
index 88474b2..f449581 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/util/MapReduceHelper.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/util/MapReduceHelper.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.process.computer.util;
 
-import org.apache.commons.configuration.BaseConfiguration;
+import org.apache.commons.configuration2.BaseConfiguration;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
@@ -65,7 +65,6 @@
             newConfiguration.unset(Constants.GREMLIN_HADOOP_GRAPH_FILTER);
         }
         final BaseConfiguration apacheConfiguration = new BaseConfiguration();
-        apacheConfiguration.setDelimiterParsingDisabled(true);
         mapReduce.storeState(apacheConfiguration);
         ConfUtil.mergeApacheIntoHadoopConfiguration(apacheConfiguration, newConfiguration);
 
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopConfiguration.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopConfiguration.java
index a8125ea..610f073 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopConfiguration.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopConfiguration.java
@@ -18,13 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.structure;
 
-import org.apache.commons.configuration.AbstractConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.hadoop.io.NullWritable;
-import org.apache.hadoop.mapreduce.InputFormat;
-import org.apache.hadoop.mapreduce.OutputFormat;
+import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
-import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.javatuples.Pair;
 
@@ -42,7 +38,6 @@
 
     public HadoopConfiguration() {
         super();
-        super.setDelimiterParsingDisabled(true);
     }
 
     public HadoopConfiguration(final Configuration configuration) {
@@ -51,6 +46,26 @@
     }
 
     @Override
+    protected Iterator<String> getKeysInternal() {
+        return properties.keySet().iterator();
+    }
+
+    @Override
+    protected Object getPropertyInternal(final String s) {
+        return properties.get(s);
+    }
+
+    @Override
+    protected boolean isEmptyInternal() {
+        return properties.isEmpty();
+    }
+
+    @Override
+    protected boolean containsKeyInternal(String s) {
+        return properties.containsKey(s);
+    }
+
+    @Override
     protected void addPropertyDirect(final String key, final Object value) {
         this.properties.put(key, value);
     }
@@ -60,26 +75,6 @@
         this.properties.remove(key);
     }
 
-    @Override
-    public boolean isEmpty() {
-        return this.properties.isEmpty();
-    }
-
-    @Override
-    public boolean containsKey(final String key) {
-        return this.properties.containsKey(key);
-    }
-
-    @Override
-    public Object getProperty(final String key) {
-        return this.properties.get(key);
-    }
-
-    @Override
-    public Iterator<String> getKeys() {
-        return this.properties.keySet().iterator();
-    }
-
     ///////
 
     public <A> Class<A> getGraphReader() {
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopGraph.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopGraph.java
index 9ec0cfd..f4722ea 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopGraph.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/HadoopGraph.java
@@ -18,10 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
+import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.process.computer.AbstractHadoopGraphComputer;
 import org.apache.tinkerpop.gremlin.hadoop.process.computer.traversal.strategy.HadoopIoStrategy;
@@ -188,7 +188,8 @@
 
     public static HadoopGraph open(final String configurationFile) throws ConfigurationException {
         if (null == configurationFile) throw Graph.Exceptions.argumentCanNotBeNull("configurationFile");
-        return open(new PropertiesConfiguration(configurationFile));
+        final Configurations configs = new Configurations();
+        return open(configs.properties(configurationFile));
     }
 
     @Override
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/FileSystemStorage.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/FileSystemStorage.java
index b0847f1..e718f20 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/FileSystemStorage.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/FileSystemStorage.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.hadoop.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
+import org.apache.commons.configuration2.BaseConfiguration;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FSDataInputStream;
 import org.apache.hadoop.fs.FSDataOutputStream;
@@ -181,7 +181,7 @@
 
     @Override
     public Iterator<Vertex> head(final String location, final Class readerClass, final int totalLines) {
-        final org.apache.commons.configuration.Configuration configuration = new BaseConfiguration();
+        final org.apache.commons.configuration2.Configuration configuration = new BaseConfiguration();
         configuration.setProperty(Constants.GREMLIN_HADOOP_INPUT_LOCATION, Constants.getSearchGraphLocation(location, this).get());
         configuration.setProperty(Constants.GREMLIN_HADOOP_GRAPH_READER, readerClass.getCanonicalName());
         try {
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/GraphFilterAware.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/GraphFilterAware.java
index ff28d86..cbf735b 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/GraphFilterAware.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/GraphFilterAware.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.hadoop.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPoolShimService.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPoolShimService.java
index db79d97..40c73a2 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPoolShimService.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPoolShimService.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.KryoShimService;
 import org.apache.tinkerpop.shaded.kryo.io.Input;
 import org.apache.tinkerpop.shaded.kryo.io.Output;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPools.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPools.java
index ea73431..69f176f 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPools.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/HadoopPools.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.structure.io;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationUtils;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ConfigurationUtils;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
 import org.apache.tinkerpop.gremlin.hadoop.structure.util.ConfUtil;
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/InputOutputHelper.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/InputOutputHelper.java
index ebb9f77..381c784 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/InputOutputHelper.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/InputOutputHelper.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.io.NullWritable;
 import org.apache.hadoop.mapreduce.InputFormat;
 import org.apache.hadoop.mapreduce.OutputFormat;
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/ObjectWritableComparator.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/ObjectWritableComparator.java
index 976518f..e2884cc 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/ObjectWritableComparator.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/ObjectWritableComparator.java
@@ -64,7 +64,7 @@
         @Override
         public void setConf(final Configuration configuration) {
             super.setConf(configuration);
-            final org.apache.commons.configuration.Configuration apacheConfiguration = ConfUtil.makeApacheConfiguration(configuration);
+            final org.apache.commons.configuration2.Configuration apacheConfiguration = ConfUtil.makeApacheConfiguration(configuration);
             this.comparator = MapReduce.<MapReduce<?,?,?,?,?>>createMapReduce(HadoopGraph.open(apacheConfiguration),apacheConfiguration).getMapKeySort().get();
         }
     }
@@ -73,7 +73,7 @@
         @Override
         public void setConf(final Configuration configuration) {
             super.setConf(configuration);
-            final org.apache.commons.configuration.Configuration apacheConfiguration = ConfUtil.makeApacheConfiguration(configuration);
+            final org.apache.commons.configuration2.Configuration apacheConfiguration = ConfUtil.makeApacheConfiguration(configuration);
             this.comparator = MapReduce.<MapReduce<?,?,?,?,?>>createMapReduce(HadoopGraph.open(apacheConfiguration),apacheConfiguration).getReduceKeySort().get();
         }
     }
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/util/ConfUtil.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/util/ConfUtil.java
index 0e1efb7..b5685ea 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/util/ConfUtil.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/util/ConfUtil.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.hadoop.structure.util;
 
-import org.apache.commons.configuration.BaseConfiguration;
+import org.apache.commons.configuration2.BaseConfiguration;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.io.NullWritable;
 import org.apache.hadoop.mapreduce.InputFormat;
@@ -33,14 +33,13 @@
     private ConfUtil() {
     }
 
-    public static org.apache.commons.configuration.Configuration makeApacheConfiguration(final Configuration hadoopConfiguration) {
+    public static org.apache.commons.configuration2.Configuration makeApacheConfiguration(final Configuration hadoopConfiguration) {
         final BaseConfiguration apacheConfiguration = new BaseConfiguration();
-        apacheConfiguration.setDelimiterParsingDisabled(true);
         hadoopConfiguration.iterator().forEachRemaining(e -> apacheConfiguration.setProperty(e.getKey(), e.getValue()));
         return apacheConfiguration;
     }
 
-    public static Configuration makeHadoopConfiguration(final org.apache.commons.configuration.Configuration apacheConfiguration) {
+    public static Configuration makeHadoopConfiguration(final org.apache.commons.configuration2.Configuration apacheConfiguration) {
         final Configuration hadoopConfiguration = new Configuration();
         apacheConfiguration.getKeys().forEachRemaining(key -> {
             final Object object = apacheConfiguration.getProperty(key);
@@ -49,7 +48,7 @@
         return hadoopConfiguration;
     }
 
-    public static void mergeApacheIntoHadoopConfiguration(final org.apache.commons.configuration.Configuration apacheConfiguration, final Configuration hadoopConfiguration) {
+    public static void mergeApacheIntoHadoopConfiguration(final org.apache.commons.configuration2.Configuration apacheConfiguration, final Configuration hadoopConfiguration) {
         apacheConfiguration.getKeys().forEachRemaining(key -> {
             final Object object = apacheConfiguration.getProperty(key);
             hadoopConfiguration.set(key, object.toString());
diff --git a/neo4j-gremlin/pom.xml b/neo4j-gremlin/pom.xml
index 6ea5bf0..d9c959b 100644
--- a/neo4j-gremlin/pom.xml
+++ b/neo4j-gremlin/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>neo4j-gremlin</artifactId>
     <name>Apache TinkerPop :: Neo4j Gremlin</name>
@@ -34,7 +34,7 @@
         <dependency>
             <groupId>org.neo4j</groupId>
             <artifactId>neo4j-tinkerpop-api</artifactId>
-            <version>0.1</version>
+            <version>0.1.1</version>
         </dependency>
         <!-- TESTING -->
         <dependency>
@@ -42,6 +42,13 @@
             <artifactId>gremlin-test</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
+            <!-- conflict from kirby --> 
+            <exclusions>
+                <exclusion>
+                    <groupId>org.ow2.asm</groupId>
+                    <artifactId>asm</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -89,7 +96,7 @@
                 <configuration>
                     <archive>
                         <manifestEntries>
-                            <Gremlin-Plugin-Dependencies>org.neo4j:neo4j-tinkerpop-api-impl:0.7-3.2.3
+                            <Gremlin-Plugin-Dependencies>org.neo4j:neo4j-tinkerpop-api-impl:0.9-3.4.0
                             </Gremlin-Plugin-Dependencies>
                         </manifestEntries>
                     </archive>
@@ -117,7 +124,7 @@
                 <dependency>
                     <groupId>org.neo4j</groupId>
                     <artifactId>neo4j-tinkerpop-api-impl</artifactId>
-                    <version>0.7-3.2.3</version>
+                    <version>0.9-3.4.0</version>
                     <scope>test</scope>
                     <exclusions>
                         <exclusion>
@@ -129,6 +136,10 @@
                             <artifactId>commons-lang3</artifactId>
                         </exclusion>
                         <exclusion>
+                            <groupId>org.apache.commons</groupId>
+                            <artifactId>commons-text</artifactId>
+                        </exclusion>
+                        <exclusion>
                             <groupId>com.github.ben-manes.caffeine</groupId>
                             <artifactId>caffeine</artifactId>
                         </exclusion>
@@ -148,9 +159,23 @@
                             <groupId>org.slf4j</groupId>
                             <artifactId>slf4j-nop</artifactId>
                         </exclusion>
+                        <exclusion>
+                            <groupId>org.apache.lucene</groupId>
+                            <artifactId>lucene-core</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>io.dropwizard.metrics</groupId>
+                            <artifactId>metrics-core</artifactId>
+                        </exclusion>
                     </exclusions>
                 </dependency>
                 <dependency>
+                    <groupId>org.apache.commons</groupId>
+                    <artifactId>commons-text</artifactId>
+                    <version>1.8</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
                     <groupId>org.scala-lang</groupId>
                     <artifactId>scala-library</artifactId>
                     <version>2.11.8</version>
@@ -168,11 +193,22 @@
                     <version>2.3.1</version>
                     <scope>test</scope>
                 </dependency>
-                <!-- self-conflict with neo4j-graph-matching -->
+                <dependency>
+                    <groupId>org.apache.lucene</groupId>
+                    <artifactId>lucene-core</artifactId>
+                    <version>5.5.0</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>io.dropwizard.metrics</groupId>
+                    <artifactId>metrics-core</artifactId>
+                    <version>4.0.2</version>
+                    <scope>test</scope>
+                </dependency>
                 <dependency>
                     <groupId>org.neo4j</groupId>
                     <artifactId>neo4j-kernel</artifactId>
-                    <version>3.2.3</version>
+                    <version>3.4.11</version>
                     <scope>test</scope>
                 </dependency>
                 <!-- *** WARNING *** -->
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
index f196a8d..43dcd39 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
@@ -18,23 +18,33 @@
  */
 package org.apache.tinkerpop.gremlin.neo4j.process.traversal.step.sideEffect;
 
+import org.apache.tinkerpop.gremlin.neo4j.process.traversal.LabelP;
 import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
+import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
+import org.apache.tinkerpop.gremlin.process.traversal.Compare;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Text;
 import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+import org.neo4j.tinkerpop.api.Neo4jGraphAPI;
+import org.neo4j.tinkerpop.api.Neo4jNode;
+import org.neo4j.tinkerpop.api.Neo4jStringSearchMode;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Optional;
+import java.util.function.BiPredicate;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -61,7 +71,59 @@
         if (null == this.ids)
             return Collections.emptyIterator();
         final Neo4jGraph graph = (Neo4jGraph) this.getTraversal().getGraph().get();
-        return graph.getTrait().lookupVertices(graph, this.hasContainers, this.ids);
+
+        // ids are present, filter on them first
+        if (ids.length > 0)
+            return IteratorUtils.filter(graph.vertices(ids), vertex -> HasContainer.testAll(vertex, hasContainers));
+        ////// do index lookups //////
+        graph.tx().readWrite();
+        // get a label being search on
+        Optional<String> label = hasContainers.stream()
+                .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
+                .filter(hasContainer -> Compare.eq == hasContainer.getBiPredicate())
+                .map(hasContainer -> (String) hasContainer.getValue())
+                .findAny();
+        if (!label.isPresent())
+            label = hasContainers.stream()
+                    .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
+                    .filter(hasContainer -> hasContainer.getPredicate() instanceof LabelP)
+                    .map(hasContainer -> (String) hasContainer.getValue())
+                    .findAny();
+
+        if (label.isPresent()) {
+            // find a vertex by label and key/value
+            String labelValue = label.get();
+            Neo4jGraphAPI baseGraph = graph.getBaseGraph();
+            for (final HasContainer hasContainer : hasContainers) {
+                String key = hasContainer.getKey();
+                Object value = hasContainer.getValue();
+                if (!key.equals(T.label.getAccessor()) && baseGraph.hasSchemaIndex(labelValue, key)) {
+                    BiPredicate<?, ?> predicate = hasContainer.getBiPredicate();
+                    Iterable<Neo4jNode> nodes = null;
+                    if (Compare.eq == predicate) {
+                        nodes = baseGraph.findNodes(labelValue, key, value);
+                    } else if (Text.containing == predicate) {
+                        nodes = baseGraph.findNodes(labelValue, key, value.toString(), Neo4jStringSearchMode.CONTAINS);
+                    } else if (Text.startingWith == predicate) {
+                        nodes = baseGraph.findNodes(labelValue, key, value.toString(), Neo4jStringSearchMode.PREFIX);
+                    } else if (Text.endingWith == predicate) {
+                        nodes = baseGraph.findNodes(labelValue, key, value.toString(), Neo4jStringSearchMode.SUFFIX);
+                    }
+                    if (nodes != null) {
+                        return IteratorUtils.stream(nodes)
+                                .map(node -> (Vertex) new Neo4jVertex(node, graph))
+                                .filter(vertex -> HasContainer.testAll(vertex, hasContainers)).iterator();
+                    }
+                }
+            }
+            // find a vertex by label
+            return IteratorUtils.stream(graph.getBaseGraph().findNodes(label.get()))
+                    .map(node -> (Vertex) new Neo4jVertex(node, graph))
+                    .filter(vertex -> HasContainer.testAll(vertex, hasContainers)).iterator();
+        } else {
+            // linear scan
+            return IteratorUtils.filter(graph.vertices(), vertex -> HasContainer.testAll(vertex, hasContainers));
+        }
     }
 
     @Override
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jEdge.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jEdge.java
index 29ccef1..08282fc 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jEdge.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jEdge.java
@@ -115,6 +115,12 @@
     @Override
     public <V> Property<V> property(final String key, final V value) {
         ElementHelper.validateProperty(key, value);
+        
+        if (null == value) {
+            properties(key).forEachRemaining(Property::remove);
+            return Property.empty();
+        }
+
         this.graph.tx().readWrite();
         try {
             this.baseElement.setProperty(key, value);
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
index aeeb9ef..55be5f6 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
@@ -18,15 +18,12 @@
  */
 package org.apache.tinkerpop.gremlin.neo4j.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationConverter;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ConfigurationConverter;
 import org.apache.tinkerpop.gremlin.neo4j.process.traversal.step.sideEffect.CypherStartStep;
 import org.apache.tinkerpop.gremlin.neo4j.process.traversal.strategy.optimization.Neo4jGraphStepStrategy;
 import org.apache.tinkerpop.gremlin.neo4j.process.util.Neo4jCypherIterator;
-import org.apache.tinkerpop.gremlin.neo4j.structure.trait.MultiMetaNeo4jTrait;
-import org.apache.tinkerpop.gremlin.neo4j.structure.trait.Neo4jTrait;
-import org.apache.tinkerpop.gremlin.neo4j.structure.trait.NoMultiNoMetaNeo4jTrait;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
@@ -44,17 +41,11 @@
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.neo4j.tinkerpop.api.Neo4jFactory;
 import org.neo4j.tinkerpop.api.Neo4jGraphAPI;
-import org.neo4j.tinkerpop.api.Neo4jNode;
-import org.neo4j.tinkerpop.api.Neo4jRelationship;
 import org.neo4j.tinkerpop.api.Neo4jTx;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Optional;
-import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 /**
@@ -68,8 +59,6 @@
 @Graph.OptIn("org.apache.tinkerpop.gremlin.neo4j.NativeNeo4jSuite")
 public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
 
-    public static final Logger LOGGER = LoggerFactory.getLogger(Neo4jGraph.class);
-
     static {
         TraversalStrategies.GlobalCache.registerStrategies(Neo4jGraph.class, TraversalStrategies.GlobalCache.getStrategies(Graph.class).clone().addStrategies(Neo4jGraphStepStrategy.instance()));
     }
@@ -86,42 +75,13 @@
     public static final String CONFIG_DIRECTORY = "gremlin.neo4j.directory";
     public static final String CONFIG_CONF = "gremlin.neo4j.conf";
 
-    /**
-     * @deprecated As of release 3.3.8, not replaced.
-     */
-    @Deprecated
-    public static final String CONFIG_META_PROPERTIES = "gremlin.neo4j.metaProperties";
-
-    /**
-     * @deprecated As of release 3.3.8, not replaced.
-     */
-    @Deprecated
-    public static final String CONFIG_MULTI_PROPERTIES = "gremlin.neo4j.multiProperties";
-
     private final Neo4jTransaction neo4jTransaction = new Neo4jTransaction();
     private Neo4jGraphVariables neo4jGraphVariables;
 
-    protected Neo4jTrait trait;
-
     private void initialize(final Neo4jGraphAPI baseGraph, final Configuration configuration) {
         this.configuration.copy(configuration);
         this.baseGraph = baseGraph;
         this.neo4jGraphVariables = new Neo4jGraphVariables(this);
-        this.tx().readWrite();
-        final Optional<Boolean> hasMultiProperties = this.neo4jGraphVariables.get(Graph.Hidden.hide(CONFIG_MULTI_PROPERTIES));
-        final Optional<Boolean> hasMetaProperties = this.neo4jGraphVariables.get(Graph.Hidden.hide(CONFIG_META_PROPERTIES));
-        boolean supportsMetaProperties = hasMetaProperties.orElse(this.configuration.getBoolean(CONFIG_META_PROPERTIES, false));
-        boolean supportsMultiProperties = hasMultiProperties.orElse(this.configuration.getBoolean(CONFIG_MULTI_PROPERTIES, false));
-        if (supportsMultiProperties != supportsMetaProperties)
-            throw new IllegalArgumentException(this.getClass().getSimpleName() + " currently supports either both meta-properties and multi-properties or neither");
-        if (!hasMultiProperties.isPresent())
-            this.neo4jGraphVariables.set(Graph.Hidden.hide(CONFIG_MULTI_PROPERTIES), supportsMultiProperties);
-        if (!hasMetaProperties.isPresent())
-            this.neo4jGraphVariables.set(Graph.Hidden.hide(CONFIG_META_PROPERTIES), supportsMetaProperties);
-        this.trait = supportsMultiProperties ? MultiMetaNeo4jTrait.instance() : NoMultiNoMetaNeo4jTrait.instance();
-        if (supportsMultiProperties)
-            LOGGER.warn(this.getClass().getSimpleName() + " multi/meta-properties feature has always been considered experimental and not production ready - it is now deprecated as of 3.3.8");
-        this.tx().commit();
     }
 
     protected Neo4jGraph(final Neo4jGraphAPI baseGraph, final Configuration configuration) {
@@ -179,10 +139,8 @@
     @Override
     public Iterator<Vertex> vertices(final Object... vertexIds) {
         this.tx().readWrite();
-        final Predicate<Neo4jNode> nodePredicate = this.trait.getNodePredicate();
         if (0 == vertexIds.length) {
             return IteratorUtils.stream(this.getBaseGraph().allNodes())
-                    .filter(nodePredicate)
                     .map(node -> (Vertex) new Neo4jVertex(node, this)).iterator();
         } else {
             ElementHelper.validateMixedElementIds(Vertex.class, vertexIds);
@@ -205,7 +163,6 @@
                             throw e;
                         }
                     })
-                    .filter(nodePredicate)
                     .map(node -> (Vertex) new Neo4jVertex(node, this)).iterator();
         }
     }
@@ -213,10 +170,8 @@
     @Override
     public Iterator<Edge> edges(final Object... edgeIds) {
         this.tx().readWrite();
-        final Predicate<Neo4jRelationship> relationshipPredicate = this.trait.getRelationshipPredicate();
         if (0 == edgeIds.length) {
             return IteratorUtils.stream(this.getBaseGraph().allRelationships())
-                    .filter(relationshipPredicate)
                     .map(relationship -> (Edge) new Neo4jEdge(relationship, this)).iterator();
         } else {
             ElementHelper.validateMixedElementIds(Edge.class, edgeIds);
@@ -239,20 +194,10 @@
                             throw e;
                         }
                     })
-                    .filter(relationshipPredicate)
                     .map(relationship -> (Edge) new Neo4jEdge(relationship, this)).iterator();
         }
     }
 
-
-    /**
-     * @deprecated As of release 3.3.8, not replaced.
-     */
-    @Deprecated
-    public Neo4jTrait getTrait() {
-        return this.trait;
-    }
-
     @Override
     public <C extends GraphComputer> C compute(final Class<C> graphComputerClass) {
         throw Graph.Exceptions.graphComputerNotSupported();
@@ -434,12 +379,12 @@
 
             @Override
             public boolean supportsMetaProperties() {
-                return trait.supportsMetaProperties();
+                return false;
             }
 
             @Override
             public boolean supportsMultiProperties() {
-                return trait.supportsMultiProperties();
+                return false;
             }
 
             @Override
@@ -449,7 +394,7 @@
 
             @Override
             public VertexProperty.Cardinality getCardinality(final String key) {
-                return trait.getCardinality(key);
+                return VertexProperty.Cardinality.single;
             }
         }
 
@@ -472,6 +417,11 @@
             }
 
             @Override
+            public boolean supportsNullPropertyValues() {
+                return false;
+            }
+
+            @Override
             public boolean supportsUserSuppliedIds() {
                 return false;
             }
@@ -503,6 +453,11 @@
             }
 
             @Override
+            public boolean supportsNullPropertyValues() {
+                return false;
+            }
+
+            @Override
             public boolean supportsMapValues() {
                 return false;
             }
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertex.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertex.java
index 2bcd363..98b1893 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertex.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertex.java
@@ -21,12 +21,14 @@
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.structure.util.wrapped.WrappedVertex;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+import org.neo4j.tinkerpop.api.Neo4jDirection;
 import org.neo4j.tinkerpop.api.Neo4jNode;
 import org.neo4j.tinkerpop.api.Neo4jRelationship;
 
@@ -73,7 +75,18 @@
     @Override
     public void remove() {
         this.graph.tx().readWrite();
-        this.graph.trait.removeVertex(this);
+        try {
+            final Neo4jNode node = (Neo4jNode) baseElement;
+            for (final Neo4jRelationship relationship : node.relationships(Neo4jDirection.BOTH)) {
+                relationship.delete();
+            }
+            node.delete();
+        } catch (final IllegalStateException ignored) {
+            // this one happens if the vertex is still chilling in the tx
+        } catch (final RuntimeException ex) {
+            if (!Neo4jHelper.isNotFound(ex)) throw ex;
+            // this one happens if the vertex is committed
+        }
     }
 
     @Override
@@ -82,19 +95,37 @@
         if (ElementHelper.getIdValue(keyValues).isPresent())
             throw Vertex.Exceptions.userSuppliedIdsNotSupported();
         this.graph.tx().readWrite();
-        return this.graph.trait.setVertexProperty(this, cardinality, key, value, keyValues);
+
+        if (cardinality != VertexProperty.Cardinality.single)
+            throw VertexProperty.Exceptions.multiPropertiesNotSupported();
+
+        if (null == value) {
+            properties(key).forEachRemaining(VertexProperty::remove);
+            return VertexProperty.empty();
+        }
+
+        if (keyValues.length > 0)
+            throw VertexProperty.Exceptions.metaPropertiesNotSupported();
+        try {
+            this.baseElement.setProperty(key, value);
+            return new Neo4jVertexProperty<>(this, key, value);
+        } catch (final IllegalArgumentException iae) {
+            throw Property.Exceptions.dataTypeOfPropertyValueNotSupported(value, iae);
+        }
     }
 
     @Override
     public <V> VertexProperty<V> property(final String key) {
         this.graph.tx().readWrite();
-        return this.graph.trait.getVertexProperty(this, key);
+        return baseElement.hasProperty(key) ? new Neo4jVertexProperty<>(this, key, (V) baseElement.getProperty(key)) : VertexProperty.<V>empty();
     }
 
     @Override
     public <V> Iterator<VertexProperty<V>> properties(final String... propertyKeys) {
         this.graph.tx().readWrite();
-        return this.graph.trait.getVertexProperties(this, propertyKeys);
+        return (Iterator) IteratorUtils.stream(this.baseElement.getKeys())
+                .filter(key -> ElementHelper.keyExists(key, propertyKeys))
+                .map(key -> new Neo4jVertexProperty<>(this, key, (V) this.baseElement.getProperty(key))).iterator();
     }
 
     @Override
@@ -112,7 +143,7 @@
     public Iterator<Vertex> vertices(final Direction direction, final String... edgeLabels) {
         this.graph.tx().readWrite();
         return new Iterator<Vertex>() {
-            final Iterator<Neo4jRelationship> relationshipIterator = IteratorUtils.filter(0 == edgeLabels.length ?
+            final Iterator<Neo4jRelationship> relationshipIterator = 0 == edgeLabels.length ?
                     BOTH == direction ?
                             IteratorUtils.concat(getBaseVertex().relationships(Neo4jHelper.mapDirection(OUT)).iterator(),
                                     getBaseVertex().relationships(Neo4jHelper.mapDirection(IN)).iterator()) :
@@ -120,7 +151,7 @@
                     BOTH == direction ?
                             IteratorUtils.concat(getBaseVertex().relationships(Neo4jHelper.mapDirection(OUT), (edgeLabels)).iterator(),
                                     getBaseVertex().relationships(Neo4jHelper.mapDirection(IN), (edgeLabels)).iterator()) :
-                            getBaseVertex().relationships(Neo4jHelper.mapDirection(direction), (edgeLabels)).iterator(), graph.trait.getRelationshipPredicate());
+                            getBaseVertex().relationships(Neo4jHelper.mapDirection(direction), (edgeLabels)).iterator();
 
             @Override
             public boolean hasNext() {
@@ -138,7 +169,7 @@
     public Iterator<Edge> edges(final Direction direction, final String... edgeLabels) {
         this.graph.tx().readWrite();
         return new Iterator<Edge>() {
-            final Iterator<Neo4jRelationship> relationshipIterator = IteratorUtils.filter(0 == edgeLabels.length ?
+            final Iterator<Neo4jRelationship> relationshipIterator = 0 == edgeLabels.length ?
                     BOTH == direction ?
                             IteratorUtils.concat(getBaseVertex().relationships(Neo4jHelper.mapDirection(OUT)).iterator(),
                                     getBaseVertex().relationships(Neo4jHelper.mapDirection(IN)).iterator()) :
@@ -146,7 +177,7 @@
                     BOTH == direction ?
                             IteratorUtils.concat(getBaseVertex().relationships(Neo4jHelper.mapDirection(OUT), (edgeLabels)).iterator(),
                                     getBaseVertex().relationships(Neo4jHelper.mapDirection(IN), (edgeLabels)).iterator()) :
-                            getBaseVertex().relationships(Neo4jHelper.mapDirection(direction), (edgeLabels)).iterator(), graph.trait.getRelationshipPredicate());
+                            getBaseVertex().relationships(Neo4jHelper.mapDirection(direction), (edgeLabels)).iterator();
 
             @Override
             public boolean hasNext() {
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertexProperty.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertexProperty.java
index 108aec2..b5fa2af 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertexProperty.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jVertexProperty.java
@@ -93,21 +93,19 @@
 
     @Override
     public <U> Iterator<Property<U>> properties(final String... propertyKeys) {
-        this.vertex.graph.tx().readWrite();
-        return this.vertex.graph.trait.getProperties(this, propertyKeys);
+        throw VertexProperty.Exceptions.metaPropertiesNotSupported();
     }
 
     @Override
     public <U> Property<U> property(final String key, final U value) {
-        this.vertex.graph.tx().readWrite();
-        ElementHelper.validateProperty(key, value);
-        return this.vertex.graph.trait.setProperty(this, key, value);
+        throw VertexProperty.Exceptions.metaPropertiesNotSupported();
     }
 
     @Override
     public void remove() {
         this.vertex.graph.tx().readWrite();
-        this.vertex.graph.trait.removeVertexProperty(this);
+        final Neo4jNode node = ((Neo4jVertex) element()).getBaseVertex();
+        if (node.hasProperty(key)) node.removeProperty(key);
         this.vertexPropertyNode= null;
     }
 
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java
deleted file mode 100644
index 5ded961..0000000
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * 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.neo4j.structure.trait;
-
-import org.apache.tinkerpop.gremlin.neo4j.process.traversal.LabelP;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jHelper;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jProperty;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty;
-import org.apache.tinkerpop.gremlin.process.traversal.Compare;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
-import org.apache.tinkerpop.gremlin.structure.util.wrapped.WrappedGraph;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.neo4j.tinkerpop.api.Neo4jDirection;
-import org.neo4j.tinkerpop.api.Neo4jGraphAPI;
-import org.neo4j.tinkerpop.api.Neo4jNode;
-import org.neo4j.tinkerpop.api.Neo4jRelationship;
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @deprecated As of release 3.3.8, not replaced.
- */
-@Deprecated
-public final class MultiMetaNeo4jTrait implements Neo4jTrait {
-
-    private static final MultiMetaNeo4jTrait INSTANCE = new MultiMetaNeo4jTrait();
-
-    public static final String VERTEX_PROPERTY_LABEL = "vertexProperty";
-    public static final String VERTEX_PROPERTY_TOKEN = Graph.Hidden.hide("vertexProperty");
-
-    private static final Predicate<Neo4jNode> NODE_PREDICATE = node -> !node.hasLabel(VERTEX_PROPERTY_LABEL);
-    private static final Predicate<Neo4jRelationship> RELATIONSHIP_PREDICATE = relationship -> !Graph.Hidden.isHidden(relationship.type());
-
-    private MultiMetaNeo4jTrait() {
-
-    }
-
-    public static MultiMetaNeo4jTrait instance() {
-        return INSTANCE;
-    }
-
-    @Override
-    public Predicate<Neo4jNode> getNodePredicate() {
-        return NODE_PREDICATE;
-    }
-
-    @Override
-    public Predicate<Neo4jRelationship> getRelationshipPredicate() {
-        return RELATIONSHIP_PREDICATE;
-    }
-
-    @Override
-    public void removeVertex(final Neo4jVertex vertex) {
-        try {
-            final Neo4jNode node = vertex.getBaseVertex();
-            for (final Neo4jRelationship relationship : node.relationships(Neo4jDirection.BOTH)) {
-                final Neo4jNode otherNode = relationship.other(node);
-                if (otherNode.hasLabel(VERTEX_PROPERTY_LABEL)) {
-                    otherNode.delete(); // meta property node
-                }
-                relationship.delete();
-            }
-            node.delete();
-        } catch (final IllegalStateException ignored) {
-            // this one happens if the vertex is still chilling in the tx
-        } catch (final RuntimeException ex) {
-            if (!Neo4jHelper.isNotFound(ex)) throw ex;
-            // this one happens if the vertex is committed
-        }
-    }
-
-    @Override
-    public <V> VertexProperty<V> getVertexProperty(final Neo4jVertex vertex, final String key) {
-        final Neo4jNode node = vertex.getBaseVertex();
-        if (node.hasProperty(key)) {
-            if (node.getProperty(key).equals(VERTEX_PROPERTY_TOKEN)) {
-                if (node.degree(Neo4jDirection.OUTGOING, Graph.Hidden.hide(key)) > 1)
-                    throw Vertex.Exceptions.multiplePropertiesExistForProvidedKey(key);
-                else {
-                    return (VertexProperty<V>) new Neo4jVertexProperty<>(vertex, node.relationships(Neo4jDirection.OUTGOING, Graph.Hidden.hide(key)).iterator().next().end());
-                }
-            } else {
-                return new Neo4jVertexProperty<>(vertex, key, (V) node.getProperty(key));
-            }
-        } else
-            return VertexProperty.<V>empty();
-    }
-
-    @Override
-    public <V> Iterator<VertexProperty<V>> getVertexProperties(final Neo4jVertex vertex, final String... keys) {
-        if (Neo4jHelper.isDeleted(vertex.getBaseVertex()))
-            return Collections.emptyIterator(); // TODO: I believe its because the vertex property is deleted, but then seen again in the iterator. ?
-        return IteratorUtils.stream(vertex.getBaseVertex().getKeys())
-                .filter(key -> ElementHelper.keyExists(key, keys))
-                .flatMap(key -> {
-                    if (vertex.getBaseVertex().getProperty(key).equals(VERTEX_PROPERTY_TOKEN))
-                        return IteratorUtils.stream(vertex.getBaseVertex().relationships(Neo4jDirection.OUTGOING, Graph.Hidden.hide(key)))
-                                .map(relationship -> (VertexProperty<V>) new Neo4jVertexProperty<>(vertex, relationship.end()));
-                    else
-                        return Stream.of(new Neo4jVertexProperty<>(vertex, key, (V) vertex.getBaseVertex().getProperty(key)));
-                }).iterator();
-    }
-
-    @Override
-    public <V> VertexProperty<V> setVertexProperty(final Neo4jVertex vertex, final VertexProperty.Cardinality cardinality,
-                                                   final String key, final V value, final Object... keyValues) {
-        try {
-            final Optional<VertexProperty<V>> optionalVertexProperty = ElementHelper.stageVertexProperty(vertex, cardinality, key, value, keyValues);
-            if (optionalVertexProperty.isPresent()) return optionalVertexProperty.get();
-            final Neo4jNode node = vertex.getBaseVertex();
-            final Neo4jGraphAPI graph = ((Neo4jGraph) vertex.graph()).getBaseGraph();
-            final String prefixedKey = Graph.Hidden.hide(key);
-            if (node.hasProperty(key)) {
-                if (node.getProperty(key).equals(VERTEX_PROPERTY_TOKEN)) {
-                    final Neo4jNode vertexPropertyNode = graph.createNode(VERTEX_PROPERTY_LABEL, key);
-                    vertexPropertyNode.setProperty(T.key.getAccessor(), key);
-                    vertexPropertyNode.setProperty(T.value.getAccessor(), value);
-                    vertexPropertyNode.setProperty(key, value);
-                    node.connectTo(vertexPropertyNode, prefixedKey);
-                    final Neo4jVertexProperty<V> property = new Neo4jVertexProperty<>(vertex, key, value, vertexPropertyNode);
-                    ElementHelper.attachProperties(property, keyValues); // TODO: make this inlined
-                    return property;
-                } else {
-                    // move current key to be a vertex property node
-                    Neo4jNode vertexPropertyNode = graph.createNode(VERTEX_PROPERTY_LABEL, key);
-                    final Object tempValue = node.removeProperty(key);
-                    vertexPropertyNode.setProperty(T.key.getAccessor(), key);
-                    vertexPropertyNode.setProperty(T.value.getAccessor(), tempValue);
-                    vertexPropertyNode.setProperty(key, tempValue);
-                    node.connectTo(vertexPropertyNode, prefixedKey);
-                    node.setProperty(key, VERTEX_PROPERTY_TOKEN);
-                    vertexPropertyNode = graph.createNode(VERTEX_PROPERTY_LABEL, key);
-                    vertexPropertyNode.setProperty(T.key.getAccessor(), key);
-                    vertexPropertyNode.setProperty(T.value.getAccessor(), value);
-                    vertexPropertyNode.setProperty(key, value);
-                    node.connectTo(vertexPropertyNode, prefixedKey);
-                    final Neo4jVertexProperty<V> property = new Neo4jVertexProperty<>(vertex, key, value, vertexPropertyNode);
-                    ElementHelper.attachProperties(property, keyValues); // TODO: make this inlined
-                    return property;
-                }
-            } else {
-                node.setProperty(key, value);
-                final Neo4jVertexProperty<V> property = new Neo4jVertexProperty<>(vertex, key, value);
-                ElementHelper.attachProperties(property, keyValues); // TODO: make this inlined
-                return property;
-            }
-        } catch (final IllegalArgumentException iae) {
-            throw Property.Exceptions.dataTypeOfPropertyValueNotSupported(value, iae);
-        }
-    }
-
-    @Override
-    public VertexProperty.Cardinality getCardinality(final String key) {
-        return VertexProperty.Cardinality.list;
-    }
-
-    @Override
-    public boolean supportsMultiProperties() {
-        return true;
-    }
-
-    @Override
-    public boolean supportsMetaProperties() {
-        return true;
-    }
-
-    @Override
-    public void removeVertexProperty(final Neo4jVertexProperty vertexProperty) {
-        final Neo4jNode vertexPropertyNode = Neo4jHelper.getVertexPropertyNode(vertexProperty);
-        final Neo4jNode vertexNode = ((Neo4jVertex) vertexProperty.element()).getBaseVertex();
-        if (null == vertexPropertyNode) {
-            if (vertexNode.degree(Neo4jDirection.OUTGOING, Graph.Hidden.hide(vertexProperty.key())) == 0) {
-                if (vertexNode.hasProperty(vertexProperty.key()))
-                    vertexNode.removeProperty(vertexProperty.key());
-            }
-        } else {
-            vertexPropertyNode.relationships(Neo4jDirection.BOTH).forEach(Neo4jRelationship::delete);
-            vertexPropertyNode.delete();
-            if (vertexNode.degree(Neo4jDirection.OUTGOING, Graph.Hidden.hide(vertexProperty.key())) == 0) {
-                if (vertexNode.hasProperty(vertexProperty.key()))
-                    vertexNode.removeProperty(vertexProperty.key());
-            }
-        }
-    }
-
-    @Override
-    public <V> Property<V> setProperty(final Neo4jVertexProperty vertexProperty, final String key, final V value) {
-        final Neo4jNode vertexPropertyNode = Neo4jHelper.getVertexPropertyNode(vertexProperty);
-        if (null != vertexPropertyNode) {
-            vertexPropertyNode.setProperty(key, value);
-            return new Neo4jProperty<>(vertexProperty, key, value);
-        } else {
-            final Neo4jNode vertexNode = ((Neo4jVertex) vertexProperty.element()).getBaseVertex();
-            final Neo4jNode newVertexPropertyNode = ((WrappedGraph<Neo4jGraphAPI>) vertexProperty.element().graph()).getBaseGraph().createNode(VERTEX_PROPERTY_LABEL, vertexProperty.label());
-            newVertexPropertyNode.setProperty(T.key.getAccessor(), vertexProperty.key());
-            newVertexPropertyNode.setProperty(T.value.getAccessor(), vertexProperty.value());
-            newVertexPropertyNode.setProperty(vertexProperty.key(), vertexProperty.value());
-            newVertexPropertyNode.setProperty(key, value);
-            vertexNode.connectTo(newVertexPropertyNode, Graph.Hidden.hide(vertexProperty.key()));
-            vertexNode.setProperty(vertexProperty.key(), VERTEX_PROPERTY_TOKEN);
-            Neo4jHelper.setVertexPropertyNode(vertexProperty, newVertexPropertyNode);
-            return new Neo4jProperty<>(vertexProperty, key, value);
-        }
-    }
-
-    @Override
-    public <V> Property<V> getProperty(final Neo4jVertexProperty vertexProperty, final String key) {
-        final Neo4jNode vertexPropertyNode = Neo4jHelper.getVertexPropertyNode(vertexProperty);
-        if (null != vertexPropertyNode && vertexPropertyNode.hasProperty(key))
-            return new Neo4jProperty<>(vertexProperty, key, (V) vertexPropertyNode.getProperty(key));
-        else
-            return Property.empty();
-    }
-
-    @Override
-    public <V> Iterator<Property<V>> getProperties(final Neo4jVertexProperty vertexProperty, final String... keys) {
-        final Neo4jNode vertexPropertyNode = Neo4jHelper.getVertexPropertyNode(vertexProperty);
-        if (null == vertexPropertyNode)
-            return Collections.emptyIterator();
-        else
-            return IteratorUtils.stream(vertexPropertyNode.getKeys())
-                    .filter(key -> ElementHelper.keyExists(key, keys))
-                    .filter(key -> !key.equals(vertexProperty.key()))
-                    .map(key -> (Property<V>) new Neo4jProperty<>(vertexProperty, key, (V) vertexPropertyNode.getProperty(key))).iterator();
-
-    }
-
-    @Override
-    public Iterator<Vertex> lookupVertices(final Neo4jGraph graph, final List<HasContainer> hasContainers, final Object... ids) {
-        // ids are present, filter on them first
-        if (ids.length > 0)
-            return IteratorUtils.filter(graph.vertices(ids), vertex -> HasContainer.testAll(vertex, hasContainers));
-        ////// do index lookups //////
-        graph.tx().readWrite();
-        // get a label being search on
-        Optional<String> label = hasContainers.stream()
-                .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
-                .filter(hasContainer -> Compare.eq == hasContainer.getBiPredicate())
-                .map(hasContainer -> (String) hasContainer.getValue())
-                .findAny();
-        if (!label.isPresent())
-            label = hasContainers.stream()
-                    .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
-                    .filter(hasContainer -> hasContainer.getPredicate() instanceof LabelP)
-                    .map(hasContainer -> (String) hasContainer.getValue())
-                    .findAny();
-
-        if (label.isPresent()) {
-            // find a vertex by label and key/value
-            for (final HasContainer hasContainer : hasContainers) {
-                if (Compare.eq == hasContainer.getBiPredicate()) {
-                    if (graph.getBaseGraph().hasSchemaIndex(label.get(), hasContainer.getKey())) {
-                        return Stream.concat(
-                                IteratorUtils.stream(graph.getBaseGraph().findNodes(label.get(), hasContainer.getKey(), hasContainer.getValue()))
-                                        .filter(getNodePredicate())
-                                        .map(node -> (Vertex) new Neo4jVertex(node, graph))
-                                        .filter(vertex -> HasContainer.testAll(vertex, hasContainers)),
-                                IteratorUtils.stream(graph.getBaseGraph().findNodes(VERTEX_PROPERTY_LABEL, hasContainer.getKey(), hasContainer.getValue()))  // look up indexed vertex property nodes
-                                        .map(node -> node.relationships(Neo4jDirection.INCOMING).iterator().next().start())
-                                        .map(node -> (Vertex) new Neo4jVertex(node, graph))
-                                        .filter(vertex -> HasContainer.testAll(vertex, hasContainers))).iterator();
-                    }
-                }
-            }
-            // find a vertex by label
-            return IteratorUtils.stream(graph.getBaseGraph().findNodes(label.get()))
-                    .filter(getNodePredicate())
-                    .map(node -> (Vertex) new Neo4jVertex(node, graph))
-                    .filter(vertex -> HasContainer.testAll(vertex, hasContainers)).iterator();
-        } else {
-            // linear scan
-            return IteratorUtils.filter(graph.vertices(), vertex -> HasContainer.testAll(vertex, hasContainers));
-        }
-    }
-}
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java
deleted file mode 100644
index 085b3a4..0000000
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.neo4j.structure.trait;
-
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.neo4j.tinkerpop.api.Neo4jNode;
-import org.neo4j.tinkerpop.api.Neo4jRelationship;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.function.Predicate;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @deprecated As of release 3.3.8, not replaced.
- */
-@Deprecated
-public interface Neo4jTrait {
-
-    public Predicate<Neo4jNode> getNodePredicate();
-
-    public Predicate<Neo4jRelationship> getRelationshipPredicate();
-
-    public void removeVertex(final Neo4jVertex vertex);
-
-    public <V> VertexProperty<V> getVertexProperty(final Neo4jVertex vertex, final String key);
-
-    public <V> Iterator<VertexProperty<V>> getVertexProperties(final Neo4jVertex vertex, final String... keys);
-
-    public <V> VertexProperty<V> setVertexProperty(final Neo4jVertex vertex, final VertexProperty.Cardinality cardinality, final String key, final V value, final Object... keyValues);
-
-    ////
-
-    public boolean supportsMultiProperties();
-
-    public boolean supportsMetaProperties();
-
-    public VertexProperty.Cardinality getCardinality(final String key);
-
-    public void removeVertexProperty(final Neo4jVertexProperty vertexProperty);
-
-    public <V> Property<V> setProperty(final Neo4jVertexProperty vertexProperty, final String key, final V value);
-
-    public <V> Property<V> getProperty(final Neo4jVertexProperty vertexProperty, final String key);
-
-    public <V> Iterator<Property<V>> getProperties(final Neo4jVertexProperty vertexProperty, final String... keys);
-
-    ////
-
-    public Iterator<Vertex> lookupVertices(final Neo4jGraph graph, final List<HasContainer> hasContainers, final Object... ids);
-
-}
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java
deleted file mode 100644
index 119630f..0000000
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.neo4j.structure.trait;
-
-import org.apache.tinkerpop.gremlin.neo4j.process.traversal.LabelP;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jHelper;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty;
-import org.apache.tinkerpop.gremlin.process.traversal.Compare;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.neo4j.tinkerpop.api.Neo4jDirection;
-import org.neo4j.tinkerpop.api.Neo4jNode;
-import org.neo4j.tinkerpop.api.Neo4jRelationship;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Predicate;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @deprecated As of release 3.3.8, not replaced.
- */
-@Deprecated
-public final class NoMultiNoMetaNeo4jTrait implements Neo4jTrait {
-
-    private static final NoMultiNoMetaNeo4jTrait INSTANCE = new NoMultiNoMetaNeo4jTrait();
-
-    private final static Predicate TRUE_PREDICATE = x -> true;
-
-    public static NoMultiNoMetaNeo4jTrait instance() {
-        return INSTANCE;
-    }
-
-    private NoMultiNoMetaNeo4jTrait() {
-
-    }
-
-    @Override
-    public Predicate<Neo4jNode> getNodePredicate() {
-        return TRUE_PREDICATE;
-    }
-
-    @Override
-    public Predicate<Neo4jRelationship> getRelationshipPredicate() {
-        return TRUE_PREDICATE;
-    }
-
-    @Override
-    public void removeVertex(final Neo4jVertex vertex) {
-        try {
-            final Neo4jNode node = vertex.getBaseVertex();
-            for (final Neo4jRelationship relationship : node.relationships(Neo4jDirection.BOTH)) {
-                relationship.delete();
-            }
-            node.delete();
-        } catch (final IllegalStateException ignored) {
-            // this one happens if the vertex is still chilling in the tx
-        } catch (final RuntimeException ex) {
-            if (!Neo4jHelper.isNotFound(ex)) throw ex;
-            // this one happens if the vertex is committed
-        }
-    }
-
-    @Override
-    public <V> VertexProperty<V> getVertexProperty(final Neo4jVertex vertex, final String key) {
-        return vertex.getBaseVertex().hasProperty(key) ? new Neo4jVertexProperty<>(vertex, key, (V) vertex.getBaseVertex().getProperty(key)) : VertexProperty.<V>empty();
-    }
-
-    @Override
-    public <V> Iterator<VertexProperty<V>> getVertexProperties(final Neo4jVertex vertex, final String... keys) {
-        return (Iterator) IteratorUtils.stream(vertex.getBaseVertex().getKeys())
-                .filter(key -> ElementHelper.keyExists(key, keys))
-                .map(key -> new Neo4jVertexProperty<>(vertex, key, (V) vertex.getBaseVertex().getProperty(key))).iterator();
-    }
-
-    @Override
-    public <V> VertexProperty<V> setVertexProperty(final Neo4jVertex vertex, final VertexProperty.Cardinality cardinality, final String key, final V value, final Object... keyValues) {
-        if (cardinality != VertexProperty.Cardinality.single)
-            throw VertexProperty.Exceptions.multiPropertiesNotSupported();
-        if (keyValues.length > 0)
-            throw VertexProperty.Exceptions.metaPropertiesNotSupported();
-        try {
-            vertex.getBaseVertex().setProperty(key, value);
-            return new Neo4jVertexProperty<>(vertex, key, value);
-        } catch (final IllegalArgumentException iae) {
-            throw Property.Exceptions.dataTypeOfPropertyValueNotSupported(value, iae);
-        }
-    }
-
-    @Override
-    public VertexProperty.Cardinality getCardinality(final String key) {
-        return VertexProperty.Cardinality.single;
-    }
-
-    @Override
-    public boolean supportsMultiProperties() {
-        return false;
-    }
-
-    @Override
-    public boolean supportsMetaProperties() {
-        return false;
-    }
-
-    @Override
-    public void removeVertexProperty(final Neo4jVertexProperty vertexProperty) {
-        final Neo4jNode node = ((Neo4jVertex) vertexProperty.element()).getBaseVertex();
-        if (node.hasProperty(vertexProperty.key()))
-            node.removeProperty(vertexProperty.key());
-    }
-
-    @Override
-    public <V> Property<V> setProperty(final Neo4jVertexProperty vertexProperty, final String key, final V value) {
-        throw VertexProperty.Exceptions.metaPropertiesNotSupported();
-    }
-
-    @Override
-    public <V> Property<V> getProperty(final Neo4jVertexProperty vertexProperty, final String key) {
-        throw VertexProperty.Exceptions.metaPropertiesNotSupported();
-    }
-
-    @Override
-    public <V> Iterator<Property<V>> getProperties(final Neo4jVertexProperty vertexProperty, final String... keys) {
-        throw VertexProperty.Exceptions.metaPropertiesNotSupported();
-    }
-
-    @Override
-    public Iterator<Vertex> lookupVertices(final Neo4jGraph graph, final List<HasContainer> hasContainers, final Object... ids) {
-        // ids are present, filter on them first
-        if (ids.length > 0)
-            return IteratorUtils.filter(graph.vertices(ids), vertex -> HasContainer.testAll(vertex, hasContainers));
-        ////// do index lookups //////
-        graph.tx().readWrite();
-        // get a label being search on
-        Optional<String> label = hasContainers.stream()
-                .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
-                .filter(hasContainer -> Compare.eq == hasContainer.getBiPredicate())
-                .map(hasContainer -> (String) hasContainer.getValue())
-                .findAny();
-        if (!label.isPresent())
-            label = hasContainers.stream()
-                    .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
-                    .filter(hasContainer -> hasContainer.getPredicate() instanceof LabelP)
-                    .map(hasContainer -> (String) hasContainer.getValue())
-                    .findAny();
-
-        if (label.isPresent()) {
-            // find a vertex by label and key/value
-            for (final HasContainer hasContainer : hasContainers) {
-                if (Compare.eq == hasContainer.getBiPredicate() && !hasContainer.getKey().equals(T.label.getAccessor())) {
-                    if (graph.getBaseGraph().hasSchemaIndex(label.get(), hasContainer.getKey())) {
-                        return IteratorUtils.stream(graph.getBaseGraph().findNodes(label.get(), hasContainer.getKey(), hasContainer.getValue()))
-                                .map(node -> (Vertex) new Neo4jVertex(node, graph))
-                                .filter(vertex -> HasContainer.testAll(vertex, hasContainers)).iterator();
-                    }
-                }
-            }
-            // find a vertex by label
-            return IteratorUtils.stream(graph.getBaseGraph().findNodes(label.get()))
-                    .map(node -> (Vertex) new Neo4jVertex(node, graph))
-                    .filter(vertex -> HasContainer.testAll(vertex, hasContainers)).iterator();
-        } else {
-            // linear scan
-            return IteratorUtils.filter(graph.vertices(), vertex -> HasContainer.testAll(vertex, hasContainers));
-        }
-    }
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
index 98e1f5b..7ebd3ec 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.neo4j;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGraphProvider;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.TestHelper;
@@ -112,10 +112,6 @@
             graph.cypher("DROP INDEX ON :vertex(age)").iterate();
             graph.cypher("DROP INDEX ON :vertex(lang)").iterate();
             graph.tx().commit();
-        } else {
-            // TODO: add CREW work here.
-            // TODO: add meta_property indices when meta_property graph is provided
-            //throw new RuntimeException("Could not load graph with " + graphData);
         }
     }
 
@@ -160,10 +156,6 @@
                     graph.cypher("CREATE INDEX ON :vertex(lang)").iterate();
                 graph.tx().commit();
             } // else no indices
-        } else {
-            // TODO: add CREW work here.
-            // TODO: add meta_property indices when meta_property graph is provided
-            //throw new RuntimeException("Could not load graph with " + graphData);
         }
     }
 
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/MultiMetaNeo4jGraphNativeNeo4jTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/MultiMetaNeo4jGraphNativeNeo4jTest.java
deleted file mode 100644
index f2caa9b..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/MultiMetaNeo4jGraphNativeNeo4jTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.neo4j;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.neo4j.MultiMetaNeo4jGraphProvider;
-import org.apache.tinkerpop.gremlin.neo4j.NativeNeo4jSuite;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.junit.runner.RunWith;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@RunWith(NativeNeo4jSuite.class)
-@GraphProviderClass(provider = MultiMetaNeo4jGraphProvider.class, graph = Neo4jGraph.class)
-public class MultiMetaNeo4jGraphNativeNeo4jTest {
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/MultiMetaNeo4jGraphProvider.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/MultiMetaNeo4jGraphProvider.java
deleted file mode 100644
index c7f082c..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/MultiMetaNeo4jGraphProvider.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.neo4j;
-
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class MultiMetaNeo4jGraphProvider extends AbstractNeo4jGraphProvider {
-    @Override
-    public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData graphData) {
-        final String directory = makeTestDirectory(graphName, test, testMethodName);
-
-        return new HashMap<String, Object>() {{
-            put(Graph.GRAPH, Neo4jGraph.class.getName());
-            put(Neo4jGraph.CONFIG_DIRECTORY, directory);
-            put(Neo4jGraph.CONFIG_META_PROPERTIES, true);
-            put(Neo4jGraph.CONFIG_MULTI_PROPERTIES, true);
-            put(Neo4jGraph.CONFIG_CONF + ".dbms.memory.pagecache.size", "1m");
-        }};
-    }
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphNativeNeo4jTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphNativeNeo4jTest.java
new file mode 100644
index 0000000..b212f78
--- /dev/null
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphNativeNeo4jTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.neo4j;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(NativeNeo4jSuite.class)
+@GraphProviderClass(provider = Neo4jGraphProvider.class, graph = Neo4jGraph.class)
+public class Neo4jGraphNativeNeo4jTest {
+}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphProvider.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphProvider.java
new file mode 100644
index 0000000..c95d2d3
--- /dev/null
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphProvider.java
@@ -0,0 +1,42 @@
+/*
+ * 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.neo4j;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class Neo4jGraphProvider extends AbstractNeo4jGraphProvider {
+    @Override
+    public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData graphData) {
+        final String directory = makeTestDirectory(graphName, test, testMethodName);
+
+        return new HashMap<String, Object>() {{
+            put(Graph.GRAPH, Neo4jGraph.class.getName());
+            put(Neo4jGraph.CONFIG_DIRECTORY, directory);
+            put(Neo4jGraph.CONFIG_CONF + ".dbms.memory.pagecache.size", "1m");
+        }};
+    }
+}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NoMultiNoMetaNeo4jGraphNativeNeo4jTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NoMultiNoMetaNeo4jGraphNativeNeo4jTest.java
deleted file mode 100644
index e186685..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NoMultiNoMetaNeo4jGraphNativeNeo4jTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.neo4j;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.neo4j.NativeNeo4jSuite;
-import org.apache.tinkerpop.gremlin.neo4j.NoMultiNoMetaNeo4jGraphProvider;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.junit.runner.RunWith;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@RunWith(NativeNeo4jSuite.class)
-@GraphProviderClass(provider = NoMultiNoMetaNeo4jGraphProvider.class, graph = Neo4jGraph.class)
-public class NoMultiNoMetaNeo4jGraphNativeNeo4jTest {
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NoMultiNoMetaNeo4jGraphProvider.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NoMultiNoMetaNeo4jGraphProvider.java
deleted file mode 100644
index d0b015e..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NoMultiNoMetaNeo4jGraphProvider.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.neo4j;
-
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class NoMultiNoMetaNeo4jGraphProvider extends AbstractNeo4jGraphProvider {
-    @Override
-    public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData graphData) {
-        final String directory = makeTestDirectory(graphName, test, testMethodName);
-
-        return new HashMap<String, Object>() {{
-            put(Graph.GRAPH, Neo4jGraph.class.getName());
-            put(Neo4jGraph.CONFIG_DIRECTORY, directory);
-            put(Neo4jGraph.CONFIG_META_PROPERTIES, false);
-            put(Neo4jGraph.CONFIG_MULTI_PROPERTIES, false);
-            put(Neo4jGraph.CONFIG_CONF + ".dbms.memory.pagecache.size", "1m");
-        }};
-    }
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/MultiMetaNeo4jGraphProcessStandardTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/MultiMetaNeo4jGraphProcessStandardTest.java
deleted file mode 100644
index 62f7b83..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/MultiMetaNeo4jGraphProcessStandardTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.neo4j.process;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.neo4j.MultiMetaNeo4jGraphProvider;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite;
-import org.junit.runner.RunWith;
-
-
-/**
- * Executes the Standard Gremlin Structure Test Suite using Neo4j.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@RunWith(ProcessStandardSuite.class)
-@GraphProviderClass(provider = MultiMetaNeo4jGraphProvider.class, graph = Neo4jGraph.class)
-public class MultiMetaNeo4jGraphProcessStandardTest {
-}
\ No newline at end of file
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/Neo4jGraphProcessStandardTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/Neo4jGraphProcessStandardTest.java
new file mode 100644
index 0000000..3f2e819
--- /dev/null
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/Neo4jGraphProcessStandardTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.neo4j.process;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.neo4j.Neo4jGraphProvider;
+import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
+import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(ProcessStandardSuite.class)
+@GraphProviderClass(provider = Neo4jGraphProvider.class, graph = Neo4jGraph.class)
+public class Neo4jGraphProcessStandardTest {
+}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/NoMultiNoMetaNeo4jGraphProcessStandardTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/NoMultiNoMetaNeo4jGraphProcessStandardTest.java
deleted file mode 100644
index b1b60be..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/process/NoMultiNoMetaNeo4jGraphProcessStandardTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.neo4j.process;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.neo4j.NoMultiNoMetaNeo4jGraphProvider;
-import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
-import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite;
-import org.junit.runner.RunWith;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@RunWith(ProcessStandardSuite.class)
-@GraphProviderClass(provider = NoMultiNoMetaNeo4jGraphProvider.class, graph = Neo4jGraph.class)
-public class NoMultiNoMetaNeo4jGraphProcessStandardTest {
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/MultiMetaNeo4jGraphStructureStandardTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/MultiMetaNeo4jGraphStructureStandardTest.java
deleted file mode 100644
index 0e56f28..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/MultiMetaNeo4jGraphStructureStandardTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.neo4j.structure;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.neo4j.MultiMetaNeo4jGraphProvider;
-import org.apache.tinkerpop.gremlin.structure.StructureStandardSuite;
-import org.junit.runner.RunWith;
-
-
-/**
- * Executes the Standard Gremlin Structure Test Suite using Neo4j.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@RunWith(StructureStandardSuite.class)
-@GraphProviderClass(provider = MultiMetaNeo4jGraphProvider.class, graph = Neo4jGraph.class)
-public class MultiMetaNeo4jGraphStructureStandardTest {
-}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexCheck.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexCheck.java
index 3591804..3f8f6bd 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexCheck.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexCheck.java
@@ -20,7 +20,6 @@
 
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.neo4j.AbstractNeo4jGremlinTest;
-import org.apache.tinkerpop.gremlin.neo4j.structure.trait.MultiMetaNeo4jTrait;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -83,47 +82,6 @@
     }
 
     @Test
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES)
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES)
-    public void shouldHaveFasterRuntimeWithLabelKeyValueIndexOnMultiProperties() throws Exception {
-        final Neo4jGraph neo4j = (Neo4jGraph) this.graph;
-        int maxVertices = 10000;
-        for (int i = 0; i < maxVertices; i++) {
-            if (i % 2 == 0)
-                this.graph.addVertex(T.label, "something", "myId", i, "myId", i + maxVertices + 1);
-            else
-                this.graph.addVertex(T.label, "nothing", "myId", i, "myId", i + maxVertices + 1);
-        }
-        this.graph.tx().commit();
-
-        // traversal
-        final Runnable traversal = () -> {
-            final Traversal<Vertex, Vertex> t = g.V().hasLabel("something").has("myId", 2000 + maxVertices + 1);
-            final Vertex vertex = t.tryNext().get();
-            assertFalse(t.hasNext());
-            assertEquals(2, IteratorUtils.count(vertex.properties("myId")));
-            assertEquals("something", vertex.label());
-        };
-
-        // no index
-        this.graph.tx().readWrite();
-        assertFalse(this.getBaseGraph().hasSchemaIndex("something", "myId"));
-        TimeUtil.clock(20, traversal);
-        final double noIndexTime = TimeUtil.clock(20, traversal);
-        // index time
-        neo4j.cypher("CREATE INDEX ON :something(myId)").iterate();
-        neo4j.cypher("CREATE INDEX ON :vertexProperty(myId)").iterate();
-        this.graph.tx().commit();
-        this.graph.tx().readWrite();
-        Thread.sleep(5000); // wait for indices to be built
-        assertTrue(this.getBaseGraph().hasSchemaIndex("something", "myId"));
-        TimeUtil.clock(20, traversal);
-        final double indexTime = TimeUtil.clock(20, traversal);
-        logger.info("Query time (no-index vs. index): {}", noIndexTime + " vs. {}", indexTime);
-        assertTrue((noIndexTime / 10) > indexTime); // should be at least 10x faster
-    }
-
-    @Test
     public void shouldReturnResultsLabeledIndexOnVertexWithHasHas() {
         this.graph.tx().readWrite();
         this.getBaseGraph().execute("CREATE INDEX ON :Person(name)", null);
@@ -289,61 +247,6 @@
     }
 
     @Test
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES)
-    public void shouldSupportVertexPropertyToVertexMappingOnIndexCalls() {
-        graph.tx().readWrite();
-        this.getBaseGraph().execute("CREATE INDEX ON :person(name)", null);
-//            this.graph.getBaseGraph().execute("CREATE INDEX ON :name(" + T.value.getAccessor() + ")", null);
-        this.graph.tx().commit();
-
-        final Vertex a = graph.addVertex(T.label, "person", "name", "marko", "age", 34);
-        a.property(VertexProperty.Cardinality.list, "name", "okram");
-        a.property(VertexProperty.Cardinality.list, "name", "marko a. rodriguez");
-        final Vertex b = graph.addVertex(T.label, "person", "name", "stephen");
-        final Vertex c = graph.addVertex("name", "matthias", "name", "mbroecheler");
-
-        tryCommit(graph, graph -> {
-            assertEquals(a.id(), g.V().has("person", "name", "okram").id().next());
-            assertEquals(1, g.V().has("person", "name", "okram").count().next().intValue());
-            assertEquals(34, ((Neo4jVertex) g.V().has("person", "name", "okram").next()).getBaseVertex().getProperty("age"));
-            assertEquals(MultiMetaNeo4jTrait.VERTEX_PROPERTY_TOKEN, ((Neo4jVertex) g.V().has("person", "name", "okram").next()).getBaseVertex().getProperty("name"));
-            ///
-            assertEquals(b.id(), g.V().has("person", "name", "stephen").id().next());
-            assertEquals(1, g.V().has("person", "name", "stephen").count().next().intValue());
-            assertEquals("stephen", ((Neo4jVertex) g.V().has("person", "name", "stephen").next()).getBaseVertex().getProperty("name"));
-            ///
-            assertEquals(c.id(), g.V().has("name", "matthias").id().next());
-            assertEquals(c.id(), g.V().has("name", "mbroecheler").id().next());
-            assertEquals(1, g.V().has("name", "matthias").count().next().intValue());
-            assertEquals(1, g.V().has("name", "mbroecheler").count().next().intValue());
-            assertEquals(0, g.V().has("person", "name", "matthias").count().next().intValue());
-            assertEquals(0, g.V().has("person", "name", "mbroecheler").count().next().intValue());
-        });
-
-        final Vertex d = graph.addVertex(T.label, "person", "name", "kuppitz");
-        tryCommit(graph, graph -> {
-            assertEquals(d.id(), g.V().has("person", "name", "kuppitz").id().next());
-            assertEquals("kuppitz", ((Neo4jVertex) g.V().has("person", "name", "kuppitz").next()).getBaseVertex().getProperty("name"));
-        });
-        d.property(VertexProperty.Cardinality.list, "name", "daniel", "acl", "private");
-        tryCommit(graph, graph -> {
-            assertEquals(d.id(), g.V().has("person", "name", P.within("daniel", "kuppitz")).id().next());
-            assertEquals(d.id(), g.V().has("person", "name", "kuppitz").id().next());
-            assertEquals(d.id(), g.V().has("person", "name", "daniel").id().next());
-            assertEquals(MultiMetaNeo4jTrait.VERTEX_PROPERTY_TOKEN, ((Neo4jVertex) g.V().has("person", "name", "kuppitz").next()).getBaseVertex().getProperty("name"));
-        });
-        d.property(VertexProperty.Cardinality.list, "name", "marko", "acl", "private");
-        tryCommit(graph, graph -> {
-            assertEquals(2, g.V().has("person", "name", "marko").count().next().intValue());
-            assertEquals(1, g.V().has("person", "name", "marko").properties("name").has(T.value, "marko").has("acl", "private").count().next().intValue());
-            g.V().has("person", "name", "marko").forEachRemaining(v -> {
-                assertEquals(MultiMetaNeo4jTrait.VERTEX_PROPERTY_TOKEN, ((Neo4jVertex) v).getBaseVertex().getProperty("name"));
-            });
-
-        });
-    }
-
-    @Test
     public void shouldDoLabelsNamespaceBehavior() {
         graph.tx().readWrite();
 
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureCheck.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureCheck.java
index 8215ad3..2338a94 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureCheck.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureCheck.java
@@ -21,7 +21,6 @@
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
 import org.apache.tinkerpop.gremlin.neo4j.AbstractNeo4jGremlinTest;
 import org.apache.tinkerpop.gremlin.neo4j.process.traversal.LabelP;
-import org.apache.tinkerpop.gremlin.neo4j.structure.trait.MultiMetaNeo4jTrait;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -153,9 +152,7 @@
     }
 
     @Test
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES, supported = false)
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES, supported = false)
-    public void shouldNotGenerateNodesAndRelationshipsForNoMultiPropertiesNoMetaProperties() {
+    public void shouldNotGenerateNodesAndRelationships() {
         graph.tx().readWrite();
         tryCommit(graph, graph -> validateCounts(0, 0, 0, 0));
         Vertex vertex = graph.addVertex(T.label, "person");
@@ -183,201 +180,6 @@
     }
 
     @Test
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES)
-    public void shouldGenerateNodesAndRelationshipsCorrectlyForVertexProperties() {
-
-        graph.tx().readWrite();
-        Neo4jVertex a = (Neo4jVertex) graph.addVertex("name", "marko", "name", "okram");
-        Neo4jVertex b = (Neo4jVertex) graph.addVertex("name", "stephen", "location", "virginia");
-
-        tryCommit(graph, graph -> {
-            assertEquals(2, g.V().count().next().intValue());
-            // assertEquals(2, a.properties("name").count().next().intValue());
-            // assertEquals(1, b.properties("name").count().next().intValue());
-            // assertEquals(1, b.properties("location").count().next().intValue());
-            assertEquals(0, g.E().count().next().intValue());
-
-            assertEquals(4l, this.getBaseGraph().execute("MATCH (n) RETURN COUNT(n)", null).next().get("COUNT(n)"));
-            assertEquals(2l, this.getBaseGraph().execute("MATCH (n)-[r]->(m) RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            assertEquals(2l, this.getBaseGraph().execute("MATCH (a)-[r]->() WHERE id(a) = " + a.id() + " RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            final AtomicInteger counter = new AtomicInteger(0);
-            a.getBaseVertex().relationships(Neo4jDirection.OUTGOING).forEach(relationship -> {
-                assertEquals(Graph.Hidden.hide("name"), relationship.type());
-                counter.incrementAndGet();
-            });
-            assertEquals(2, counter.getAndSet(0));
-            this.getBaseGraph().execute("MATCH (a)-->(m) WHERE id(a) = " + a.id() + " RETURN labels(m)", null).forEachRemaining(results -> {
-                assertEquals(true, ((List<String>) results.get("labels(m)")).contains(VertexProperty.DEFAULT_LABEL));
-                counter.incrementAndGet();
-            });
-            assertEquals(2, counter.getAndSet(0));
-            IteratorUtils.stream(a.getBaseVertex().relationships(Neo4jDirection.OUTGOING)).map(Neo4jRelationship::end).forEach(node -> {
-                assertEquals(3, IteratorUtils.count(node.getKeys()));  // T.key, T.value, key
-                assertEquals("name", node.getProperty(T.key.getAccessor()));
-                assertTrue("marko".equals(node.getProperty(T.value.getAccessor())) || "okram".equals(node.getProperty(T.value.getAccessor())));
-                assertEquals(0, node.degree(Neo4jDirection.OUTGOING, null));
-                assertEquals(1, node.degree(Neo4jDirection.INCOMING, null));
-                assertEquals(Graph.Hidden.hide("name"), node.relationships(Neo4jDirection.INCOMING).iterator().next().type());
-                counter.incrementAndGet();
-            });
-            assertEquals(2, counter.getAndSet(0));
-
-            assertEquals(2, IteratorUtils.count(b.getBaseVertex().getKeys()));
-            assertEquals("stephen", b.getBaseVertex().getProperty("name"));
-            assertEquals("virginia", b.getBaseVertex().getProperty("location"));
-        });
-
-        a.property("name", "the marko");
-        tryCommit(graph, graph -> {
-            assertEquals(2, g.V().count().next().intValue());
-            //assertEquals(1, a.prope rties().count().next().intValue());
-            //  assertEquals(1, b.properties("name").count().next().intValue());
-            // assertEquals(1, b.properties("location").count().next().intValue());
-            assertEquals(0, g.E().count().next().intValue());
-            assertEquals(2l, this.getBaseGraph().execute("MATCH (n) RETURN COUNT(n)", null).next().get("COUNT(n)"));
-            assertEquals(0l, this.getBaseGraph().execute("MATCH (n)-[r]->(m) RETURN COUNT(r)", null).next().get("COUNT(r)"));
-
-            assertEquals(1, IteratorUtils.count(a.getBaseVertex().getKeys()));
-            assertEquals("the marko", a.getBaseVertex().getProperty("name"));
-            assertEquals(2, IteratorUtils.count(b.getBaseVertex().getKeys()));
-            assertEquals("stephen", b.getBaseVertex().getProperty("name"));
-            assertEquals("virginia", b.getBaseVertex().getProperty("location"));
-        });
-
-        a.property("name").remove();
-        tryCommit(graph, graph -> {
-            assertEquals(2, g.V().count().next().intValue());
-            //    assertEquals(0, a.properties().count().next().intValue());
-            //   assertEquals(2, b.properties().count().next().intValue());
-            assertEquals(0, g.E().count().next().intValue());
-            assertEquals(2l, this.getBaseGraph().execute("MATCH (n) RETURN COUNT(n)", null).next().get("COUNT(n)"));
-            assertEquals(0l, this.getBaseGraph().execute("MATCH (n)-[r]->(m) RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            assertEquals(0, IteratorUtils.count(a.getBaseVertex().getKeys()));
-            assertEquals(2, IteratorUtils.count(b.getBaseVertex().getKeys()));
-        });
-
-        graph.tx().commit();
-        a.property("name", "the marko", "acl", "private");
-        tryCommit(graph, graph -> {
-            assertEquals(2, g.V().count().next().intValue());
-            // assertEquals(1, a.properties("name").count().next().intValue());
-            // assertEquals(1, b.properties("name").count().next().intValue());
-            // assertEquals(1, b.properties("location").count().next().intValue());
-            assertEquals(0, g.E().count().next().intValue());
-
-            assertEquals(3l, this.getBaseGraph().execute("MATCH (n) RETURN COUNT(n)", null).next().get("COUNT(n)"));
-            assertEquals(1l, this.getBaseGraph().execute("MATCH (n)-[r]->(m) RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            assertEquals(1l, this.getBaseGraph().execute("MATCH (a)-[r]->() WHERE id(a) = " + a.id() + " RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            final AtomicInteger counter = new AtomicInteger(0);
-            a.getBaseVertex().relationships(Neo4jDirection.OUTGOING).forEach(relationship -> {
-                assertEquals(Graph.Hidden.hide("name"), relationship.type());
-                counter.incrementAndGet();
-            });
-            assertEquals(1, counter.getAndSet(0));
-            this.getBaseGraph().execute("MATCH (a)-->(m) WHERE id(a) = " + a.id() + " RETURN labels(m)", null).forEachRemaining(results -> {
-                assertEquals(true, ((List<String>) results.get("labels(m)")).contains(VertexProperty.DEFAULT_LABEL));
-                counter.incrementAndGet();
-            });
-            assertEquals(1, counter.getAndSet(0));
-            IteratorUtils.stream(a.getBaseVertex().relationships(Neo4jDirection.OUTGOING)).map(Neo4jRelationship::end).forEach(node -> {
-                assertEquals(4, IteratorUtils.count(node.getKeys()));
-                assertEquals("name", node.getProperty(T.key.getAccessor()));
-                assertEquals("the marko", node.getProperty(T.value.getAccessor()));
-                assertEquals("private", node.getProperty("acl"));
-                assertEquals(0, node.degree(Neo4jDirection.OUTGOING, null));
-                assertEquals(1, node.degree(Neo4jDirection.INCOMING, null));
-                assertEquals(Graph.Hidden.hide("name"), node.relationships(Neo4jDirection.INCOMING).iterator().next().type());
-                counter.incrementAndGet();
-            });
-            assertEquals(1, counter.getAndSet(0));
-
-            assertEquals(1, IteratorUtils.count(a.getBaseVertex().getKeys()));
-            assertTrue(a.getBaseVertex().hasProperty("name"));
-            assertEquals(MultiMetaNeo4jTrait.VERTEX_PROPERTY_TOKEN, a.getBaseVertex().getProperty("name"));
-            assertEquals(2, IteratorUtils.count(b.getBaseVertex().getKeys()));
-            assertEquals("stephen", b.getBaseVertex().getProperty("name"));
-            assertEquals("virginia", b.getBaseVertex().getProperty("location"));
-        });
-
-        a.property(VertexProperty.Cardinality.list, "name", "marko", "acl", "private");
-        a.property(VertexProperty.Cardinality.list, "name", "okram", "acl", "public");
-        a.property(VertexProperty.Cardinality.single, "name", "the marko", "acl", "private");
-        tryCommit(graph, graph -> {
-            assertEquals(2, g.V().count().next().intValue());
-            //assertEquals(1, a.properties("name").count().next().intValue());
-            //assertEquals(1, b.properties("name").count().next().intValue());
-            //assertEquals(1, b.properties("location").count().next().intValue());
-            assertEquals(0, g.E().count().next().intValue());
-
-            assertEquals(3l, this.getBaseGraph().execute("MATCH (n) RETURN COUNT(n)", null).next().get("COUNT(n)"));
-            assertEquals(1l, this.getBaseGraph().execute("MATCH (n)-[r]->(m) RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            assertEquals(1l, this.getBaseGraph().execute("MATCH (a)-[r]->() WHERE id(a) = " + a.id() + " RETURN COUNT(r)", null).next().get("COUNT(r)"));
-            final AtomicInteger counter = new AtomicInteger(0);
-            a.getBaseVertex().relationships(Neo4jDirection.OUTGOING).forEach(relationship -> {
-                assertEquals(Graph.Hidden.hide("name"), relationship.type());
-                counter.incrementAndGet();
-            });
-            assertEquals(1, counter.getAndSet(0));
-            this.getBaseGraph().execute("MATCH (a)-->(m) WHERE id(a) = " + a.id() + " RETURN labels(m)", null).forEachRemaining(results -> {
-                assertEquals(true, ((List<String>) results.get("labels(m)")).contains(VertexProperty.DEFAULT_LABEL));
-                counter.incrementAndGet();
-            });
-            assertEquals(1, counter.getAndSet(0));
-            IteratorUtils.stream(a.getBaseVertex().relationships(Neo4jDirection.OUTGOING)).map(Neo4jRelationship::end).forEach(node -> {
-                assertEquals(4, IteratorUtils.count(node.getKeys()));
-                assertEquals("name", node.getProperty(T.key.getAccessor()));
-                assertEquals("the marko", node.getProperty(T.value.getAccessor()));
-                assertEquals("private", node.getProperty("acl"));
-                assertEquals(0, node.degree(Neo4jDirection.OUTGOING, null));
-                assertEquals(1, node.degree(Neo4jDirection.INCOMING, null));
-                assertEquals(Graph.Hidden.hide("name"), node.relationships(Neo4jDirection.INCOMING).iterator().next().type());
-                counter.incrementAndGet();
-            });
-            assertEquals(1, counter.getAndSet(0));
-
-            assertEquals(1, IteratorUtils.count(a.getBaseVertex().getKeys()));
-            assertTrue(a.getBaseVertex().hasProperty("name"));
-            assertEquals(MultiMetaNeo4jTrait.VERTEX_PROPERTY_TOKEN, a.getBaseVertex().getProperty("name"));
-            assertEquals(2, IteratorUtils.count(b.getBaseVertex().getKeys()));
-            assertEquals("stephen", b.getBaseVertex().getProperty("name"));
-            assertEquals("virginia", b.getBaseVertex().getProperty("location"));
-        });
-    }
-
-    @Test
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_MULTI_PROPERTIES)
-    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_META_PROPERTIES)
-    public void shouldNotGenerateNodesAndRelationshipsForMultiPropertiesWithSingle() {
-        graph.tx().readWrite();
-        tryCommit(graph, graph -> validateCounts(0, 0, 0, 0));
-        Vertex vertex = graph.addVertex(T.label, "person");
-        tryCommit(graph, graph -> validateCounts(1, 0, 1, 0));
-        vertex.property(VertexProperty.Cardinality.list, "name", "marko");
-        assertEquals("marko", vertex.value("name"));
-        tryCommit(graph, graph -> validateCounts(1, 0, 1, 0));
-        vertex.property(VertexProperty.Cardinality.single, "name", "okram");
-        tryCommit(graph, graph -> {
-            validateCounts(1, 0, 1, 0);
-            assertEquals("okram", vertex.value("name"));
-        });
-        VertexProperty vertexProperty = vertex.property("name");
-        tryCommit(graph, graph -> {
-            assertTrue(vertexProperty.isPresent());
-            assertEquals("name", vertexProperty.key());
-            assertEquals("okram", vertexProperty.value());
-            validateCounts(1, 0, 1, 0);
-        });
-
-        // now make it a meta property (and thus, force node/relationship creation)
-        vertexProperty.property("acl", "private");
-        tryCommit(graph, graph -> {
-            assertEquals("private", vertexProperty.value("acl"));
-            validateCounts(1, 0, 2, 1);
-        });
-
-    }
-
-    @Test
     public void shouldSupportNeo4jMultiLabels() {
         final Neo4jVertex vertex = (Neo4jVertex) graph.addVertex(T.label, "animal::person", "name", "marko");
         tryCommit(graph, graph -> {
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraphStructureStandardTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraphStructureStandardTest.java
new file mode 100644
index 0000000..827b304
--- /dev/null
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraphStructureStandardTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.neo4j.structure;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.neo4j.Neo4jGraphProvider;
+import org.apache.tinkerpop.gremlin.structure.StructureStandardSuite;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(StructureStandardSuite.class)
+@GraphProviderClass(provider = Neo4jGraphProvider.class, graph = Neo4jGraph.class)
+public class Neo4jGraphStructureStandardTest {
+}
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NoMultiNoMetaNeo4jGraphStructureStandardTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NoMultiNoMetaNeo4jGraphStructureStandardTest.java
deleted file mode 100644
index 976744f..0000000
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NoMultiNoMetaNeo4jGraphStructureStandardTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.neo4j.structure;
-
-import org.apache.tinkerpop.gremlin.GraphProviderClass;
-import org.apache.tinkerpop.gremlin.neo4j.NoMultiNoMetaNeo4jGraphProvider;
-import org.apache.tinkerpop.gremlin.structure.StructureStandardSuite;
-import org.junit.runner.RunWith;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@RunWith(StructureStandardSuite.class)
-@GraphProviderClass(provider = NoMultiNoMetaNeo4jGraphProvider.class, graph = Neo4jGraph.class)
-public class NoMultiNoMetaNeo4jGraphStructureStandardTest {
-}
diff --git a/pom.xml b/pom.xml
index 752a47d..605c4e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
     </parent>
     <groupId>org.apache.tinkerpop</groupId>
     <artifactId>tinkerpop</artifactId>
-    <version>3.4.9-SNAPSHOT</version>
+    <version>3.5.0-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>Apache TinkerPop</name>
     <description>A Graph Computing Framework</description>
@@ -146,24 +146,25 @@
         <url>https://github.com/apache/tinkerpop</url>
     </scm>
     <properties>
-        <commons.configuration.version>1.10</commons.configuration.version>
+        <commons.configuration.version>2.6</commons.configuration.version>
         <commons.lang.version>2.6</commons.lang.version>
         <commons.lang3.version>3.8.1</commons.lang3.version>
-        <groovy.version>2.5.11</groovy.version>
-        <hadoop.version>2.7.2</hadoop.version>
+        <groovy.version>3.0.3</groovy.version>
+        <hadoop.version>2.7.7</hadoop.version>
         <java.tuples.version>1.2</java.tuples.version>
-        <javadoc-plugin.version>2.10.4</javadoc-plugin.version>
+        <javadoc-plugin.version>3.1.0</javadoc-plugin.version>
         <jcabi.version>1.1</jcabi.version>
         <log4j.version>1.2.17</log4j.version>
         <metrics.version>3.0.2</metrics.version>
         <netty.version>4.1.49.Final</netty.version>
         <slf4j.version>1.7.25</slf4j.version>
         <snakeyaml.version>1.15</snakeyaml.version>
-        <spark.version>2.4.0</spark.version>
+        <spark.version>3.0.0</spark.version>
 
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <skipIntegrationTests>true</skipIntegrationTests>
+        <suresafeArgs> </suresafeArgs>
 
         <!--
         This file will come from the root of each modules test/resources/ directories. log4j-silent.properties will
@@ -188,7 +189,9 @@
                 <artifactId>maven-compiler-plugin</artifactId>
             </plugin>
             <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
+                <version>3.0.0-M2</version>
                 <executions>
                     <execution>
                         <id>enforce-all</id>
@@ -199,7 +202,7 @@
                             <rules>
                                 <DependencyConvergence/>
                                 <requireJavaVersion>
-                                    <version>[1.8.0-40,)</version>
+                                    <version>[1.8,12)</version>
                                 </requireJavaVersion>
                                 <requireMavenVersion>
                                     <version>[3.3.9,)</version>
@@ -237,7 +240,7 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
                 <configuration>
-                    <additionalparam>-Xdoclint:none</additionalparam>
+                    <additionalJOption>-Xdoclint:none</additionalJOption>
                     <tags>
                         <tag>
                             <name>example</name>
@@ -254,7 +257,7 @@
                         </goals>
                         <phase>site</phase>
                         <configuration>
-                            <additionalparam>-Xdoclint:none</additionalparam>
+                            <additionalJOption>-Xdoclint:none</additionalJOption>
                             <includeDependencySources>true</includeDependencySources>
                             <dependencySourceIncludes>
                                 <dependencySourceInclude>org.apache.tinkerpop:*</dependencySourceInclude>
@@ -359,6 +362,7 @@
                     <excludeSubProjects>false</excludeSubProjects>
                     <excludes>
                         <exclude>.mailmap</exclude>
+                        <exclude>.asf.yaml</exclude>
                         <exclude>.travis.yml</exclude>
                         <exclude>.travis.*.sh</exclude>
                         <exclude>.dockerignore</exclude>
@@ -403,10 +407,8 @@
                         <exclude>**/.vs/**</exclude>
                         <exclude>**/NuGet.Config</exclude>
                         <exclude>**/*.nuspec</exclude>
-                        <exclude>**/*.nuspec.template</exclude>
                         <exclude>**/gremlin-javascript/node_modules/**</exclude>
                         <exclude>**/gremlin-javascript/doc/**</exclude>
-                        <exclude>**/node/node_modules/**</exclude>
                         <exclude>**/node/**</exclude>
                         <exclude>**/npm-debug.log</exclude>
                         <exclude>**/_site/**</exclude>
@@ -442,10 +444,11 @@
         </plugins>
         <pluginManagement>
             <plugins>
+                <!-- there is a jdk11 profile that will be enabled if built with that version - these settings will be overriden -->
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-compiler-plugin</artifactId>
-                    <version>3.7.0</version>
+                    <version>3.8.1</version>
                     <configuration>
                         <source>1.8</source>
                         <target>1.8</target>
@@ -462,11 +465,14 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>2.21.0</version>
+                    <version>2.22.2</version>
                     <configuration>
-                        <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true
+                        <argLine>
+                            -Dlog4j.configuration=${log4j-test.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true ${suresafeArgs}
                         </argLine>
                         <trimStackTrace>false</trimStackTrace>
+                        <forkCount>1</forkCount>
+                        <reuseForks>false</reuseForks>
                         <excludes>
                             <exclude>**/*IntegrateTest.java</exclude>
                         </excludes>
@@ -475,7 +481,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-failsafe-plugin</artifactId>
-                    <version>2.21.0</version>
+                    <version>2.22.2</version>
                     <executions>
                         <execution>
                             <id>integration-test</id>
@@ -487,8 +493,11 @@
                                     <include>**/*IntegrateTest.java</include>
                                 </includes>
                                 <skipTests>${skipIntegrationTests}</skipTests>
-                                <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dhost=localhost -Dport=8182 -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true
+                                <argLine>
+                                    -Dlog4j.configuration=${log4j-test.properties} -Dhost=localhost -Dport=8182 -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true ${suresafeArgs}
                                 </argLine>
+                                <forkCount>1</forkCount>
+                                <reuseForks>false</reuseForks>
                                 <summaryFile>target/failsafe-reports/failsafe-integration.xml</summaryFile>
                             </configuration>
                         </execution>
@@ -524,6 +533,9 @@
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-javadoc-plugin</artifactId>
                     <version>${javadoc-plugin.version}</version>
+                    <configuration>
+                        <source>1.8</source>
+                    </configuration>
                 </plugin>
                 <plugin>
                     <groupId>org.codehaus.gmavenplus</groupId>
@@ -577,18 +589,16 @@
 
     <dependencyManagement>
         <dependencies>
-            <!-- commons-configuration drags in the old commons-lang. need to update someday -->
             <dependency>
-                <groupId>commons-configuration</groupId>
-                <artifactId>commons-configuration</artifactId>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-configuration2</artifactId>
                 <version>${commons.configuration.version}</version>
-                <exclusions>
-                    <!-- self-conflict -->
-                    <exclusion>
-                        <groupId>commons-logging</groupId>
-                        <artifactId>commons-logging</artifactId>
-                    </exclusion>
-                </exclusions>
+            </dependency>
+            <!-- commons-configuration2 requires beanutils because we rely on file loaders -->
+            <dependency>
+                <groupId>commons-beanutils</groupId>
+                <artifactId>commons-beanutils</artifactId>
+                <version>1.9.4</version>
             </dependency>
             <dependency>
                 <groupId>commons-collections</groupId>
@@ -712,7 +722,7 @@
             <dependency>
                 <groupId>org.mockito</groupId>
                 <artifactId>mockito-core</artifactId>
-                <version>1.10.19</version>
+                <version>3.2.4</version>
                 <exclusions>
                     <exclusion>
                         <groupId>org.hamcrest</groupId>
@@ -722,8 +732,8 @@
             </dependency>
             <dependency>
                 <groupId>org.hamcrest</groupId>
-                <artifactId>hamcrest-all</artifactId>
-                <version>1.3</version>
+                <artifactId>hamcrest</artifactId>
+                <version>2.2</version>
             </dependency>
             <dependency>
                 <groupId>org.slf4j</groupId>
@@ -761,6 +771,33 @@
     <profiles>
 
         <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <properties>
+                <suresafeArgs>--illegal-access=permit</suresafeArgs>
+            </properties>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.apache.maven.plugins</groupId>
+                            <artifactId>maven-compiler-plugin</artifactId>
+                            <version>3.8.1</version>
+                            <configuration>
+                                <release>8</release>
+                                <compilerArgs>
+                                    <arg>-parameters</arg>
+                                </compilerArgs>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+            </build>
+        </profile>
+
+        <profile>
             <id>asciidoc</id>
             <activation>
                 <activeByDefault>false</activeByDefault>
@@ -1204,12 +1241,16 @@
                                 <inherited>false</inherited>
                                 <configuration>
                                     <destDir>full</destDir>
-                                    <additionalparam>-Xdoclint:none</additionalparam>
+                                    <additionalJOption>-Xdoclint:none</additionalJOption>
                                     <overview>${basedir}/docs/javadoc/overview.html</overview>
                                     <quiet>true</quiet>
                                     <sourcepath>
                                         gremlin-core/src/main/java:gremlin-driver/src/main/java:gremlin-groovy/src/main/java:gremlin-python/src/main/java:gremlin-server/src/main/java:gremlin-test/src/main/java:hadoop-gremlin/src/main/java:neo4j-gremlin/src/main/java:spark-gremlin/src/main/java:tinkergraph-gremlin/src/main/java
                                     </sourcepath>
+                                    <includeDependencySources>true</includeDependencySources>
+                                    <dependencySourceIncludes>
+                                        <dependencySourceInclude>org.apache.tinkerpop:*</dependencySourceInclude>
+                                    </dependencySourceIncludes>
                                 </configuration>
                             </execution>
                             <execution>
@@ -1221,7 +1262,7 @@
                                 <inherited>false</inherited>
                                 <configuration>
                                     <destDir>core</destDir>
-                                    <additionalparam>-Xdoclint:none</additionalparam>
+                                    <additionalJOption>-Xdoclint:none</additionalJOption>
                                     <overview>${basedir}/docs/javadoc/overview.html</overview>
                                     <quiet>true</quiet>
                                     <sourcepath>
@@ -1302,8 +1343,8 @@
                                          build for the "full" javadocs -->
                                     <additionalDependencies>
                                         <additionalDependency>
-                                            <groupId>commons-configuration</groupId>
-                                            <artifactId>commons-configuration</artifactId>
+                                            <groupId>org.apache.commons</groupId>
+                                            <artifactId>commons-configuration2</artifactId>
                                             <version>${commons.configuration.version}</version>
                                         </additionalDependency>
                                         <additionalDependency>
@@ -1427,7 +1468,7 @@
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-surefire-plugin</artifactId>
                         <configuration>
-                            <argLine>-Dlog4j.configuration=${log4j-silent.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true
+                            <argLine>-Dlog4j.configuration=${log4j-silent.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true -Djava.net.preferIPv4Stack=true ${suresafeArgs}
                             </argLine>
                             <excludes>
                                 <exclude>**/*IntegrateTest.java</exclude>
@@ -1524,7 +1565,7 @@
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-surefire-plugin</artifactId>
                         <configuration>
-                            <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true ${surefireArgLine} -Djava.net.preferIPv4Stack=true
+                            <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dbuild.dir=${project.build.directory} -Dis.testing=true ${suresafeArgs} -Djava.net.preferIPv4Stack=true
                             </argLine>
                         </configuration>
                     </plugin>
@@ -1532,7 +1573,7 @@
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-failsafe-plugin</artifactId>
                         <configuration>
-                            <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dhost=localhost -Dport=8182 -Dbuild.dir=${project.build.directory} -Dis.testing=true ${failsafeArgLine} -Djava.net.preferIPv4Stack=true
+                            <argLine>-Dlog4j.configuration=${log4j-test.properties} -Dhost=localhost -Dport=8182 -Dbuild.dir=${project.build.directory} -Dis.testing=true ${suresafeArgs} -Djava.net.preferIPv4Stack=true
                             </argLine>
                         </configuration>
                     </plugin>
@@ -1540,7 +1581,7 @@
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-surefire-report-plugin</artifactId>
-                        <version>2.20</version>
+                        <version>2.22.2</version>
                         <executions>
                             <execution>
                                 <id>aggregate-surefire-report</id>
diff --git a/spark-gremlin/pom.xml b/spark-gremlin/pom.xml
index d8f2847..866ccec 100644
--- a/spark-gremlin/pom.xml
+++ b/spark-gremlin/pom.xml
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>spark-gremlin</artifactId>
     <name>Apache TinkerPop :: Spark Gremlin</name>
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>14.0.1</version>
+            <version>16.0.1</version>
         </dependency>
         <dependency>
             <groupId>org.apache.tinkerpop</groupId>
@@ -44,257 +44,133 @@
             <artifactId>hadoop-gremlin</artifactId>
             <version>${project.version}</version>
             <exclusions>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>javax.servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.sun.jersey</groupId>
-                    <artifactId>jersey-core</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.sun.jersey</groupId>
-                    <artifactId>jersey-server</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>commons-net</groupId>
-                    <artifactId>commons-net</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>commons-io</groupId>
-                    <artifactId>commons-io</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.google.guava</groupId>
-                    <artifactId>guava</artifactId>
-                </exclusion>
+                <!-- use our snappy as there is conflict within spark-->
                 <exclusion>
                     <groupId>org.xerial.snappy</groupId>
                     <artifactId>snappy-java</artifactId>
                 </exclusion>
+                <!-- use spark's avro -->
                 <exclusion>
                     <groupId>org.apache.avro</groupId>
                     <artifactId>avro</artifactId>
                 </exclusion>
+                <!-- use spark's math -->
                 <exclusion>
                     <groupId>org.apache.commons</groupId>
                     <artifactId>commons-math3</artifactId>
                 </exclusion>
-                <exclusion>
-                    <groupId>io.netty</groupId>
-                    <artifactId>netty</artifactId>
-                </exclusion>
+                <!-- use spark's netty 4-->
                 <exclusion>
                     <groupId>io.netty</groupId>
                     <artifactId>netty-all</artifactId>
                 </exclusion>
-                <exclusion>
-                    <groupId>com.thoughtworks.paranamer</groupId>
-                    <artifactId>paranamer</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <!-- SPARK -->
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_2.11</artifactId>
-            <version>${spark.version}</version>
-            <exclusions>
-                <!-- self conflicts -->
-                <exclusion>
-                    <groupId>org.scala-lang</groupId>
-                    <artifactId>scala-compiler</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.httpcomponents</groupId>
-                    <artifactId>httpclient</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.scala-lang.modules</groupId>
-                    <artifactId>scala-xml_2.11</artifactId>
-                </exclusion>
+                <!-- use spark's activation -->
                 <exclusion>
                     <groupId>javax.activation</groupId>
                     <artifactId>activation</artifactId>
                 </exclusion>
-                <exclusion>
-                    <groupId>org.codehaus.jackson</groupId>
-                    <artifactId>jackson-mapper-asl</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.codehaus.jackson</groupId>
-                    <artifactId>jackson-core-asl</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.scala-lang</groupId>
-                    <artifactId>scala-library</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-core</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-databind</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.scala-lang</groupId>
-                    <artifactId>scala-reflect</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.httpcomponents</groupId>
-                    <artifactId>httpcore</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-annotations</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.commons</groupId>
-                    <artifactId>commons-lang3</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>commons-lang</groupId>
-                    <artifactId>commons-lang</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>commons-codec</groupId>
-                    <artifactId>commons-codec</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.xerial.snappy</groupId>
-                    <artifactId>snappy-java</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.curator</groupId>
-                    <artifactId>curator-framework</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.curator</groupId>
-                    <artifactId>curator-recipes</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.thoughtworks.paranamer</groupId>
-                    <artifactId>paranamer</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>servlet-api</artifactId>
-                </exclusion>
-                <!-- gremlin-core conflicts -->
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-log4j12</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>jcl-over-slf4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.ivy</groupId>
-                    <artifactId>ivy</artifactId>
-                </exclusion>
-                <!-- gremlin-groovy conflicts -->
-                <exclusion>
-                    <groupId>jline</groupId>
-                    <artifactId>jline</artifactId>
-                </exclusion>
-                <!-- hadoop conflicts -->
-                <exclusion>
-                    <groupId>org.apache.hadoop</groupId>
-                    <artifactId>hadoop-client</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.curator</groupId>
-                    <artifactId>curator-client</artifactId>
-                </exclusion>
-                <!-- lgpl conflicts -->
-                <exclusion>
-                    <groupId>com.google.code.findbugs</groupId>
-                    <artifactId>jsr305</artifactId>
-                </exclusion>
+                <!-- use zookeeper's netty 3 -->
                 <exclusion>
                     <groupId>io.netty</groupId>
                     <artifactId>netty</artifactId>
                 </exclusion>
-                <exclusion>
-                    <groupId>io.netty</groupId>
-                    <artifactId>netty-all</artifactId>
-                </exclusion>
-                <!-- avro conflicts -->
+                <!-- use sparks commons-compress -->
                 <exclusion>
                     <groupId>org.apache.commons</groupId>
                     <artifactId>commons-compress</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
-        <!-- consistent dependencies -->
+        <!-- SPARK -->
         <dependency>
-            <groupId>org.scala-lang</groupId>
-            <artifactId>scala-library</artifactId>
-            <version>2.11.8</version>
-        </dependency>
-        <dependency>
-            <groupId>org.scala-lang.modules</groupId>
-            <artifactId>scala-xml_2.11</artifactId>
-            <version>1.0.5</version>
+            <groupId>org.apache.spark</groupId>
+            <artifactId>spark-core_2.12</artifactId>
+            <version>${spark.version}</version>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.hadoop</groupId>
+                    <artifactId>hadoop-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-databind</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.zookeeper</groupId>
+                    <artifactId>zookeeper</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.xerial.snappy</groupId>
+                    <artifactId>snappy</artifactId>
+                </exclusion>
+                <exclusion>
                     <groupId>org.scala-lang</groupId>
                     <artifactId>scala-library</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.xerial.snappy</groupId>
+                    <artifactId>snappy-java</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>jakarta.annotation</groupId>
+                    <artifactId>jakarta.annotation-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.commons</groupId>
+                    <artifactId>commons-text</artifactId>
+                </exclusion>
+                <!--
+                spark 3.0/scala 2.12 uses paranamer 2.8 and hadoop is stuck with an older version. without 2.8 you get
+                SPARK-14220
+                -->
+                <exclusion>
+                    <groupId>com.thoughtworks.paranamer</groupId>
+                    <artifactId>paranamer</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <version>2.6.7</version>
-        </dependency>
-        <dependency>
-            <groupId>commons-lang</groupId>
-            <artifactId>commons-lang</artifactId>
-            <version>${commons.lang.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.thoughtworks.paranamer</groupId>
-            <artifactId>paranamer</artifactId>
-            <version>2.6</version>
-        </dependency>
+        <!-- spark self-conflict and hadoop conflict -->
         <dependency>
             <groupId>org.xerial.snappy</groupId>
             <artifactId>snappy-java</artifactId>
-            <version>1.1.1.7</version>
+            <version>1.1.7.3</version>
         </dependency>
+        <!-- spark self-conflict and hadoop conflict -->
         <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-all</artifactId>
-            <version>4.1.32.Final</version>
+            <groupId>com.thoughtworks.paranamer</groupId>
+            <artifactId>paranamer</artifactId>
+            <version>2.8</version>
         </dependency>
+        <!-- spark self-conflict -->
         <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty</artifactId>
-            <version>3.9.9.Final</version>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+            <version>1.3.5</version>
         </dependency>
+        <!-- spark self-conflict -->
         <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-compress</artifactId>
-            <version>1.19</version>
+            <groupId>org.scala-lang</groupId>
+            <artifactId>scala-library</artifactId>
+            <version>2.12.10</version>
+        </dependency>
+        <!-- spark self-confict -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.10.0</version>
+        </dependency>
+        <!-- spark self-confict -->
+        <dependency>
+            <groupId>org.apache.zookeeper</groupId>
+            <artifactId>zookeeper</artifactId>
+            <version>3.4.6</version>
+            <exclusions>
+                <!-- use gremlin-groovy's jline -->
+                <exclusion>
+                    <groupId>jline</groupId>
+                    <artifactId>jline</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <!-- TEST -->
         <dependency>
@@ -302,16 +178,6 @@
             <artifactId>gremlin-test</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>com.google.guava</groupId>
-                    <artifactId>guava</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.objenesis</groupId>
-                    <artifactId>objenesis</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.tinkerpop</groupId>
@@ -393,7 +259,7 @@
                     <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.11:${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.12:${spark.version}
                             </Gremlin-Plugin-Dependencies>
                             <!-- deletes the servlet-api jar from the path after install - causes conflicts -->
                             <Gremlin-Plugin-Paths>servlet-api-2.5.jar=</Gremlin-Plugin-Paths>
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/MemoryAccumulator.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/MemoryAccumulator.java
index cf8cb25..fa72eb0 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/MemoryAccumulator.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/MemoryAccumulator.java
@@ -19,37 +19,58 @@
 
 package org.apache.tinkerpop.gremlin.spark.process.computer;
 
-import org.apache.spark.AccumulatorParam;
+import org.apache.spark.util.AccumulatorV2;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.ObjectWritable;
 import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
-public final class MemoryAccumulator<A> implements AccumulatorParam<ObjectWritable<A>> {
+public final class MemoryAccumulator<A> extends AccumulatorV2<ObjectWritable<A>, ObjectWritable<A>> {
 
     private final MemoryComputeKey<A> memoryComputeKey;
+    private ObjectWritable<A> value;
 
-    public MemoryAccumulator(final MemoryComputeKey<A> memoryComputeKey) {
+    MemoryAccumulator(final MemoryComputeKey<A> memoryComputeKey) {
+        this(memoryComputeKey, ObjectWritable.empty());
+    }
+
+    private MemoryAccumulator(final MemoryComputeKey<A> memoryComputeKey, final ObjectWritable<A> initial) {
         this.memoryComputeKey = memoryComputeKey;
+        this.value = initial;
     }
 
     @Override
-    public ObjectWritable<A> addAccumulator(final ObjectWritable<A> a, final ObjectWritable<A> b) {
-        if (a.isEmpty())
-            return b;
-        if (b.isEmpty())
-            return a;
-        return new ObjectWritable<>(this.memoryComputeKey.getReducer().apply(a.get(), b.get()));
+    public boolean isZero() {
+        return ObjectWritable.empty().equals(value);
     }
 
     @Override
-    public ObjectWritable<A> addInPlace(final ObjectWritable<A> a, final ObjectWritable<A> b) {
-        return this.addAccumulator(a, b);
+    public AccumulatorV2<ObjectWritable<A>, ObjectWritable<A>> copy() {
+        return new MemoryAccumulator<>(this.memoryComputeKey, this.value);
     }
 
     @Override
-    public ObjectWritable<A> zero(final ObjectWritable<A> a) {
-        return ObjectWritable.empty();
+    public void reset() {
+        this.value = ObjectWritable.empty();
+    }
+
+    @Override
+    public void add(final ObjectWritable<A> v) {
+        if (this.value.isEmpty())
+            this.value = v;
+        else if (!v.isEmpty())
+            this.value = new ObjectWritable<>(this.memoryComputeKey.getReducer().apply(value.get(), v.get()));
+    }
+
+    @Override
+    public void merge(final AccumulatorV2<ObjectWritable<A>, ObjectWritable<A>> other) {
+        this.add(other.value());
+    }
+
+    @Override
+    public ObjectWritable<A> value() {
+        return this.value;
     }
 }
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkExecutor.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkExecutor.java
index e9372d0..59b8c22 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkExecutor.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkExecutor.java
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.spark.process.computer;
 
 import org.apache.spark.api.java.Optional;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.spark.api.java.function.Function2;
 import org.apache.spark.api.java.function.PairFlatMapFunction;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkGraphComputer.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkGraphComputer.java
index 5184db6..d364b3d 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkGraphComputer.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkGraphComputer.java
@@ -18,9 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.spark.process.computer;
 
-import org.apache.commons.configuration.ConfigurationUtils;
-import org.apache.commons.configuration.FileConfiguration;
-import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration2.ConfigurationUtils;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
@@ -102,7 +101,7 @@
  */
 public final class SparkGraphComputer extends AbstractHadoopGraphComputer {
 
-    private final org.apache.commons.configuration.Configuration sparkConfiguration;
+    private final org.apache.commons.configuration2.Configuration sparkConfiguration;
     private boolean workersSet = false;
     private final ThreadFactory threadFactoryBoss = new BasicThreadFactory.Builder().namingPattern(SparkGraphComputer.class.getSimpleName() + "-boss").build();
 
@@ -251,7 +250,7 @@
             //////////////////////////////////////////////////
             //////////////////////////////////////////////////
             // apache and hadoop configurations that are used throughout the graph computer computation
-            final org.apache.commons.configuration.Configuration graphComputerConfiguration = new HadoopConfiguration(this.sparkConfiguration);
+            final org.apache.commons.configuration2.Configuration graphComputerConfiguration = new HadoopConfiguration(this.sparkConfiguration);
             if (!graphComputerConfiguration.containsKey(Constants.SPARK_SERIALIZER)) {
                 graphComputerConfiguration.setProperty(Constants.SPARK_SERIALIZER, KryoSerializer.class.getCanonicalName());
                 if (!graphComputerConfiguration.containsKey(Constants.SPARK_KRYO_REGISTRATOR))
@@ -541,7 +540,8 @@
     }
 
     public static void main(final String[] args) throws Exception {
-        final FileConfiguration configuration = new PropertiesConfiguration(args[0]);
+        final Configurations configs = new Configurations();
+        final org.apache.commons.configuration2.Configuration configuration = configs.properties(args[0]);
         new SparkGraphComputer(HadoopGraph.open(configuration)).program(VertexProgram.createVertexProgram(HadoopGraph.open(configuration), configuration)).submit().get();
     }
 }
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkMemory.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkMemory.java
index bf8590e..5a04162 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkMemory.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/SparkMemory.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.spark.process.computer;
 
-import org.apache.spark.Accumulator;
+import org.apache.spark.util.AccumulatorV2;
 import org.apache.spark.api.java.JavaSparkContext;
 import org.apache.spark.broadcast.Broadcast;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.ObjectWritable;
@@ -46,7 +46,7 @@
 public final class SparkMemory implements Memory.Admin, Serializable {
 
     public final Map<String, MemoryComputeKey> memoryComputeKeys = new HashMap<>();
-    private final Map<String, Accumulator<ObjectWritable>> sparkMemory = new HashMap<>();
+    private final Map<String, AccumulatorV2<ObjectWritable,ObjectWritable>> sparkMemory = new HashMap<>();
     private final AtomicInteger iteration = new AtomicInteger(0);
     private final AtomicLong runtime = new AtomicLong(0l);
     private Broadcast<Map<String, Object>> broadcast;
@@ -62,9 +62,9 @@
             this.memoryComputeKeys.put(mapReduce.getMemoryKey(), MemoryComputeKey.of(mapReduce.getMemoryKey(), Operator.assign, false, false));
         }
         for (final MemoryComputeKey memoryComputeKey : this.memoryComputeKeys.values()) {
-            this.sparkMemory.put(
-                    memoryComputeKey.getKey(),
-                    sparkContext.accumulator(ObjectWritable.empty(), memoryComputeKey.getKey(), new MemoryAccumulator<>(memoryComputeKey)));
+            final AccumulatorV2<ObjectWritable, ObjectWritable> accumulator = new MemoryAccumulator<>(memoryComputeKey);
+            JavaSparkContext.toSparkContext(sparkContext).register(accumulator, memoryComputeKey.getKey());
+            this.sparkMemory.put(memoryComputeKey.getKey(), accumulator);
         }
         this.broadcast = sparkContext.broadcast(Collections.emptyMap());
     }
@@ -135,8 +135,10 @@
         checkKeyValue(key, value);
         if (this.inExecute)
             throw Memory.Exceptions.memorySetOnlyDuringVertexProgramSetUpAndTerminate(key);
-        else
-            this.sparkMemory.get(key).setValue(new ObjectWritable<>(value));
+        else {
+            this.sparkMemory.get(key).reset();
+            this.sparkMemory.get(key).add(new ObjectWritable<>(value));
+        }
     }
 
     @Override
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java
index de42525..7eb12d4 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java
@@ -163,7 +163,7 @@
         final Step<?, ?> startStep = traversal.getStartStep();
         final Step<?, ?> endStep = traversal.getEndStep();
         // right now this is not supported because of how the SparkStarBarrierInterceptor mutates the traversal prior to local evaluation
-        if (traversal.getStrategies().toList().stream().filter(strategy -> strategy instanceof SubgraphStrategy).findAny().isPresent())
+        if (traversal.getStrategies().getStrategy(SubgraphStrategy.class).isPresent())
             return false;
         if (!startStep.getClass().equals(GraphStep.class) || ((GraphStep) startStep).returnsEdge())
             return false;
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 d9bfd68..697e649 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
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.SparkConf;
 import org.apache.spark.SparkContext;
 import org.apache.spark.rdd.RDD;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputFormatRDD.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputFormatRDD.java
index 9589497..eced132 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputFormatRDD.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputFormatRDD.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.io.NullWritable;
 import org.apache.hadoop.mapreduce.InputFormat;
 import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputHelper.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputHelper.java
index 444b10a..f0a0453 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputHelper.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputHelper.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopConfiguration;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDD.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDD.java
index a1f044c..b37672e 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDD.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDD.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.mapred.InputFormat;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.spark.api.java.JavaSparkContext;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputFormatRDD.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputFormatRDD.java
index fe848a0..3d169e4 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputFormatRDD.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputFormatRDD.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.io.NullWritable;
 import org.apache.hadoop.mapreduce.OutputFormat;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDD.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDD.java
index 3332b4d..666534f 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDD.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDD.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputRDD.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputRDD.java
index 00237db..0b6aa2d 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputRDD.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputRDD.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.spark.api.java.JavaRDD;
 import org.apache.spark.api.java.JavaSparkContext;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedOutputRDD.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedOutputRDD.java
index 6eb6673..5c76391 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedOutputRDD.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedOutputRDD.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.spark.storage.StorageLevel;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/SparkContextStorage.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/SparkContextStorage.java
index e02b159..4d72f70 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/SparkContextStorage.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/SparkContextStorage.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.hadoop.mapreduce.InputFormat;
 import org.apache.spark.SparkContext;
 import org.apache.spark.api.java.JavaSparkContext;
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 13fc787..d0e46da 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
@@ -198,8 +198,8 @@
         // the ordering of the existing entries in that constructor, since not all
         // of the entries are for TinkerPop (and the ordering is significant).
         try {
-            m.put(Class.forName("scala.reflect.ClassTag$$anon$1"), new JavaSerializer());
-            m.put(Class.forName("scala.reflect.ManifestFactory$$anon$1"), new JavaSerializer());
+            m.put(Class.forName("scala.reflect.ManifestFactory$AnyManifest"), new JavaSerializer());
+            m.put(Class.forName("scala.reflect.ClassTag$GenericClassTag"), new JavaSerializer());
             m.put(Class.forName("org.apache.spark.internal.io.FileCommitProtocol$TaskCommitMessage"), new JavaSerializer());
             m.put(Class.forName("org.apache.spark.internal.io.FileCommitProtocol$EmptyTaskCommitMessage$"), new JavaSerializer());
 
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 ec5ae9b..2dce832 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
@@ -20,8 +20,8 @@
 package org.apache.tinkerpop.gremlin.spark.structure.io.gryo;
 
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.SparkConf;
 import org.apache.spark.api.python.PythonBroadcast;
 import org.apache.spark.broadcast.TorrentBroadcast;
@@ -115,7 +115,6 @@
 
     private static Configuration makeApacheConfiguration(final SparkConf sparkConfiguration) {
         final BaseConfiguration apacheConfiguration = new BaseConfiguration();
-        apacheConfiguration.setDelimiterParsingDisabled(true);
         for (final Tuple2<String, String> tuple : sparkConfiguration.getAll()) {
             apacheConfiguration.setProperty(tuple._1(), tuple._2());
         }
@@ -139,8 +138,8 @@
                 super.register(GryoIo.class, TorrentBroadcast.class, null);
                 super.register(GryoIo.class, PythonBroadcast.class, null);
                 super.register(GryoIo.class, BoxedUnit.class, null);
-                super.register(GryoIo.class, Class.forName("scala.reflect.ClassTag$$anon$1"), new JavaSerializer());
-                super.register(GryoIo.class, Class.forName("scala.reflect.ManifestFactory$$anon$1"), new JavaSerializer());
+                super.register(GryoIo.class, Class.forName("scala.reflect.ManifestFactory$AnyManifest"), new JavaSerializer());
+                super.register(GryoIo.class, Class.forName("scala.reflect.ClassTag$GenericClassTag"), new JavaSerializer());
                 super.register(GryoIo.class, Class.forName("org.apache.spark.internal.io.FileCommitProtocol$TaskCommitMessage"), new JavaSerializer());
                 super.register(GryoIo.class, Class.forName("org.apache.spark.internal.io.FileCommitProtocol$EmptyTaskCommitMessage$"), new JavaSerializer());
                 super.register(GryoIo.class, Class.forName("scala.collection.immutable.Map$EmptyMap$"), new JavaSerializer());
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/kryoshim/unshaded/UnshadedKryoShimService.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/kryoshim/unshaded/UnshadedKryoShimService.java
index e1a4600..77cbf20 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/kryoshim/unshaded/UnshadedKryoShimService.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/kryoshim/unshaded/UnshadedKryoShimService.java
@@ -21,7 +21,7 @@
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.SparkConf;
 import org.apache.spark.serializer.KryoSerializer;
 import org.apache.tinkerpop.gremlin.spark.structure.Spark;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/AbstractSparkTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/AbstractSparkTest.java
index 2f3eb6f..f9ada20 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/AbstractSparkTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/AbstractSparkTest.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.spark;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.launcher.SparkLauncher;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
@@ -51,7 +51,6 @@
 
     protected Configuration getBaseConfiguration() {
         final BaseConfiguration configuration = new BaseConfiguration();
-        configuration.setDelimiterParsingDisabled(true);
         configuration.setProperty(SparkLauncher.SPARK_MASTER, "local[4]");
         configuration.setProperty(Constants.SPARK_SERIALIZER, GryoSerializer.class.getCanonicalName());
         configuration.setProperty(Constants.SPARK_KRYO_REGISTRATION_REQUIRED, true);
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/LocalPropertyTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/LocalPropertyTest.java
index c6b6e8a..829c405 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/LocalPropertyTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/LocalPropertyTest.java
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.spark.process.computer;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.SparkConf;
 import org.apache.spark.SparkContext;
 import org.apache.spark.api.java.JavaSparkContext;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkInterceptorStrategyTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkInterceptorStrategyTest.java
index 73d47db..b1d58a6 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkInterceptorStrategyTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkInterceptorStrategyTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.process.computer.traversal.strategy.optimization;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat;
@@ -69,9 +69,9 @@
         ///
         Graph graph = GraphFactory.open(configuration);
         GraphTraversalSource g = graph.traversal().withComputer().withoutStrategies(SparkSingleIterationStrategy.class);
-        assertFalse(g.getStrategies().toList().contains(SparkSingleIterationStrategy.instance()));
+        assertFalse(g.getStrategies().getStrategy(SparkSingleIterationStrategy.class).isPresent());
         assertFalse(g.V().count().explain().toString().contains(SparkSingleIterationStrategy.class.getSimpleName()));
-        assertTrue(g.getStrategies().toList().contains(SparkInterceptorStrategy.instance()));
+        assertTrue(g.getStrategies().getStrategy(SparkInterceptorStrategy.class).isPresent());
         assertTrue(g.V().count().explain().toString().contains(SparkInterceptorStrategy.class.getSimpleName()));
         /// groupCount(m)-test
         Traversal.Admin<Vertex, Long> traversal = g.V().groupCount("m").by(T.label).count().asAdmin();
@@ -97,9 +97,9 @@
         ///
         Graph graph = GraphFactory.open(configuration);
         GraphTraversalSource g = graph.traversal().withComputer().withoutStrategies(SparkSingleIterationStrategy.class);
-        assertFalse(g.getStrategies().toList().contains(SparkSingleIterationStrategy.instance()));
+        assertFalse(g.getStrategies().getStrategy(SparkSingleIterationStrategy.class).isPresent());
         assertFalse(g.V().count().explain().toString().contains(SparkSingleIterationStrategy.class.getSimpleName()));
-        assertTrue(g.getStrategies().toList().contains(SparkInterceptorStrategy.instance()));
+        assertTrue(g.getStrategies().getStrategy(SparkInterceptorStrategy.class).isPresent());
         assertTrue(g.V().count().explain().toString().contains(SparkInterceptorStrategy.class.getSimpleName()));
         /// SparkCountInterceptor matches
         test(SparkStarBarrierInterceptor.class, 6l, g.V().count());
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
index da63560..6202f33 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.process.computer.traversal.strategy.optimization;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat;
@@ -88,11 +88,11 @@
 
         Graph graph = GraphFactory.open(configuration);
         GraphTraversalSource g = graph.traversal().withComputer().withoutStrategies(SparkInterceptorStrategy.class, MessagePassingReductionStrategy.class);
-        assertFalse(g.getStrategies().toList().contains(SparkInterceptorStrategy.instance()));
+        assertFalse(g.getStrategies().getStrategy(SparkInterceptorStrategy.class).isPresent());
         assertFalse(g.V().count().explain().getStrategyTraversals().stream().filter(pair -> pair.getValue0() instanceof SparkInterceptorStrategy).findAny().isPresent());
-        assertFalse(g.getStrategies().toList().contains(MessagePassingReductionStrategy.instance()));
+        assertFalse(g.getStrategies().getStrategy(MessagePassingReductionStrategy.class).isPresent());
         assertFalse(g.V().count().explain().getStrategyTraversals().stream().filter(pair -> pair.getValue0() instanceof MessagePassingReductionStrategy).findAny().isPresent());
-        assertTrue(g.getStrategies().toList().contains(SparkSingleIterationStrategy.instance()));
+        assertTrue(g.getStrategies().getStrategy(SparkSingleIterationStrategy.class).isPresent());
         assertTrue(g.V().count().explain().getStrategyTraversals().stream().filter(pair -> pair.getValue0() instanceof SparkSingleIterationStrategy).findAny().isPresent());
 
         test(true, g.V().limit(10));
@@ -116,11 +116,11 @@
 
         graph = GraphFactory.open(configuration);
         g = graph.traversal().withComputer().withoutStrategies(SparkInterceptorStrategy.class).withStrategies(MessagePassingReductionStrategy.instance());
-        assertFalse(g.getStrategies().toList().contains(SparkInterceptorStrategy.instance()));
+        assertFalse(g.getStrategies().getStrategy(SparkInterceptorStrategy.class).isPresent());
         assertFalse(g.V().count().explain().getStrategyTraversals().stream().filter(pair -> pair.getValue0() instanceof SparkInterceptorStrategy).findAny().isPresent());
-        assertTrue(g.getStrategies().toList().contains(MessagePassingReductionStrategy.instance()));
+        assertTrue(g.getStrategies().getStrategy(MessagePassingReductionStrategy.class).isPresent());
         assertTrue(g.V().count().explain().getStrategyTraversals().stream().filter(pair -> pair.getValue0() instanceof MessagePassingReductionStrategy).findAny().isPresent());
-        assertTrue(g.getStrategies().toList().contains(SparkSingleIterationStrategy.instance()));
+        assertTrue(g.getStrategies().getStrategy(SparkSingleIterationStrategy.class).isPresent());
         assertTrue(g.V().count().explain().getStrategyTraversals().stream().filter(pair -> pair.getValue0() instanceof SparkSingleIterationStrategy).findAny().isPresent());
 
         test(true, g.V().limit(10));
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 539f67a..5aa78a4 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
@@ -19,8 +19,8 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.rdd.RDD;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleInputRDD.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleInputRDD.java
index 86c7610..7ca67a1 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleInputRDD.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleInputRDD.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.spark.api.java.JavaSparkContext;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleOutputRDD.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleOutputRDD.java
index ed36886..4ca0a69 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleOutputRDD.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ExampleOutputRDD.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputRDDTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputRDDTest.java
index e1098de..337b2b5 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputRDDTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputOutputRDDTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDDTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDDTest.java
index 8a8392a..11c4f48 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDDTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/InputRDDTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDDTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDDTest.java
index 617b268..7042a6c 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDDTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/OutputRDDTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputOutputRDDIntegrateTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputOutputRDDIntegrateTest.java
index 07f3223..f26efbc 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputOutputRDDIntegrateTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/PersistedInputOutputRDDIntegrateTest.java
@@ -19,8 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.storage.StorageLevel;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
@@ -28,7 +27,6 @@
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoOutputFormat;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
-import org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgram;
 import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankMapReduce;
 import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
@@ -38,9 +36,7 @@
 import org.apache.tinkerpop.gremlin.spark.process.computer.SparkHadoopGraphProvider;
 import org.apache.tinkerpop.gremlin.spark.structure.Spark;
 import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.io.IoCore;
 import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -208,86 +204,6 @@
     }
 
     @Test
-    public void testBulkLoaderVertexProgramChain() throws Exception {
-        Spark.create("local[4]");
-        final String rddName = TestHelper.makeTestDataDirectory(PersistedInputOutputRDDIntegrateTest.class, UUID.randomUUID().toString());
-        final Configuration readConfiguration = super.getBaseConfiguration();
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_GRAPH_READER, GryoInputFormat.class.getCanonicalName());
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_INPUT_LOCATION, SparkHadoopGraphProvider.PATHS.get("tinkerpop-modern-v3d0.kryo"));
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_GRAPH_WRITER, PersistedOutputRDD.class.getCanonicalName());
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, rddName);
-        readConfiguration.setProperty(Constants.GREMLIN_SPARK_PERSIST_CONTEXT, true);
-        Graph pageRankGraph = GraphFactory.open(readConfiguration);
-        ///////////////
-        final Configuration writeConfiguration = new BaseConfiguration();
-        writeConfiguration.setProperty(Graph.GRAPH, TinkerGraph.class.getCanonicalName());
-        writeConfiguration.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo");
-        writeConfiguration.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, TestHelper.makeTestDataFile(PersistedInputOutputRDDIntegrateTest.class, "testBulkLoaderVertexProgramChain.kryo"));
-        final Graph bulkLoaderGraph = pageRankGraph.compute(SparkGraphComputer.class).persist(GraphComputer.Persist.VERTEX_PROPERTIES).program(PageRankVertexProgram.build().create(pageRankGraph)).submit().get().graph();
-        bulkLoaderGraph.compute(SparkGraphComputer.class)
-                .persist(GraphComputer.Persist.NOTHING)
-                .workers(1)
-                .configure(Constants.GREMLIN_HADOOP_GRAPH_READER, PersistedInputRDD.class.getCanonicalName())
-                .configure(Constants.GREMLIN_HADOOP_INPUT_LOCATION, rddName)
-                .configure(Constants.GREMLIN_HADOOP_GRAPH_WRITER, null)
-                .configure(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, null)
-                .program(BulkLoaderVertexProgram.build().userSuppliedIds(true).writeGraph(writeConfiguration).create(bulkLoaderGraph))
-                .submit().get();
-        ////
-        assertTrue(Spark.hasRDD(Constants.getGraphLocation(rddName)));
-        assertEquals(1, Spark.getContext().getPersistentRDDs().size());
-        ////
-        final Graph graph = TinkerGraph.open();
-        final GraphTraversalSource g = graph.traversal();
-        graph.io(IoCore.gryo()).readGraph(TestHelper.makeTestDataFile(PersistedInputOutputRDDIntegrateTest.class, "testBulkLoaderVertexProgramChain.kryo"));
-        assertEquals(6l, g.V().count().next().longValue());
-        assertEquals(0l, g.E().count().next().longValue());
-        assertEquals("marko", g.V().has("name", "marko").values("name").next());
-        assertEquals(6l, g.V().values(PageRankVertexProgram.PAGE_RANK).count().next().longValue());
-        ////
-        Spark.close();
-    }
-
-    @Test
-    public void testBulkLoaderVertexProgramChainWithInputOutputHelperMapping() throws Exception {
-        Spark.create("local[4]");
-
-        final String rddName = TestHelper.makeTestDataDirectory(PersistedInputOutputRDDIntegrateTest.class, UUID.randomUUID().toString());
-        final Configuration readConfiguration = super.getBaseConfiguration();
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_GRAPH_READER, GryoInputFormat.class.getCanonicalName());
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_INPUT_LOCATION, SparkHadoopGraphProvider.PATHS.get("tinkerpop-modern-v3d0.kryo"));
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_GRAPH_WRITER, PersistedOutputRDD.class.getCanonicalName());
-        readConfiguration.setProperty(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, rddName);
-        readConfiguration.setProperty(Constants.GREMLIN_SPARK_PERSIST_CONTEXT, true);
-        Graph pageRankGraph = GraphFactory.open(readConfiguration);
-        ///////////////
-        final Configuration writeConfiguration = new BaseConfiguration();
-        writeConfiguration.setProperty(Graph.GRAPH, TinkerGraph.class.getCanonicalName());
-        writeConfiguration.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo");
-        writeConfiguration.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, TestHelper.makeTestDataFile(PersistedInputOutputRDDIntegrateTest.class, "testBulkLoaderVertexProgramChainWithInputOutputHelperMapping.kryo"));
-        final Graph bulkLoaderGraph = pageRankGraph.compute(SparkGraphComputer.class).persist(GraphComputer.Persist.EDGES).program(PageRankVertexProgram.build().create(pageRankGraph)).submit().get().graph();
-        bulkLoaderGraph.compute(SparkGraphComputer.class)
-                .persist(GraphComputer.Persist.NOTHING)
-                .workers(1)
-                .program(BulkLoaderVertexProgram.build().userSuppliedIds(true).writeGraph(writeConfiguration).create(bulkLoaderGraph))
-                .submit().get();
-        ////
-        Spark.create(readConfiguration);
-        assertTrue(Spark.hasRDD(Constants.getGraphLocation(rddName)));
-        assertEquals(1, Spark.getContext().getPersistentRDDs().size());
-        ////
-        final Graph graph = TinkerGraph.open();
-        final GraphTraversalSource g = graph.traversal();
-        graph.io(IoCore.gryo()).readGraph(TestHelper.makeTestDataFile(PersistedInputOutputRDDIntegrateTest.class, "testBulkLoaderVertexProgramChainWithInputOutputHelperMapping.kryo"));
-        assertEquals(6l, g.V().count().next().longValue());
-        assertEquals(6l, g.E().count().next().longValue());
-        assertEquals("marko", g.V().has("name", "marko").values("name").next());
-        assertEquals(6l, g.V().values(PageRankVertexProgram.PAGE_RANK).count().next().longValue());
-        ////
-        Spark.close();
-    }
-
-    @Test
     public void testComplexChain() throws Exception {
         Spark.create("local[4]");
 
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ToyGraphInputRDD.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ToyGraphInputRDD.java
index 90764ce..d167756 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ToyGraphInputRDD.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/ToyGraphInputRDD.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.spark.api.java.JavaPairRDD;
 import org.apache.spark.api.java.JavaSparkContext;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializerIntegrateTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializerIntegrateTest.java
index c3ac83f..c3a01fb 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializerIntegrateTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/io/gryo/GryoSerializerIntegrateTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.spark.structure.io.gryo;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat;
diff --git a/sparql-gremlin/pom.xml b/sparql-gremlin/pom.xml
index 78f58c0..6818036 100644
--- a/sparql-gremlin/pom.xml
+++ b/sparql-gremlin/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>sparql-gremlin</artifactId>
     <name>Apache TinkerPop :: SPARQL Gremlin</name>
@@ -41,7 +41,7 @@
         </dependency>
         <dependency>
             <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
+            <artifactId>hamcrest</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java
index 1dbb173..62e9647 100644
--- a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java
+++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java
@@ -218,7 +218,7 @@
 
                 // by default, the sort will be ascending. getDirection() returns -2 if the DESC/ASC isn't
                 // supplied - weird
-                orderingIndex.put(expr.getVarName(), sortCondition.getDirection() == -1 ? Order.decr : Order.incr);
+                orderingIndex.put(expr.getVarName(), sortCondition.getDirection() == -1 ? Order.desc : Order.asc);
             }
         }
 
diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/dsl/sparql/SparqlTraversalSource.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/dsl/sparql/SparqlTraversalSource.java
index 79812bb..bb8d70b 100644
--- a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/dsl/sparql/SparqlTraversalSource.java
+++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/dsl/sparql/SparqlTraversalSource.java
@@ -18,12 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.sparql.process.traversal.dsl.sparql;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.strategy.decoration.RemoteStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
@@ -33,9 +30,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
 import org.apache.tinkerpop.gremlin.sparql.process.traversal.strategy.SparqlStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Transaction;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
@@ -174,21 +168,6 @@
         return (SparqlTraversalSource) super.withoutStrategies(traversalStrategyClasses);
     }
 
-    @Override
-    public SparqlTraversalSource withRemote(final Configuration conf) {
-        return (SparqlTraversalSource) super.withRemote(conf);
-    }
-
-    @Override
-    public SparqlTraversalSource withRemote(final String configFile) throws Exception {
-        return (SparqlTraversalSource) super.withRemote(configFile);
-    }
-
-    @Override
-    public SparqlTraversalSource withRemote(final RemoteConnection connection) {
-        return (SparqlTraversalSource) super.withRemote(connection);
-    }
-
     /**
      * The start step for a SPARQL based traversal that accepts a string representation of the query to execute.
      */
diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java
index 7a62e31..a4a95cc 100644
--- a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java
+++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java
@@ -65,7 +65,7 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!(traversal.getParent() instanceof EmptyStep))
+        if (!(traversal.isRoot()))
             return;
 
         // assumes that the traversal starts with the single inject step that holds the sparql query
diff --git a/tinkergraph-gremlin/pom.xml b/tinkergraph-gremlin/pom.xml
index 7c09296..7d19fdd 100644
--- a/tinkergraph-gremlin/pom.xml
+++ b/tinkergraph-gremlin/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.4.9-SNAPSHOT</version>
+        <version>3.5.0-SNAPSHOT</version>
     </parent>
     <artifactId>tinkergraph-gremlin</artifactId>
     <name>Apache TinkerPop :: TinkerGraph Gremlin</name>
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
index 3e49c34..dd993c1 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
@@ -66,7 +66,7 @@
                 final MessageScope.Local<M> localMessageScope = (MessageScope.Local<M>) messageScope;
                 final Traversal.Admin<Vertex, Edge> incidentTraversal = TinkerMessenger.setVertexStart(localMessageScope.getIncidentTraversal().get().asAdmin(), this.vertex);
                 final Direction direction = TinkerMessenger.getDirection(incidentTraversal);
-                final Edge[] edge = new Edge[1]; // simulates storage side-effects available in Gremlin, but not Java8 streams
+                final Edge[] edge = new Edge[1]; // simulates storage side-effects available in Gremlin, but not Java streams
                 multiIterator.addIterator(StreamSupport.stream(Spliterators.spliteratorUnknownSize(VertexProgramHelper.reverse(incidentTraversal.asAdmin()), Spliterator.IMMUTABLE | Spliterator.SIZED), false)
                         .map((Edge e) -> {
                             edge[0] = e;
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphCountStrategy.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphCountStrategy.java
index 55e6b55..53b3eca 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphCountStrategy.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphCountStrategy.java
@@ -25,9 +25,8 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
@@ -61,7 +60,7 @@
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!(traversal.getParent() instanceof EmptyStep) || TraversalHelper.onGraphComputer(traversal))
+        if (!(traversal.isRoot()) || TraversalHelper.onGraphComputer(traversal))
             return;
         final List<Step> steps = traversal.getSteps();
         if (steps.size() < 2 ||
@@ -76,7 +75,7 @@
                     current instanceof NoOpBarrierStep ||
                     current instanceof CollectingBarrierStep) ||
                     (current instanceof TraversalParent &&
-                            TraversalHelper.anyStepRecursively(s -> (s instanceof SideEffectStep || s instanceof AggregateStep), (TraversalParent) current)))
+                            TraversalHelper.anyStepRecursively(s -> (s instanceof SideEffectStep || s instanceof AggregateGlobalStep), (TraversalParent) current)))
                 return;
         }
         final Class<? extends Element> elementClass = ((GraphStep<?, ?>) steps.get(0)).getReturnClass();
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerEdge.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerEdge.java
index bcfe485..02f7ede 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerEdge.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerEdge.java
@@ -43,11 +43,13 @@
     protected Map<String, Property> properties;
     protected final Vertex inVertex;
     protected final Vertex outVertex;
+    private final boolean allowNullPropertyValues;
 
     protected TinkerEdge(final Object id, final Vertex outVertex, final String label, final Vertex inVertex) {
         super(id, label);
         this.outVertex = outVertex;
         this.inVertex = inVertex;
+        this.allowNullPropertyValues = outVertex.graph().features().edge().supportsNullPropertyValues();
         TinkerHelper.autoUpdateIndex(this, T.label.getAccessor(), this.label, null);
     }
 
@@ -55,6 +57,12 @@
     public <V> Property<V> property(final String key, final V value) {
         if (this.removed) throw elementAlreadyRemoved(Edge.class, id);
         ElementHelper.validateProperty(key, value);
+
+        if (!allowNullPropertyValues && null == value) {
+            properties(key).forEachRemaining(Property::remove);
+            return Property.empty();
+        }
+
         final Property oldProperty = super.property(key);
         final Property<V> newProperty = new TinkerProperty<>(this, key, value);
         if (null == this.properties) this.properties = new HashMap<>();
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java
index 6c0f1b2..61cc7a8 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
index 5dbc311..6f4f821 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -83,6 +83,7 @@
     public static final String GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY = "gremlin.tinkergraph.defaultVertexPropertyCardinality";
     public static final String GREMLIN_TINKERGRAPH_GRAPH_LOCATION = "gremlin.tinkergraph.graphLocation";
     public static final String GREMLIN_TINKERGRAPH_GRAPH_FORMAT = "gremlin.tinkergraph.graphFormat";
+    public static final String GREMLIN_TINKERGRAPH_ALLOW_NULL_PROPERTY_VALUES = "gremlin.tinkergraph.allowNullPropertyValues";
 
     private final TinkerGraphFeatures features = new TinkerGraphFeatures();
 
@@ -99,6 +100,7 @@
     protected final IdManager<?> edgeIdManager;
     protected final IdManager<?> vertexPropertyIdManager;
     protected final VertexProperty.Cardinality defaultVertexPropertyCardinality;
+    protected final boolean allowNullPropertyValues;
 
     private final Configuration configuration;
     private final String graphLocation;
@@ -114,6 +116,7 @@
         vertexPropertyIdManager = selectIdManager(configuration, GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, VertexProperty.class);
         defaultVertexPropertyCardinality = VertexProperty.Cardinality.valueOf(
                 configuration.getString(GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.single.name()));
+        allowNullPropertyValues = configuration.getBoolean(GREMLIN_TINKERGRAPH_ALLOW_NULL_PROPERTY_VALUES, false);
 
         graphLocation = configuration.getString(GREMLIN_TINKERGRAPH_GRAPH_LOCATION, null);
         graphFormat = configuration.getString(GREMLIN_TINKERGRAPH_GRAPH_FORMAT, null);
@@ -385,6 +388,11 @@
         }
 
         @Override
+        public boolean supportsNullPropertyValues() {
+            return allowNullPropertyValues;
+        }
+
+        @Override
         public Features.VertexPropertyFeatures properties() {
             return vertexPropertyFeatures;
         }
@@ -411,6 +419,11 @@
         }
 
         @Override
+        public boolean supportsNullPropertyValues() {
+            return allowNullPropertyValues;
+        }
+
+        @Override
         public boolean supportsCustomIds() {
             return false;
         }
@@ -449,6 +462,11 @@
         }
 
         @Override
+        public boolean supportsNullPropertyValues() {
+            return allowNullPropertyValues;
+        }
+
+        @Override
         public boolean supportsCustomIds() {
             return false;
         }
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndex.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndex.java
index f5872cf..75924da 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndex.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndex.java
@@ -49,7 +49,7 @@
     protected void put(final String key, final Object value, final T element) {
         Map<Object, Set<T>> keyMap = this.index.get(key);
         if (null == keyMap) {
-            this.index.putIfAbsent(key, new ConcurrentHashMap<Object, Set<T>>());
+            this.index.putIfAbsent(key, new ConcurrentHashMap<>());
             keyMap = this.index.get(key);
         }
         Set<T> objects = keyMap.get(value);
@@ -65,7 +65,7 @@
         if (null == keyMap) {
             return Collections.emptyList();
         } else {
-            Set<T> set = keyMap.get(value);
+            Set<T> set = keyMap.get(indexable(value));
             if (null == set)
                 return Collections.emptyList();
             else
@@ -78,7 +78,7 @@
         if (null == keyMap) {
             return 0;
         } else {
-            Set<T> set = keyMap.get(value);
+            final Set<T> set = keyMap.get(indexable(value));
             if (null == set)
                 return 0;
             else
@@ -89,7 +89,7 @@
     public void remove(final String key, final Object value, final T element) {
         final Map<Object, Set<T>> keyMap = this.index.get(key);
         if (null != keyMap) {
-            Set<T> objects = keyMap.get(value);
+            final Set<T> objects = keyMap.get(indexable(value));
             if (null != objects) {
                 objects.remove(element);
                 if (objects.size() == 0) {
@@ -111,17 +111,11 @@
 
     public void autoUpdate(final String key, final Object newValue, final Object oldValue, final T element) {
         if (this.indexedKeys.contains(key)) {
-            if (oldValue != null)
-                this.remove(key, oldValue, element);
+            this.remove(key, oldValue, element);
             this.put(key, newValue, element);
         }
     }
 
-    public void autoRemove(final String key, final Object oldValue, final T element) {
-        if (this.indexedKeys.contains(key))
-            this.remove(key, oldValue, element);
-    }
-
     public void createKeyIndex(final String key) {
         if (null == key)
             throw Graph.Exceptions.argumentCanNotBeNull("key");
@@ -133,8 +127,8 @@
         this.indexedKeys.add(key);
 
         (Vertex.class.isAssignableFrom(this.indexClass) ?
-                this.graph.vertices.values().<T>parallelStream() :
-                this.graph.edges.values().<T>parallelStream())
+                this.graph.vertices.values().parallelStream() :
+                this.graph.edges.values().parallelStream())
                 .map(e -> new Object[]{((T) e).property(key), e})
                 .filter(a -> ((Property) a[0]).isPresent())
                 .forEach(a -> this.put(key, ((Property) a[0]).value(), (T) a[1]));
@@ -147,7 +141,35 @@
         this.indexedKeys.remove(key);
     }
 
+    /**
+     * Provides a way for an index to have a {@code null} value as {@code ConcurrentHashMap} will not allow a
+     * {@code null} key.
+     */
+    public static Object indexable(final Object obj) {
+        return null == obj ? IndexedNull.instance() : obj;
+    }
+
     public Set<String> getIndexedKeys() {
         return this.indexedKeys;
     }
+
+    public static final class IndexedNull {
+        private static final IndexedNull inst = new IndexedNull();
+
+        private IndexedNull() {}
+
+        static IndexedNull instance() {
+            return inst;
+        }
+
+        @Override
+        public int hashCode() {
+            return 751912123;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            return o instanceof IndexedNull;
+        }
+    }
 }
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java
index d15a4a7..e2140b1 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
index 18fd549..e6f59c9 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV3d0.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV3d0.java
index c62d179..6ee68ee 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV3d0.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV3d0.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerProperty.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerProperty.java
index 0f7077b..db40346 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerProperty.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerProperty.java
@@ -54,9 +54,12 @@
         return this.value;
     }
 
+    /**
+     * The existence of this object implies the property is present, thus even a {@code null} value means "present".
+     */
     @Override
     public boolean isPresent() {
-        return null != this.value;
+        return true;
     }
 
     @Override
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
index be08137..1765054 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
@@ -46,10 +46,12 @@
     protected Map<String, Set<Edge>> outEdges;
     protected Map<String, Set<Edge>> inEdges;
     private final TinkerGraph graph;
+    private boolean allowNullPropertyValues;
 
     protected TinkerVertex(final Object id, final String label, final TinkerGraph graph) {
         super(id, label);
         this.graph = graph;
+        this.allowNullPropertyValues = graph.features().vertex().supportsNullPropertyValues();
     }
 
     @Override
@@ -85,6 +87,16 @@
         if (this.removed) throw elementAlreadyRemoved(Vertex.class, id);
         ElementHelper.legalPropertyKeyValueArray(keyValues);
         ElementHelper.validateProperty(key, value);
+
+        // if we don't allow null property values and the value is null then the key can be removed but only if the
+        // cardinality is single. if it is list/set then we can just ignore the null.
+        if (!allowNullPropertyValues && null == value) {
+            final VertexProperty.Cardinality card = null == cardinality ? graph.features().vertex().getCardinality(key) : cardinality;
+            if (VertexProperty.Cardinality.single == card)
+                properties(key).forEachRemaining(VertexProperty::remove);
+            return VertexProperty.empty();
+        }
+
         final Optional<Object> optionalId = ElementHelper.getIdValue(keyValues);
         final Optional<VertexProperty<V>> optionalVertexProperty = ElementHelper.stageVertexProperty(this, cardinality, key, value, keyValues);
         if (optionalVertexProperty.isPresent()) return optionalVertexProperty.get();
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertexProperty.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertexProperty.java
index 3ca871a..f2635df 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertexProperty.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertexProperty.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -45,6 +44,7 @@
     private final TinkerVertex vertex;
     private final String key;
     private final V value;
+    private final boolean allowNullPropertyValues;
 
     /**
      * This constructor will not validate the ID type against the {@link Graph}.  It will always just use a
@@ -52,12 +52,7 @@
      * with {@link TinkerGraphComputerView}.
      */
     public TinkerVertexProperty(final TinkerVertex vertex, final String key, final V value, final Object... propertyKeyValues) {
-        super(((TinkerGraph) vertex.graph()).vertexPropertyIdManager.getNextId((TinkerGraph) vertex.graph()), key);
-        this.vertex = vertex;
-        this.key = key;
-        this.value = value;
-        ElementHelper.legalPropertyKeyValueArray(propertyKeyValues);
-        ElementHelper.attachProperties(this, propertyKeyValues);
+        this(((TinkerGraph) vertex.graph()).vertexPropertyIdManager.getNextId((TinkerGraph) vertex.graph()), vertex, key, value, propertyKeyValues);
     }
 
     /**
@@ -66,6 +61,10 @@
      */
     public TinkerVertexProperty(final Object id, final TinkerVertex vertex, final String key, final V value, final Object... propertyKeyValues) {
         super(id, key);
+        this.allowNullPropertyValues = vertex.graph().features().vertex().properties().supportsNullPropertyValues();
+        if (!allowNullPropertyValues && null == value)
+            throw new IllegalArgumentException("value cannot be null as feature supportsNullPropertyValues is false");
+
         this.vertex = vertex;
         this.key = key;
         this.value = value;
@@ -117,6 +116,12 @@
     @Override
     public <U> Property<U> property(final String key, final U value) {
         if (this.removed) throw elementAlreadyRemoved(VertexProperty.class, id);
+
+        if ((!allowNullPropertyValues && null == value)) {
+            properties(key).forEachRemaining(Property::remove);
+            return Property.empty();
+        }
+
         final Property<U> property = new TinkerProperty<>(this, key, value);
         if (this.properties == null) this.properties = new HashMap<>();
         this.properties.put(key, property);
@@ -138,7 +143,8 @@
             }
             final AtomicBoolean delete = new AtomicBoolean(true);
             this.vertex.properties(this.key).forEachRemaining(property -> {
-                if (property.value().equals(this.value))
+                final Object currentPropertyValue = property.value();
+                if ((currentPropertyValue != null && currentPropertyValue.equals(this.value) || null == currentPropertyValue && null == this.value))
                     delete.set(false);
             });
             if (delete.get()) TinkerHelper.removeIndex(this.vertex, this.key, this.value);
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java
index 0efd240..3254aa1 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph;
 
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.AbstractGraphProvider;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.TestHelper;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphComputerProvider.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphComputerProvider.java
index 0efc37a..6121ef7 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphComputerProvider.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphComputerProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.process;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.GraphProvider;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/HaltedTraverserStrategyTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/HaltedTraverserStrategyTest.java
index 288b4b4..a769f4a 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/HaltedTraverserStrategyTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/HaltedTraverserStrategyTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.strategy.decoration;
 
-import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java
index ce39953..32a77f2 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java
@@ -21,7 +21,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ScalarMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
@@ -54,7 +54,7 @@
 
     private static void assertOptions(final GraphTraversalSource optionedG) {
         GraphTraversal t = optionedG.inject(1);
-        t = t.asAdmin().addStep(new MapStep<Object, Object>(t.asAdmin()) {
+        t = t.asAdmin().addStep(new ScalarMapStep<Object, Object>(t.asAdmin()) {
             @Override
             protected Object map(final Traverser.Admin<Object> traverser) {
                 final OptionsStrategy strategy = traversal.asAdmin().getStrategies().getStrategy(OptionsStrategy.class).get();
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java
index f02de1c..e589c5c 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index f4a0a0a..0791b16 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -22,6 +22,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.ConsoleMutationListener;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
@@ -269,10 +270,9 @@
     }
 
     @Test
-    @Ignore
     public void testBugs() {
         GraphTraversalSource g = TinkerFactory.createModern().traversal();
-
+        Object o1 = g.V().map(__.V(1));
         System.out.println(g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b").explain());
         System.out.println(g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b").toList());
 
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
index a2208f5..555c7ca 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.tinkerpop.gremlin.GraphHelper;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
@@ -27,7 +27,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
 import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.Edge;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/graphson/AbstractTinkerGraphGraphSONTranslatorProvider.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/graphson/AbstractTinkerGraphGraphSONTranslatorProvider.java
index 4d4ee00..7f4ebe8 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/graphson/AbstractTinkerGraphGraphSONTranslatorProvider.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/graphson/AbstractTinkerGraphGraphSONTranslatorProvider.java
@@ -213,10 +213,6 @@
         method = "shouldNeverPropagateANoBulkTraverser",
         reason = "Reason requires investigation")
 @Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.CoreTraversalTest",
-        method = "shouldNeverPropagateANullValuedTraverser",
-        reason = "Reason requires investigation")
-@Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
         method = "*",
         reason = "read and write tests don't translate locally well because of calling iterate() inside read()/write() add a none()")
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/gryo/TinkerGraphGryoTranslatorProvider.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/gryo/TinkerGraphGryoTranslatorProvider.java
index d6d93a0..0d30df9 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/gryo/TinkerGraphGryoTranslatorProvider.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/io/gryo/TinkerGraphGryoTranslatorProvider.java
@@ -209,10 +209,6 @@
         method = "shouldNeverPropagateANoBulkTraverser",
         reason = "Reason requires investigation")
 @Graph.OptOut(
-        test = "org.apache.tinkerpop.gremlin.process.traversal.CoreTraversalTest",
-        method = "shouldNeverPropagateANullValuedTraverser",
-        reason = "Reason requires investigation")
-@Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
         method = "*",
         reason = "read and write tests don't translate locally well because of calling iterate() inside read()/write() add a none()")